diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..96c5d6b --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,94 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +PR Agent is an AI-powered pull request analyzer available as both a CLI tool and a GitHub Action. It analyzes code changes using multiple AI providers (Anthropic Claude, OpenAI GPT, Google Gemini) and provides summaries, risk detection, complexity scoring, and architecture-aware recommendations. + +## Build & Development Commands + +```bash +# Install dependencies (--legacy-peer-deps required for LangChain peer dependency conflicts) +npm install --legacy-peer-deps + +# Build everything (TypeScript + GitHub Action bundle) +npm run build + +# Build TypeScript only +npm run build:tsc + +# Build GitHub Action only (uses @vercel/ncc) +npm run build:action + +# Clean and rebuild +npm run build:clean + +# Run tests +npm test +npm test -- --watch # Watch mode +npm test -- --coverage # With coverage + +# Run single test file +npm test -- tests/config-loader.test.ts + +# Development mode (no build needed) +npm run dev + +# Run CLI from built dist +npm run cli +``` + +## Architecture + +The project follows a modular monolith pattern with four layers: + +### Entry Points +- `src/cli/index.ts` - CLI entry point using Commander.js +- `src/action.ts` - GitHub Action entry point +- `src/index.ts` - Probot app integration + +### Core Analysis Engine +- `src/agents/pr-analyzer-agent.ts` - Main LangChain-based analysis workflow +- `src/agents/base-pr-agent-workflow.ts` - LangGraph workflow orchestration + +### AI Provider Layer +- `src/providers/` - Provider implementations (Anthropic, OpenAI, Google) +- `src/providers/provider.factory.ts` - Factory pattern for instantiation +- `src/providers/provider.interface.ts` - Common interface all providers implement + +### Tools & Utilities +- `src/tools/pr-analysis-tools.ts` - Diff parsing and analysis tools +- `src/utils/arch-docs-parser.ts` - Parse `.arch-docs` documentation folder +- `src/utils/arch-docs-rag.ts` - RAG (Retrieval-Augmented Generation) for architecture context +- `src/utils/branch-resolver.ts` - Git branch detection and resolution +- `src/cli/utils/config-loader.ts` - Configuration file management + +### Data Flow +``` +User Input → CLI/Action Interface → Config Loader → PRAnalyzerAgent + → Parse Diff → Load Architecture Docs (optional) → Build RAG Context + → Provider Factory → AI Provider → Structured Analysis Results + → Format Output (CLI terminal or GitHub PR comment) +``` + +## Key Configuration Files + +- `.pragent.config.json` - User configuration (AI provider, model, API keys, analysis settings) +- `.pr-analyzer.yml` - GitHub Action configuration +- `action.yml` - GitHub Action manifest + +## Technology Stack + +- **Framework**: TypeScript/Node.js (ES Modules), requires Node.js >=18.0.0 +- **AI Orchestration**: LangChain v1.x with LangGraph for workflow management +- **CLI Framework**: Commander.js with Inquirer for interactive prompts +- **Testing**: Jest with ts-jest +- **Action Bundling**: @vercel/ncc bundles the GitHub Action into a single file + +## Important Notes + +- Large diffs (>50KB) automatically use agent-based chunking (configurable via `analysis.agentThreshold`) +- The GitHub Action bundle in `dist/` must be committed after changes to action code +- Environment variables `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, or `GOOGLE_API_KEY` can be used instead of config file +- Default branch detection uses: config file → GitHub API → git commands → fallback to `origin/main` diff --git a/README.md b/README.md index 2d8bfca..a6bdb3f 100644 --- a/README.md +++ b/README.md @@ -12,18 +12,20 @@ PR Agent analyzes your code changes and provides: - **Complexity Rating**: A 1-5 scale rating of complexity with file-level breakdown - **Actionable Insights**: Specific recommendations based on your codebase - **Architecture-Aware Analysis**: Leverages your `.arch-docs` for context-aware reviews +- **Peer Review Integration**: Validates PRs against linked Jira tickets and acceptance criteria - **Static Analysis**: Semgrep integration for security vulnerabilities and code quality issues ## Features -✨ **Intelligent Agent Mode** - Automatically handles large diffs without chunking -🏗️ **Architecture Documentation Integration** - Uses `.arch-docs` for smarter analysis -🔬 **Static Analysis Integration** - Semgrep-powered security and code quality scanning -🔌 **Multiple AI Providers** - Anthropic Claude, OpenAI GPT, Google Gemini -🖥️ **CLI & GitHub Action** - Use locally or in CI/CD pipelines -📊 **File-Level Analysis** - Individual risk and complexity scores per file -🌐 **Language-Aware** - Supports TypeScript, JavaScript, Python, Java, Go, Rust, and more -⚙️ **Configurable** - Customize models, providers, and analysis modes +✨ **Intelligent Agent Mode** - Automatically handles large diffs without chunking +🏗️ **Architecture Documentation Integration** - Uses `.arch-docs` for smarter analysis +🔬 **Static Analysis Integration** - Semgrep-powered security and code quality scanning +🔌 **Multiple AI Providers** - Anthropic Claude, OpenAI GPT, Google Gemini, Zhipu AI +🖥️ **CLI & GitHub Action** - Use locally or in CI/CD pipelines +📊 **File-Level Analysis** - Individual risk and complexity scores per file +🎫 **Peer Review Integration** - Validates against Jira tickets and acceptance criteria +🌐 **Language-Aware** - Supports TypeScript, JavaScript, Python, Java, Go, Rust, and more +⚙️ **Configurable** - Customize models, providers, and analysis modes 🎨 **Unified Output Format** - Semgrep and AI findings use consistent formatting, sorted by severity ## Quick Reference @@ -59,6 +61,7 @@ pr-agent help # Show help - [Configuration](#configuration) - [Architecture Documentation Integration](#architecture-documentation-integration) - [Static Analysis Integration](#static-analysis-integration) +- [Peer Review Integration](#peer-review-integration) - [GitHub Action Usage](#github-action-usage) - [Supported AI Models](#supported-ai-models) - [Common Use Cases](#common-use-cases) @@ -75,6 +78,7 @@ Before using PR Agent, you'll need: - **Anthropic Claude**: Sign up at [Anthropic Console](https://console.anthropic.com/) (Recommended) - **OpenAI GPT**: Get your key from [OpenAI Platform](https://platform.openai.com/) - **Google Gemini**: Get your key from [Google AI Studio](https://makersuite.google.com/) + - **Zhipu AI**: Get your key from [Zhipu AI Platform](https://open.bigmodel.cn/) (Anthropic-compatible API) 2. **For GitHub Action**: Repository with permissions to add workflows and secrets @@ -173,6 +177,7 @@ pr-agent analyze --complexity pr-agent analyze --provider anthropic pr-agent analyze --provider openai pr-agent analyze --provider google +pr-agent analyze --provider zhipu # Use specific model pr-agent analyze --provider anthropic --model claude-sonnet-4-5-20250929 @@ -241,7 +246,8 @@ pr-agent config --reset "apiKeys": { "anthropic": "sk-ant-...", "openai": "", - "google": "" + "google": "", + "zhipu": "" }, "analysis": { "defaultMode": "full", @@ -265,6 +271,14 @@ pr-agent config --reset "verbose": false, "showStrategy": true, "showRecommendations": true + }, + "peerReview": { + "enabled": false, + "provider": "jira", + "instanceUrl": "https://your-company.atlassian.net", + "email": "your-email@company.com", + "apiToken": "your-jira-api-token", + "defaultProject": "PROJ" } } ``` @@ -282,6 +296,9 @@ export OPENAI_API_KEY="sk-..." # Google Gemini export GOOGLE_API_KEY="..." + +# Zhipu AI +export ZHIPU_API_KEY="..." ``` Add to your `.bashrc`, `.zshrc`, or `.env` file for persistence. @@ -512,12 +529,151 @@ Key insights from arch-docs integration: ### Benefits of Arch-Docs Integration -✅ **Context-Aware Analysis** - AI understands your specific architecture -✅ **Pattern Enforcement** - Detects violations of documented patterns -✅ **Security Alignment** - Checks against your security guidelines -✅ **Consistency** - Ensures PRs follow established conventions +✅ **Context-Aware Analysis** - AI understands your specific architecture +✅ **Pattern Enforcement** - Detects violations of documented patterns +✅ **Security Alignment** - Checks against your security guidelines +✅ **Consistency** - Ensures PRs follow established conventions ✅ **Better Recommendations** - Suggestions aligned with your architecture +## Peer Review Integration + +PR Agent can integrate with Jira to provide intelligent peer review analysis that validates your PR against linked tickets and acceptance criteria. + +### Overview + +When enabled, the peer review feature acts like a **senior developer reviewing your PR**: + +- **Extracts ticket references** from PR title, branch name, or commit messages +- **Fetches ticket details** from Jira (description, acceptance criteria, story points) +- **Rates ticket quality** to identify poorly-defined requirements +- **Validates implementation** against derived requirements +- **Provides verdict** with blockers, warnings, and recommendations + +### Setup + +1. **Configure Jira credentials** in `.pragent.config.json`: + +```json +{ + "peerReview": { + "enabled": true, + "provider": "jira", + "instanceUrl": "https://your-company.atlassian.net", + "email": "your-email@company.com", + "apiToken": "your-jira-api-token", + "defaultProject": "PROJ", + "analyzeAcceptanceCriteria": true, + "rateTicketQuality": true, + "checkScopeCreep": true + } +} +``` + +2. **Get a Jira API Token**: + - Go to [Atlassian Account Settings](https://id.atlassian.com/manage-profile/security/api-tokens) + - Click "Create API token" + - Copy the token to your config + +3. **Reference tickets in your PR**: + - PR title: `feat(PROJ-123): Add new feature` + - Branch name: `feature/PROJ-123-add-feature` + - Commit message: `PROJ-123: implement feature` + +### Usage + +```bash +# Run analysis with peer review +pr-agent analyze + +# The peer review runs automatically if enabled in config +# Or enable it for a single run: +pr-agent analyze --peer-review +``` + +### Example Output + +``` +═══════════════════════════════════════════════════════════════ + 🔍 PEER REVIEW ANALYSIS +═══════════════════════════════════════════════════════════════ + +📋 LINKED TICKET +─────────────────────────────────────────────────────────────── + Key: PROJ-123 + Title: Add user authentication + Type: STORY + Status: In Progress + Points: 5 + +📊 TICKET QUALITY RATING +─────────────────────────────────────────────────────────────── + Overall Score: 🟢 85/100 (GOOD) + + Dimension Scores: + • Description Clarity: 🟢 ████████░░ 85 + • Acceptance Criteria: 🟢 █████████░ 90 + • Testability: 🟡 ███████░░░ 75 + • Scope Definition: 🟢 ████████░░ 80 + +✅ REQUIREMENTS VALIDATION +─────────────────────────────────────────────────────────────── + Compliance: 🟢 92% + + 📊 REQUIREMENT STATUS: + ✅ Implement login endpoint with JWT tokens + ✅ Add password validation (min 8 chars) + 🟡 Create logout endpoint + └─ Endpoint exists but doesn't invalidate tokens + ✅ Store hashed passwords in database + + ❌ COVERAGE GAPS: + 🟡 [MINOR] Token invalidation not implemented + └─ Impact: Users cannot fully logout, tokens remain valid + +🎯 PEER REVIEW VERDICT +─────────────────────────────────────────────────────────────── + ✅ APPROVED (Confidence: 85%) + + The PR implements the core authentication functionality as specified. + Minor gaps in token invalidation should be addressed in a follow-up. + + Scores: + • Implementation Completeness: 🟢 ████████░░ 88 + • Quality Score: 🟢 ████████░░ 82 + + 💡 RECOMMENDATIONS: + • Add token invalidation on logout + • Consider adding rate limiting + • Add integration tests for auth flow + +═══════════════════════════════════════════════════════════════ +``` + +### Configuration Options + +| Option | Type | Default | Description | +|--------|------|---------|-------------| +| `enabled` | boolean | `false` | Enable peer review integration | +| `provider` | string | `"jira"` | Issue tracker provider (currently only Jira) | +| `instanceUrl` | string | - | Your Jira instance URL | +| `email` | string | - | Your Jira account email | +| `apiToken` | string | - | Jira API token | +| `defaultProject` | string | - | Default project key for ticket extraction | +| `analyzeAcceptanceCriteria` | boolean | `true` | Validate against acceptance criteria | +| `rateTicketQuality` | boolean | `true` | Rate ticket definition quality | +| `generateTestSuggestions` | boolean | `true` | Generate test suggestions | +| `checkScopeCreep` | boolean | `true` | Detect scope creep in PRs | +| `includeTicketDetails` | boolean | `true` | Show ticket details in output | +| `verbose` | boolean | `false` | Enable verbose output | + +### Benefits + +✅ **Requirement Validation** - Ensures PRs implement what the ticket specifies +✅ **Quality Gate** - Catches incomplete implementations before review +✅ **Ticket Quality Feedback** - Identifies poorly-defined requirements +✅ **Scope Creep Detection** - Flags changes outside ticket scope +✅ **Senior Developer Perspective** - Catches edge cases and missing behaviors + ## GitHub Action Usage ### Setup Instructions @@ -766,7 +922,11 @@ pr-agent/ │ │ ├── anthropic.provider.ts │ │ ├── openai.provider.ts │ │ ├── google.provider.ts +│ │ ├── zhipu.provider.ts │ │ └── factory.ts +│ ├── issue-tracker/ # Issue tracker integrations +│ │ ├── jira-mcp-client.ts # Jira API client +│ │ └── peer-review-integration.ts │ ├── tools/ # Agent tools │ │ ├── pr-analysis-tools.ts │ │ └── index.ts @@ -957,6 +1117,13 @@ Best for: Quick analysis and cost-conscious usage Best for: Alternative to Claude/GPT with competitive performance +### Zhipu AI + +- **claude-sonnet-4-20250514** - Via Anthropic-compatible API +- **glm-4** - Zhipu's native model + +Best for: Users in China or those preferring Zhipu's platform with Claude-compatible models + ## Common Use Cases ### 1. Pre-Commit Review diff --git a/dist/agents/jira-sub-agent.d.ts b/dist/agents/jira-sub-agent.d.ts new file mode 100644 index 0000000..7d65ff1 --- /dev/null +++ b/dist/agents/jira-sub-agent.d.ts @@ -0,0 +1,199 @@ +/** + * Jira Sub-Agent (Peer Review Agent) + * + * This agent acts like an experienced senior developer reviewing a PR. + * It understands not just the code, but the business context from the Jira ticket. + * + * KEY PHILOSOPHY: + * Like a senior developer who deeply knows the codebase, this agent: + * 1. Mentally constructs test scenarios and edge cases (INTERNAL reasoning) + * 2. Uses those mental models to EVALUATE if the implementation is complete + * 3. Checks if changes might break other parts of the application + * 4. Reports FINDINGS, not suggestions for tests + * + * The test scenarios are the agent's internal thought process - like how a + * senior dev thinks "what about when X happens?" while reviewing code. + * The OUTPUT is the conclusion: "This doesn't handle X" or "X case is covered". + */ +import { z } from 'zod'; +import { IssueTicket } from '../types/issue-tracker.types.js'; +import { BaseLanguageModel } from '@langchain/core/language_models/base'; +declare const TicketQualitySchema: z.ZodObject<{ + overallScore: z.ZodNumber; + dimensions: z.ZodObject<{ + descriptionClarity: z.ZodNumber; + acceptanceCriteriaQuality: z.ZodNumber; + testabilityScore: z.ZodNumber; + scopeDefinition: z.ZodNumber; + technicalContext: z.ZodNumber; + visualDocumentation: z.ZodNumber; + completeness: z.ZodNumber; + }, z.core.$strip>; + feedback: z.ZodObject<{ + strengths: z.ZodArray; + weaknesses: z.ZodArray; + suggestions: z.ZodArray; + }, z.core.$strip>; + tier: z.ZodEnum<{ + excellent: "excellent"; + good: "good"; + adequate: "adequate"; + poor: "poor"; + insufficient: "insufficient"; + }>; + reviewable: z.ZodBoolean; + reviewabilityReason: z.ZodString; +}, z.core.$strip>; +/** + * Acceptance Criteria Validation - focuses on what IS and ISN'T covered + * + * IMPORTANT: The agent DERIVES its own acceptance criteria by analyzing: + * - The full ticket description + * - Any explicit AC field (if present, but don't rely on it) + * - The ticket type (bug vs feature has different expectations) + * - Technical context and constraints mentioned + * + * Like a senior dev who reads the whole ticket and thinks: + * "To implement this properly, I'd need to: 1) do X, 2) handle Y, 3) ensure Z" + */ +declare const AcceptanceCriteriaValidationSchema: z.ZodObject<{ + derivedRequirements: z.ZodArray; + importance: z.ZodEnum<{ + expected: "expected"; + essential: "essential"; + nice_to_have: "nice_to_have"; + }>; + }, z.core.$strip>>; + criteriaAnalysis: z.ZodArray; + criteriaText: z.ZodString; + status: z.ZodEnum<{ + met: "met"; + unmet: "unmet"; + partial: "partial"; + unclear: "unclear"; + }>; + confidence: z.ZodNumber; + evidence: z.ZodArray; + explanation: z.ZodString; + relatedFiles: z.ZodArray; + }, z.core.$strip>>; + compliancePercentage: z.ZodNumber; + gaps: z.ZodArray; + impact: z.ZodString; + }, z.core.$strip>>; + missingBehaviors: z.ZodArray; + partialImplementations: z.ZodArray; +}, z.core.$strip>; +/** + * Peer Review Analysis - the senior developer's verdict + */ +declare const PeerReviewAnalysisSchema: z.ZodObject<{ + implementationCompleteness: z.ZodNumber; + qualityScore: z.ZodNumber; + readyForReview: z.ZodBoolean; + blockers: z.ZodArray; + }, z.core.$strip>>; + warnings: z.ZodArray; + }, z.core.$strip>>; + recommendations: z.ZodArray; + scopeAnalysis: z.ZodObject<{ + inScope: z.ZodArray; + outOfScope: z.ZodArray; + scopeCreepRisk: z.ZodBoolean; + scopeCreepDetails: z.ZodOptional; + }, z.core.$strip>; + regressionRisks: z.ZodArray; + reasoning: z.ZodString; + }, z.core.$strip>>; + uncoveredScenarios: z.ZodArray; + relatedCriteria: z.ZodOptional; + }, z.core.$strip>>; + verdict: z.ZodObject<{ + summary: z.ZodString; + recommendation: z.ZodEnum<{ + approve: "approve"; + request_changes: "request_changes"; + needs_discussion: "needs_discussion"; + }>; + confidenceLevel: z.ZodNumber; + }, z.core.$strip>; +}, z.core.$strip>; +export type TicketQualityRating = z.infer; +export type AcceptanceCriteriaValidation = z.infer; +export type PeerReviewAnalysis = z.infer; +export interface JiraSubAgentResult { + ticketQuality: TicketQualityRating; + acValidation?: AcceptanceCriteriaValidation; + peerReview: PeerReviewAnalysis; +} +export interface JiraSubAgentContext { + ticket: IssueTicket; + prTitle: string; + prDescription?: string; + diff: string; + files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }>; + prSummary?: string; + prRisks?: string[]; +} +export declare class JiraSubAgent { + private llm; + constructor(llm: BaseLanguageModel); + /** + * Analyze a ticket and PR, providing comprehensive peer review + */ + analyze(context: JiraSubAgentContext): Promise; + /** + * Rate the quality of a Jira ticket + */ + rateTicketQuality(ticket: IssueTicket): Promise; + /** + * Validate acceptance criteria against PR changes + */ + validateAcceptanceCriteria(context: JiraSubAgentContext): Promise; + /** + * Generate comprehensive peer review analysis + */ + generatePeerReview(context: JiraSubAgentContext, ticketQuality: TicketQualityRating, acValidation?: AcceptanceCriteriaValidation): Promise; +} +export {}; diff --git a/dist/agents/jira-sub-agent.js b/dist/agents/jira-sub-agent.js new file mode 100644 index 0000000..d1f3a6e --- /dev/null +++ b/dist/agents/jira-sub-agent.js @@ -0,0 +1,473 @@ +/** + * Jira Sub-Agent (Peer Review Agent) + * + * This agent acts like an experienced senior developer reviewing a PR. + * It understands not just the code, but the business context from the Jira ticket. + * + * KEY PHILOSOPHY: + * Like a senior developer who deeply knows the codebase, this agent: + * 1. Mentally constructs test scenarios and edge cases (INTERNAL reasoning) + * 2. Uses those mental models to EVALUATE if the implementation is complete + * 3. Checks if changes might break other parts of the application + * 4. Reports FINDINGS, not suggestions for tests + * + * The test scenarios are the agent's internal thought process - like how a + * senior dev thinks "what about when X happens?" while reviewing code. + * The OUTPUT is the conclusion: "This doesn't handle X" or "X case is covered". + */ +import { ChatPromptTemplate } from '@langchain/core/prompts'; +import { StructuredOutputParser } from '@langchain/core/output_parsers'; +import { z } from 'zod'; +// ========== Output Schemas ========== +const TicketQualitySchema = z.object({ + overallScore: z.number().min(0).max(100).describe('Overall ticket quality score'), + dimensions: z.object({ + descriptionClarity: z.number().min(0).max(100), + acceptanceCriteriaQuality: z.number().min(0).max(100), + testabilityScore: z.number().min(0).max(100), + scopeDefinition: z.number().min(0).max(100), + technicalContext: z.number().min(0).max(100), + visualDocumentation: z.number().min(0).max(100), + completeness: z.number().min(0).max(100), + }), + feedback: z.object({ + strengths: z.array(z.string()), + weaknesses: z.array(z.string()), + suggestions: z.array(z.string()), + }), + tier: z.enum(['excellent', 'good', 'adequate', 'poor', 'insufficient']), + reviewable: z.boolean(), + reviewabilityReason: z.string(), +}); +/** + * Acceptance Criteria Validation - focuses on what IS and ISN'T covered + * + * IMPORTANT: The agent DERIVES its own acceptance criteria by analyzing: + * - The full ticket description + * - Any explicit AC field (if present, but don't rely on it) + * - The ticket type (bug vs feature has different expectations) + * - Technical context and constraints mentioned + * + * Like a senior dev who reads the whole ticket and thinks: + * "To implement this properly, I'd need to: 1) do X, 2) handle Y, 3) ensure Z" + */ +const AcceptanceCriteriaValidationSchema = z.object({ + // The agent's derived understanding of what needs to be implemented + derivedRequirements: z.array(z.object({ + id: z.string(), + requirement: z.string().describe('What the agent derived needs to be done'), + source: z.enum(['description', 'explicit_ac', 'implied', 'ticket_type', 'technical_context']) + .describe('Where this requirement was derived from'), + importance: z.enum(['essential', 'expected', 'nice_to_have']), + })).describe('Requirements derived by analyzing the full ticket, not just AC field'), + // Analysis of each derived requirement against the PR + criteriaAnalysis: z.array(z.object({ + criteriaId: z.string().optional(), + criteriaText: z.string(), + status: z.enum(['met', 'unmet', 'partial', 'unclear']), + confidence: z.number().min(0).max(100), + evidence: z.array(z.string()).describe('Code evidence showing coverage or lack thereof'), + explanation: z.string().describe('Why this criteria is/isnt met'), + relatedFiles: z.array(z.string()), + })), + compliancePercentage: z.number().min(0).max(100), + gaps: z.array(z.object({ + criteriaText: z.string(), + gapDescription: z.string().describe('What specific functionality is missing'), + severity: z.enum(['critical', 'major', 'minor']), + impact: z.string().describe('What will happen if this gap is not addressed'), + })), + // Internal reasoning exposed as findings, not suggestions + missingBehaviors: z.array(z.string()).describe('Behaviors that should exist but dont'), + partialImplementations: z.array(z.string()).describe('Features that are started but incomplete'), +}); +/** + * Peer Review Analysis - the senior developer's verdict + */ +const PeerReviewAnalysisSchema = z.object({ + implementationCompleteness: z.number().min(0).max(100), + qualityScore: z.number().min(0).max(100), + readyForReview: z.boolean(), + // Critical findings that block merge + blockers: z.array(z.object({ + issue: z.string(), + reason: z.string(), + location: z.string().optional().describe('File or component affected'), + })), + // Important issues that should be fixed + warnings: z.array(z.object({ + issue: z.string(), + reason: z.string(), + location: z.string().optional(), + })), + // Nice-to-have improvements + recommendations: z.array(z.string()), + // Scope analysis + scopeAnalysis: z.object({ + inScope: z.array(z.string()), + outOfScope: z.array(z.string()), + scopeCreepRisk: z.boolean(), + scopeCreepDetails: z.string().optional(), + }), + // Potential regression analysis - what might break + regressionRisks: z.array(z.object({ + risk: z.string().describe('What could break'), + affectedArea: z.string().describe('Part of the app that might be affected'), + likelihood: z.enum(['high', 'medium', 'low']), + reasoning: z.string().describe('Why this might happen'), + })), + // Uncovered scenarios identified during review (findings, not suggestions) + uncoveredScenarios: z.array(z.object({ + scenario: z.string().describe('A scenario that isnt handled'), + impact: z.enum(['critical', 'major', 'minor']), + relatedCriteria: z.string().optional(), + })), + // Final verdict + verdict: z.object({ + summary: z.string().describe('One paragraph summary of the review'), + recommendation: z.enum(['approve', 'request_changes', 'needs_discussion']), + confidenceLevel: z.number().min(0).max(100), + }), +}); +// ========== Prompts ========== +const TICKET_QUALITY_PROMPT = `You are an expert at evaluating Jira tickets and user stories. +Analyze the following ticket and rate its quality based on industry best practices. + +TICKET INFORMATION: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} +Description: +{ticketDescription} + +Acceptance Criteria: +{acceptanceCriteria} + +Test Scenarios Defined: {testScenarios} +Has Screenshots/Mockups: {hasScreenshots} +Has Diagrams: {hasDiagrams} +Story Points: {storyPoints} +Labels: {labels} +Components: {components} + +EVALUATION CRITERIA: +1. Description Clarity (0-100): Is the description clear, complete, and unambiguous? +2. Acceptance Criteria Quality (0-100): Are ACs specific, measurable, achievable, and testable (SMART)? +3. Testability Score (0-100): Can this ticket be tested? Are expected behaviors clear? +4. Scope Definition (0-100): Is the scope well-defined and bounded? No scope creep potential? +5. Technical Context (0-100): Are technical requirements, constraints, and dependencies clear? +6. Visual Documentation (0-100): Are there screenshots, mockups, or diagrams where needed? +7. Completeness (0-100): Overall ticket completeness - nothing critical missing? + +QUALITY TIERS: +- excellent (85-100): Exemplary ticket, can be implemented with high confidence +- good (70-84): Well-written ticket with minor gaps +- adequate (50-69): Passable but has notable gaps that may cause issues +- poor (25-49): Significant issues, needs improvement before implementation +- insufficient (0-24): Cannot be implemented reliably, needs major rework + +REVIEWABILITY: +A ticket is "reviewable" if there's enough information to meaningfully derive what needs +to be implemented. This does NOT require an explicit acceptance criteria field! + +A ticket is REVIEWABLE if: +- The description explains what needs to be done (even briefly) +- The title + type give enough context to understand the goal +- A senior developer could reasonably derive requirements from it + +A ticket is NOT REVIEWABLE if: +- It's just a title with no description (e.g., "Fix bug" with nothing else) +- It's too vague to derive any concrete requirements +- There's literally not enough info to know what "done" looks like + +Remember: Many good tickets have detailed descriptions but empty AC fields. +The key is whether YOU can derive what needs to be built. + +{format_instructions}`; +const AC_VALIDATION_PROMPT = `You are a SENIOR DEVELOPER with deep knowledge of this codebase reviewing a PR. + +Your task: Understand what this ticket requires, then evaluate if the PR implements it correctly. + +CRITICAL: DO NOT just rely on the "Acceptance Criteria" field. Many tickets have empty AC or +poorly written AC. You must DERIVE your own understanding of what needs to be done by reading: +- The full description +- The ticket type (bug fix has different needs than a feature) +- Any technical context mentioned +- The implicit requirements (what any experienced dev would know is needed) + +Think like an experienced dev who reads a ticket and thinks: +"Okay, to implement this properly I need to: handle X, add Y, make sure Z works..." + +JIRA TICKET: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} + +FULL DESCRIPTION (analyze this carefully): +{ticketDescription} + +EXPLICIT ACCEPTANCE CRITERIA (may be empty or incomplete - don't rely solely on this): +{acceptanceCriteria} + +PR INFORMATION: +Title: {prTitle} +Description: {prDescription} + +FILES CHANGED: +{filesChanged} + +CODE DIFF: +{diff} + +PREVIOUS PR ANALYSIS SUMMARY: +{prSummary} + +YOUR TASK: + +1. DERIVE REQUIREMENTS: + First, read the entire ticket and derive what actually needs to be implemented. + For each requirement you identify, note: + - What the requirement is + - Where you derived it from (description, explicit AC, implied by ticket type, technical context) + - How essential it is (essential, expected, nice-to-have) + + Don't just copy the AC field - THINK about what's really needed. + A ticket saying "Add login button" implies: the button should be visible, clickable, + trigger auth flow, handle errors, etc. + +2. VALIDATE EACH REQUIREMENT: + For each derived requirement: + - Is it MET, UNMET, PARTIAL, or UNCLEAR in the code? + - Provide CODE EVIDENCE + - Explain your reasoning + +3. IDENTIFY GAPS: + What's missing? What behaviors should exist but don't? + Think through scenarios: "What if the user does X?" "What about error case Y?" + +Report FINDINGS, not suggestions. Like a senior dev saying: +"This doesn't handle the case when the user is logged out" + +{format_instructions}`; +const PEER_REVIEW_PROMPT = `You are a SENIOR DEVELOPER doing a thorough peer review. + +You've been with this team for years. You know where the bodies are buried. +You think about: +- Does this actually solve the problem in the ticket? +- What might this break in other parts of the app? +- Are there scenarios the developer didn't consider? +- Is this ready for production? + +JIRA TICKET: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} +Description: {ticketDescription} +Acceptance Criteria: {acceptanceCriteria} + +PR INFORMATION: +Title: {prTitle} +Description: {prDescription} + +FILES CHANGED: +{filesChanged} + +DIFF SUMMARY: +{diff} + +EXISTING PR ANALYSIS: +Summary: {prSummary} +Risks Identified: {prRisks} + +TICKET QUALITY ASSESSMENT: +Overall Score: {ticketQualityScore}/100 +Reviewable: {isReviewable} + +AC VALIDATION RESULTS: +Compliance: {acCompliancePercentage}% +Gaps Found: {gapsFound} + +YOUR PEER REVIEW TASK: + +1. IMPLEMENTATION COMPLETENESS (0-100): + Does this PR fully implement what the ticket asks for? + +2. QUALITY SCORE (0-100): + Code quality + requirements adherence combined + +3. READY FOR REVIEW: + Would you approve this or request changes? + +4. BLOCKERS: + Critical issues - things that MUST be fixed before merge + (missing functionality, bugs, security issues) + +5. WARNINGS: + Important issues - things that SHOULD be fixed + (edge cases not handled, potential bugs) + +6. RECOMMENDATIONS: + Nice-to-haves for improvement + +7. SCOPE ANALYSIS: + - What's in scope vs out of scope? + - Is there scope creep? + +8. REGRESSION RISKS: + Think: "What else in the app might this break?" + - Consider dependencies, shared code, side effects + - Think about how this interacts with existing features + +9. UNCOVERED SCENARIOS: + As a senior dev, you mentally run through scenarios: + - "What if the user does X?" + - "What about when Y is null?" + - "What happens during Z error condition?" + + Report which scenarios you identified that AREN'T handled. + Don't suggest tests - just flag what's missing. + +10. FINAL VERDICT: + Give your honest assessment: + - APPROVE: Ready to merge (maybe minor nits) + - REQUEST_CHANGES: Needs work before merge + - NEEDS_DISCUSSION: Architectural concerns to discuss + +{format_instructions}`; +// ========== Agent Class ========== +export class JiraSubAgent { + llm; + constructor(llm) { + this.llm = llm; + } + /** + * Analyze a ticket and PR, providing comprehensive peer review + */ + async analyze(context) { + // Step 1: Rate ticket quality + const ticketQuality = await this.rateTicketQuality(context.ticket); + // Step 2: Derive requirements and validate against PR + // NOTE: We analyze even if there's no explicit AC field - the agent derives + // requirements from the full ticket (description, title, type, context) + let acValidation; + if (ticketQuality.reviewable) { + // The agent will derive its own requirements from the ticket + // Don't skip just because acceptanceCriteriaList is empty + acValidation = await this.validateAcceptanceCriteria(context); + } + // Step 3: Generate peer review analysis + const peerReview = await this.generatePeerReview(context, ticketQuality, acValidation); + return { + ticketQuality, + acValidation, + peerReview, + }; + } + /** + * Rate the quality of a Jira ticket + */ + async rateTicketQuality(ticket) { + const parser = StructuredOutputParser.fromZodSchema(TicketQualitySchema); + const prompt = ChatPromptTemplate.fromTemplate(TICKET_QUALITY_PROMPT); + const chain = prompt.pipe(this.llm); + const response = await chain.invoke({ + ticketKey: ticket.key, + ticketType: ticket.type, + ticketTitle: ticket.title, + ticketDescription: ticket.description || 'No description provided', + acceptanceCriteria: ticket.acceptanceCriteria || + ticket.acceptanceCriteriaList?.join('\n') || + 'No acceptance criteria defined', + testScenarios: ticket.testScenarios?.join(', ') || 'None defined', + hasScreenshots: ticket.hasScreenshots ? 'Yes' : 'No', + hasDiagrams: ticket.hasDiagrams ? 'Yes' : 'No', + storyPoints: ticket.storyPoints?.toString() || 'Not estimated', + labels: ticket.labels.join(', ') || 'None', + components: ticket.components.join(', ') || 'None', + format_instructions: parser.getFormatInstructions(), + }); + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } + /** + * Validate acceptance criteria against PR changes + */ + async validateAcceptanceCriteria(context) { + const parser = StructuredOutputParser.fromZodSchema(AcceptanceCriteriaValidationSchema); + const prompt = ChatPromptTemplate.fromTemplate(AC_VALIDATION_PROMPT); + const chain = prompt.pipe(this.llm); + // Format acceptance criteria with IDs + const acList = context.ticket.acceptanceCriteriaList || []; + const formattedAC = acList + .map((ac, i) => `AC-${i + 1}: ${ac}`) + .join('\n'); + // Format files changed + const filesChanged = context.files + .map((f) => `${f.path} (+${f.additions}/-${f.deletions}) [${f.status}]`) + .join('\n'); + // Truncate diff if too long + const maxDiffLength = 15000; + const truncatedDiff = context.diff.length > maxDiffLength + ? context.diff.substring(0, maxDiffLength) + '\n... [diff truncated]' + : context.diff; + const response = await chain.invoke({ + ticketKey: context.ticket.key, + ticketType: context.ticket.type, + ticketTitle: context.ticket.title, + ticketDescription: context.ticket.description?.substring(0, 2000) || 'No description', + acceptanceCriteria: formattedAC || 'No acceptance criteria defined', + prTitle: context.prTitle, + prDescription: context.prDescription || 'No description', + filesChanged, + diff: truncatedDiff, + prSummary: context.prSummary || 'No summary available', + format_instructions: parser.getFormatInstructions(), + }); + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } + /** + * Generate comprehensive peer review analysis + */ + async generatePeerReview(context, ticketQuality, acValidation) { + const parser = StructuredOutputParser.fromZodSchema(PeerReviewAnalysisSchema); + const prompt = ChatPromptTemplate.fromTemplate(PEER_REVIEW_PROMPT); + const chain = prompt.pipe(this.llm); + // Format files changed + const filesChanged = context.files + .map((f) => `${f.path} (+${f.additions}/-${f.deletions}) [${f.status}]`) + .join('\n'); + // Truncate diff if too long + const maxDiffLength = 10000; + const truncatedDiff = context.diff.length > maxDiffLength + ? context.diff.substring(0, maxDiffLength) + '\n... [diff truncated]' + : context.diff; + // Format gaps found + const gapsFound = acValidation?.gaps + .map((g) => `- ${g.criteriaText}: ${g.gapDescription}`) + .join('\n') || 'None identified'; + const response = await chain.invoke({ + ticketKey: context.ticket.key, + ticketType: context.ticket.type, + ticketTitle: context.ticket.title, + ticketDescription: context.ticket.description?.substring(0, 2000) || 'No description', + acceptanceCriteria: context.ticket.acceptanceCriteria || + context.ticket.acceptanceCriteriaList?.join('\n') || + 'None defined', + prTitle: context.prTitle, + prDescription: context.prDescription || 'No description', + filesChanged, + diff: truncatedDiff, + prSummary: context.prSummary || 'No summary available', + prRisks: context.prRisks?.join(', ') || 'None identified', + ticketQualityScore: ticketQuality.overallScore, + isReviewable: ticketQuality.reviewable ? 'Yes' : 'No', + acCompliancePercentage: acValidation?.compliancePercentage ?? 'N/A', + gapsFound, + format_instructions: parser.getFormatInstructions(), + }); + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } +} +//# sourceMappingURL=jira-sub-agent.js.map \ No newline at end of file diff --git a/dist/agents/jira-sub-agent.js.map b/dist/agents/jira-sub-agent.js.map new file mode 100644 index 0000000..628a181 --- /dev/null +++ b/dist/agents/jira-sub-agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jira-sub-agent.js","sourceRoot":"","sources":["../../src/agents/jira-sub-agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,uCAAuC;AAEvC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IACjF,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC9C,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QACrD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC5C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC3C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC5C,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QAC/C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;KACzC,CAAC;IACF,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;QACjB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC9B,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,WAAW,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACjC,CAAC;IACF,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;IACvE,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE;IACvB,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE;CAChC,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,oEAAoE;IACpE,mBAAmB,EAAE,CAAC,CAAC,KAAK,CAC1B,CAAC,CAAC,MAAM,CAAC;QACP,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;QACd,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QAC3E,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC;aAC1F,QAAQ,CAAC,yCAAyC,CAAC;QACtD,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;KAC9D,CAAC,CACH,CAAC,QAAQ,CAAC,sEAAsE,CAAC;IAElF,sDAAsD;IACtD,gBAAgB,EAAE,CAAC,CAAC,KAAK,CACvB,CAAC,CAAC,MAAM,CAAC;QACP,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QACjC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACtD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;QACtC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,gDAAgD,CAAC;QACxF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QACjE,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KAClC,CAAC,CACH;IACD,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IAChD,IAAI,EAAE,CAAC,CAAC,KAAK,CACX,CAAC,CAAC,MAAM,CAAC;QACP,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;QACxB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QAC7E,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;KAC7E,CAAC,CACH;IACD,0DAA0D;IAC1D,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IACtF,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;CACjG,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACtD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACxC,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE;IAE3B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,CAAC,KAAK,CACf,CAAC,CAAC,MAAM,CAAC;QACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;KACvE,CAAC,CACH;IAED,wCAAwC;IACxC,QAAQ,EAAE,CAAC,CAAC,KAAK,CACf,CAAC,CAAC,MAAM,CAAC;QACP,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;QACjB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC,CACH;IAED,4BAA4B;IAC5B,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAEpC,iBAAiB;IACjB,aAAa,EAAE,CAAC,CAAC,MAAM,CAAC;QACtB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5B,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE;QAC3B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACzC,CAAC;IAEF,mDAAmD;IACnD,eAAe,EAAE,CAAC,CAAC,KAAK,CACtB,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QAC7C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;QAC3E,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KACxD,CAAC,CACH;IAED,2EAA2E;IAC3E,kBAAkB,EAAE,CAAC,CAAC,KAAK,CACzB,CAAC,CAAC,MAAM,CAAC;QACP,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC7D,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9C,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACvC,CAAC,CACH;IAED,gBAAgB;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC;QAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QACnE,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;QAC1E,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;KAC5C,CAAC;CACH,CAAC,CAAC;AA6BH,gCAAgC;AAEhC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAqDR,CAAC;AAEvB,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAgEP,CAAC;AAEvB,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAoFL,CAAC;AAEvB,oCAAoC;AAEpC,MAAM,OAAO,YAAY;IACf,GAAG,CAAoB;IAE/B,YAAY,GAAsB;QAChC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,OAA4B;QACxC,8BAA8B;QAC9B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAEnE,sDAAsD;QACtD,4EAA4E;QAC5E,wEAAwE;QACxE,IAAI,YAAsD,CAAC;QAC3D,IAAI,aAAa,CAAC,UAAU,EAAE,CAAC;YAC7B,6DAA6D;YAC7D,0DAA0D;YAC1D,YAAY,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC;QAChE,CAAC;QAED,wCAAwC;QACxC,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC;QAEvF,OAAO;YACL,aAAa;YACb,YAAY;YACZ,UAAU;SACX,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAmB;QACzC,MAAM,MAAM,GAAG,sBAAsB,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;QAEzE,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC;QAEtE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;YAClC,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,UAAU,EAAE,MAAM,CAAC,IAAI;YACvB,WAAW,EAAE,MAAM,CAAC,KAAK;YACzB,iBAAiB,EAAE,MAAM,CAAC,WAAW,IAAI,yBAAyB;YAClE,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;gBAC3C,MAAM,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,CAAC;gBACzC,gCAAgC;YAClC,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,cAAc;YACjE,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YACpD,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YAC9C,WAAW,EAAE,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,IAAI,eAAe;YAC9D,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM;YAC1C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM;YAClD,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,EAAE;SACpD,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7F,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,0BAA0B,CAC9B,OAA4B;QAE5B,MAAM,MAAM,GAAG,sBAAsB,CAAC,aAAa,CAAC,kCAAkC,CAAC,CAAC;QAExF,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,oBAAoB,CAAC,CAAC;QAErE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpC,sCAAsC;QACtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,sBAAsB,IAAI,EAAE,CAAC;QAC3D,MAAM,WAAW,GAAG,MAAM;aACvB,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC;aACpC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,uBAAuB;QACvB,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;aACvE,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,4BAA4B;QAC5B,MAAM,aAAa,GAAG,KAAK,CAAC;QAC5B,MAAM,aAAa,GACjB,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa;YACjC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,wBAAwB;YACrE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAEnB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;YAClC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG;YAC7B,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YAC/B,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;YACjC,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,gBAAgB;YACrF,kBAAkB,EAAE,WAAW,IAAI,gCAAgC;YACnE,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,gBAAgB;YACxD,YAAY;YACZ,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,sBAAsB;YACtD,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,EAAE;SACpD,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7F,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CACtB,OAA4B,EAC5B,aAAkC,EAClC,YAA2C;QAE3C,MAAM,MAAM,GAAG,sBAAsB,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;QAE9E,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;QAEnE,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEpC,uBAAuB;QACvB,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK;aAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;aACvE,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,4BAA4B;QAC5B,MAAM,aAAa,GAAG,KAAK,CAAC;QAC5B,MAAM,aAAa,GACjB,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa;YACjC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,aAAa,CAAC,GAAG,wBAAwB;YACrE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QAEnB,oBAAoB;QACpB,MAAM,SAAS,GAAG,YAAY,EAAE,IAAI;aACjC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,cAAc,EAAE,CAAC;aACtD,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC;QAEnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC;YAClC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG;YAC7B,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YAC/B,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK;YACjC,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,gBAAgB;YACrF,kBAAkB,EAChB,OAAO,CAAC,MAAM,CAAC,kBAAkB;gBACjC,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,IAAI,CAAC,IAAI,CAAC;gBACjD,cAAc;YAChB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,gBAAgB;YACxD,YAAY;YACZ,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,sBAAsB;YACtD,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB;YACzD,kBAAkB,EAAE,aAAa,CAAC,YAAY;YAC9C,YAAY,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YACrD,sBAAsB,EAAE,YAAY,EAAE,oBAAoB,IAAI,KAAK;YACnE,SAAS;YACT,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,EAAE;SACpD,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC7F,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;CACF"} \ No newline at end of file diff --git a/dist/cli/commands/analyze.command.d.ts b/dist/cli/commands/analyze.command.d.ts index d18214c..4b963c2 100644 --- a/dist/cli/commands/analyze.command.d.ts +++ b/dist/cli/commands/analyze.command.d.ts @@ -14,6 +14,7 @@ interface AnalyzeOptions { verbose?: boolean; maxCost?: number; archDocs?: boolean; + peerReview?: boolean; } /** * Analyze command - analyze PR diffs with AI diff --git a/dist/cli/commands/analyze.command.js b/dist/cli/commands/analyze.command.js index 364a862..ce949de 100644 --- a/dist/cli/commands/analyze.command.js +++ b/dist/cli/commands/analyze.command.js @@ -7,6 +7,8 @@ import { loadUserConfig, getApiKey } from '../utils/config-loader.js'; import { archDocsExists } from '../../utils/arch-docs-parser.js'; import { resolveDefaultBranch } from '../../utils/branch-resolver.js'; import { ConfigurationError, GitHubAPIError, GitError } from '../../utils/errors.js'; +import { createPeerReviewIntegration, formatPeerReviewOutput, } from '../../issue-tracker/index.js'; +import { ProviderFactory } from '../../providers/index.js'; /** * Determine which files should be skipped during analysis */ @@ -232,6 +234,7 @@ export async function analyzePR(options = {}) { } const provider = (options.provider || config.ai?.provider || 'anthropic').toLowerCase(); const apiKey = getApiKey(provider, config); + const model = options.model || config.ai?.model; if (!apiKey) { spinner.fail('No API key found'); console.error(chalk.yellow('💡 Please set it in one of these ways:')); @@ -240,6 +243,10 @@ export async function analyzePR(options = {}) { console.error(chalk.gray(' - Anthropic (Claude): export ANTHROPIC_API_KEY="your-api-key"')); console.error(chalk.gray(' - OpenAI (GPT): export OPENAI_API_KEY="your-api-key"')); console.error(chalk.gray(' - Google (Gemini): export GOOGLE_API_KEY="your-api-key"')); + console.error(chalk.gray(' - Zhipu (GLM): export ZHIPU_API_KEY="your-api-key"')); + if (options.verbose) { + console.error(chalk.gray(` Debug: Provider=${provider}, Config apiKeys=${JSON.stringify(config.apiKeys || {})}`)); + } process.exit(1); } spinner.succeed(`Using AI provider: ${provider}`); @@ -345,7 +352,6 @@ export async function analyzePR(options = {}) { else if (options.archDocs && !hasArchDocs) { console.log(chalk.yellow('⚠️ --arch-docs flag specified but no .arch-docs folder found\n')); } - const model = options.model || config.ai?.model; const agent = new PRAnalyzerAgent({ provider: provider, apiKey, @@ -360,6 +366,19 @@ export async function analyzePR(options = {}) { }); // Display results displayAgentResults(result, mode, options.verbose || false); + // Run Peer Review if enabled (via flag or config) + const peerReviewEnabled = options.peerReview || config.peerReview?.enabled; + if (options.verbose) { + console.log(chalk.gray(`\n Debug: peerReviewEnabled=${peerReviewEnabled}, options.peerReview=${options.peerReview}, config.peerReview?.enabled=${config.peerReview?.enabled}`)); + } + if (peerReviewEnabled) { + // Pass the same provider config to peer review so it uses the same LLM + await runPeerReview(config, diff, title, result, options.verbose || false, { + provider, + apiKey, + model, + }); + } } catch (error) { spinner.fail('Analysis failed'); @@ -490,6 +509,52 @@ function displayAgentResults(result, mode, verbose) { console.log(chalk.gray(` ... and ${totalFilteredFixes - prCommentFixes.length} more issues\n`)); } } + // Show recommendations if available + if (result.recommendations.length > 0) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.cyan.bold('\n💡 Recommendations\n')); + result.recommendations.forEach((rec, i) => { + console.log(chalk.white(` ${i + 1}. ${rec}`)); + }); + console.log('\n'); + } + // Show agent reasoning if available (minimal) + if (verbose && result.reasoning.length > 0 && result.reasoning.length <= 5) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.cyan.bold('\n🤔 Analysis Strategy\n')); + result.reasoning.forEach((reason, i) => { + if (reason.includes('Strategy:') || i === 0) { + console.log(chalk.gray(` ${reason.substring(0, 150)}${reason.length > 150 ? '...' : ''}`)); + } + }); + console.log('\n'); + } + // Show arch-docs impact if used + if (result.archDocsImpact?.used) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.blue.bold('\n📚 Architecture Documentation Impact\n')); + console.log(chalk.white(`Documents analyzed: ${result.archDocsImpact.docsAvailable}`)); + console.log(chalk.white(`Relevant sections used: ${result.archDocsImpact.sectionsUsed}\n`)); + if (result.archDocsImpact.influencedStages.length > 0) { + console.log(chalk.cyan('Stages influenced by arch-docs:')); + result.archDocsImpact.influencedStages.forEach((stage) => { + const stageEmoji = stage === 'file-analysis' ? '🔍' : + stage === 'risk-detection' ? '⚠️' : + stage === 'complexity-calculation' ? '📊' : + stage === 'summary-generation' ? '📝' : + stage === 'refinement' ? '🔄' : '✨'; + console.log(chalk.white(` ${stageEmoji} ${stage}`)); + }); + console.log(''); + } + if (result.archDocsImpact.keyInsights.length > 0) { + console.log(chalk.cyan('Key insights from arch-docs integration:\n')); + result.archDocsImpact.keyInsights.forEach((insight, i) => { + console.log(chalk.white(` ${i + 1}. ${insight}`)); + }); + console.log(''); + } + } else { console.log(chalk.green.bold('✅ Status\n')); console.log(chalk.white(' No critical issues found.\n\n')); @@ -500,4 +565,116 @@ function displayAgentResults(result, mode, verbose) { } console.log(chalk.gray('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n')); } +/** + * Run Peer Review analysis against linked Jira tickets + * + * This extends the PR analysis with business context validation: + * - Fetches linked Jira tickets from PR title/branch + * - Rates ticket quality + * - Validates implementation against derived requirements + * - Provides senior-dev style verdict + */ +async function runPeerReview(config, diff, title, prAnalysisResult, verbose, providerOptions) { + const spinner = ora('Running Peer Review analysis...').start(); + try { + // Create LLM using the same provider as main analysis + const llm = ProviderFactory.createChatModel({ + provider: providerOptions.provider, + apiKey: providerOptions.apiKey, + model: providerOptions.model, + temperature: 0.2, + maxTokens: 4000, + }); + // Create peer review integration from config, passing the LLM + const peerReviewConfig = config.peerReview || {}; + const integration = createPeerReviewIntegration(peerReviewConfig, llm); + if (!integration.isEnabled()) { + spinner.warn('Peer Review enabled but not configured. Add Jira settings to config.'); + console.log(chalk.gray(' Run: pr-agent config --set peerReview.instanceUrl=https://your.atlassian.net')); + console.log(chalk.gray(' Or configure MCP: peerReview.useMcp=true')); + if (verbose) { + console.log(chalk.gray(` Debug: peerReviewConfig=${JSON.stringify(peerReviewConfig)}`)); + } + return; + } + // Get branch name for ticket extraction + let branchName; + try { + branchName = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim(); + } + catch { + // Ignore - branch name is optional + } + // Get commit messages for ticket extraction + let commitMessages = []; + try { + const commits = execSync('git log --oneline -10', { encoding: 'utf-8' }); + commitMessages = commits.trim().split('\n'); + } + catch { + // Ignore + } + // Parse diff to get file info + const files = parseDiffFiles(diff); + spinner.text = 'Extracting ticket references...'; + // Run peer review analysis + const result = await integration.analyze({ + prTitle: title || 'Untitled PR', + prDescription: undefined, // Could extract from git commit body + branchName, + commitMessages, + diff, + files, + prSummary: prAnalysisResult.summary, + prRisks: prAnalysisResult.overallRisks, + prComplexity: prAnalysisResult.overallComplexity, + }); + spinner.succeed('Peer Review analysis complete'); + // Display peer review results + const output = formatPeerReviewOutput(result); + if (output) { + console.log(output); + } + if (verbose && result.ticketReferences.length > 0) { + console.log(chalk.gray('Ticket references found:')); + result.ticketReferences.forEach((ref) => { + console.log(chalk.gray(` - ${ref.key} (from ${ref.source}, confidence: ${ref.confidence}%)`)); + }); + } + } + catch (error) { + spinner.fail('Peer Review analysis failed'); + console.error(chalk.yellow(`⚠️ ${error.message || 'Unknown error'}`)); + console.log(chalk.gray(' The main PR analysis completed successfully.')); + console.log(chalk.gray(' Peer Review is an optional enhancement - check Jira configuration.')); + } +} +/** + * Parse diff to extract file information + */ +function parseDiffFiles(diff) { + const files = []; + const filePattern = /^diff --git a\/(.+?) b\/(.+?)$/gm; + let match; + while ((match = filePattern.exec(diff)) !== null) { + const filePath = match[2] !== '/dev/null' ? match[2] : match[1]; + const isNew = match[1] === '/dev/null' || match[1].startsWith('dev/null'); + const isDeleted = match[2] === '/dev/null'; + // Count additions and deletions (simplified) + const fileStart = match.index; + const nextFileMatch = filePattern.exec(diff); + const fileEnd = nextFileMatch ? nextFileMatch.index : diff.length; + filePattern.lastIndex = match.index + 1; // Reset to continue from after current match + const fileContent = diff.substring(fileStart, fileEnd); + const additions = (fileContent.match(/^\+[^+]/gm) || []).length; + const deletions = (fileContent.match(/^-[^-]/gm) || []).length; + files.push({ + path: filePath, + additions, + deletions, + status: isNew ? 'added' : isDeleted ? 'deleted' : 'modified', + }); + } + return files; +} //# sourceMappingURL=analyze.command.js.map \ No newline at end of file diff --git a/dist/cli/commands/analyze.command.js.map b/dist/cli/commands/analyze.command.js.map index 13c86f8..246145e 100644 --- a/dist/cli/commands/analyze.command.js.map +++ b/dist/cli/commands/analyze.command.js.map @@ -1 +1 @@ -{"version":3,"file":"analyze.command.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.command.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"analyze.command.js","sourceRoot":"","sources":["../../../src/cli/commands/analyze.command.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/cli/commands/help.command.js b/dist/cli/commands/help.command.js index 8024f2a..c2dff9c 100644 --- a/dist/cli/commands/help.command.js +++ b/dist/cli/commands/help.command.js @@ -39,7 +39,7 @@ export function displayHelp() { console.log(' 4. Fallback to origin/main'); console.log(' Use --branch to override for a single analysis\n'); console.log(chalk.dim(' Advanced Options:')); - console.log(' --provider AI provider: anthropic|openai|google'); + console.log(' --provider AI provider: anthropic|openai|google|zhipu'); console.log(' --model Specific model to use'); console.log(' --title PR title (auto-detected from git)'); console.log(' --max-cost Maximum cost limit (default: $5.00)'); diff --git a/dist/cli/commands/help.command.js.map b/dist/cli/commands/help.command.js.map index 1aa82f6..719eeed 100644 --- a/dist/cli/commands/help.command.js.map +++ b/dist/cli/commands/help.command.js.map @@ -1 +1 @@ -{"version":3,"file":"help.command.js","sourceRoot":"","sources":["../../../src/cli/commands/help.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,uGAAuG,CACxG,CACF,CAAC;IAEF,cAAc;IACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,iCAAiC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,yBAAyB,CAAC,CAAC;IACtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,oDAAoD,CAAC,CAAC;IAEhG,gBAAgB;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;IAEhD,kBAAkB;IAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAC;IACxF,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,8EAA8E,CAAC,CAAC;IAE5F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IAEjE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;IAEpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;IAEtE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAC9E,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;IAEpE,iBAAiB;IACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IAErF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;IACjF,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;IAC1F,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;IACxE,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;IAE9E,eAAe;IACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;IAEjE,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,uEAAuE,CAAC,CAAC;IAChH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,qEAAqE,CAAC,CAAC;IAC5G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,4DAA4D,CAAC,CAAC;IACxG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,8CAA8C,CAAC,CAAC;IAEpF,oBAAoB;IACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,iFAAiF,CAAC,CAAC;IAC/F,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,6CAA6C,CAAC,CAAC;IACxG,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,0BAA0B,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,GAAG,mBAAmB,CAAC,CAAC;IACrF,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,wCAAwC,CAAC,CAAC;IAEpG,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;IAC1F,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,2EAA2E,CAAC,CAAC;IACzF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC,CAAC;IAExF,qBAAqB;IACrB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,mBAAmB,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;MAmBR,CAAC,CACJ,CAAC;IAEF,sBAAsB;IACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,CAAC,GAAG,gBAAgB,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IAEpC,mBAAmB;IACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;IAEvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAE1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;IAEpF,oBAAoB;IACpB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC,CAAC;IAExF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;IAE9D,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,+BAA+B,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,uCAAuC,CAAC,CAAC;IAC7F,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,sCAAsC,CAAC,CAAC;IAC1F,OAAO,CAAC,GAAG,CAAC,wBAAwB,GAAG,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,wBAAwB,CAAC,CAAC;IACtG,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,yCAAyC,CAAC,CAAC;IAC9F,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,wCAAwC,CAAC,CAAC;IAErG,SAAS;IACT,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,6CAA6C,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CACnG,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;IACxG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,wCAAwC,CAAC;SACrD,MAAM,CAAC,GAAG,EAAE;QACX,WAAW,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC"} \ No newline at end of file +{"version":3,"file":"help.command.js","sourceRoot":"","sources":["../../../src/cli/commands/help.command.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/cli/index.js b/dist/cli/index.js index 0a26553..586a044 100644 --- a/dist/cli/index.js +++ b/dist/cli/index.js @@ -27,7 +27,7 @@ program .option('--staged', 'Analyze staged changes (git diff --staged)') .option('--branch ', 'Analyze against specific branch') .option('--title ', 'PR title (auto-detected from git)') - .option('--provider ', 'AI provider (anthropic|openai|google)') + .option('--provider ', 'AI provider (anthropic|openai|google|zhipu)') .option('--model ', 'Specific model to use') .option('--agent', 'Force intelligent agent (recommended for large diffs)') .option('--summary', 'Show summary only') diff --git a/dist/cli/index.js.map b/dist/cli/index.js.map index f5b4186..01ab536 100644 --- a/dist/cli/index.js.map +++ b/dist/cli/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,sCAAsC;AACtC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACtE,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAC1C,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,oDAAoD;AACpD,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,eAAe,EAAE,4BAA4B,CAAC;KACrD,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC;KAC9C,MAAM,CAAC,UAAU,EAAE,4CAA4C,CAAC;KAChE,MAAM,CAAC,iBAAiB,EAAE,iCAAiC,CAAC;KAC5D,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC;KAC7D,MAAM,CAAC,uBAAuB,EAAE,uCAAuC,CAAC;KACxE,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;KAClD,MAAM,CAAC,SAAS,EAAE,uDAAuD,CAAC;KAC1E,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC;KACxC,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACpC,MAAM,CAAC,cAAc,EAAE,sBAAsB,CAAC;KAC9C,MAAM,CAAC,QAAQ,EAAE,0BAA0B,EAAE,IAAI,CAAC;KAClD,MAAM,CAAC,aAAa,EAAE,kFAAkF,CAAC;KACzG,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,uBAAuB,EAAE,KAAK,CAAC;KACnD,MAAM,CAAC,SAAS,CAAC,CAAC;AAErB,iBAAiB;AACjB,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,eAAe;AACf,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,sBAAsB;AACtB,OAAO,CAAC,KAAK,EAAE,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,sCAAsC;AACtC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;AACtE,iCAAiC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAC5B,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,OAAO,CAAC,CAC1C,CAAC;AAEF,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,UAAU,CAAC;KAChB,WAAW,CAAC,4DAA4D,CAAC;KACzE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAEhC,oDAAoD;AACpD,OAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,eAAe,EAAE,4BAA4B,CAAC;KACrD,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC;KAC9C,MAAM,CAAC,UAAU,EAAE,4CAA4C,CAAC;KAChE,MAAM,CAAC,iBAAiB,EAAE,iCAAiC,CAAC;KAC5D,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC;KAC7D,MAAM,CAAC,uBAAuB,EAAE,6CAA6C,CAAC;KAC9E,MAAM,CAAC,iBAAiB,EAAE,uBAAuB,CAAC;KAClD,MAAM,CAAC,SAAS,EAAE,uDAAuD,CAAC;KAC1E,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC;KACxC,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC;KACpC,MAAM,CAAC,cAAc,EAAE,sBAAsB,CAAC;KAC9C,MAAM,CAAC,QAAQ,EAAE,0BAA0B,EAAE,IAAI,CAAC;KAClD,MAAM,CAAC,aAAa,EAAE,kFAAkF,CAAC;KACzG,MAAM,CAAC,sBAAsB,EAAE,yBAAyB,EAAE,KAAK,CAAC;KAChE,MAAM,CAAC,WAAW,EAAE,uBAAuB,EAAE,KAAK,CAAC;KACnD,MAAM,CAAC,SAAS,CAAC,CAAC;AAErB,iBAAiB;AACjB,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAE/B,eAAe;AACf,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,sBAAsB;AACtB,OAAO,CAAC,KAAK,EAAE,CAAC"} \ No newline at end of file diff --git a/dist/cli/utils/config-loader.d.ts b/dist/cli/utils/config-loader.d.ts index a39e635..1658d57 100644 --- a/dist/cli/utils/config-loader.d.ts +++ b/dist/cli/utils/config-loader.d.ts @@ -3,6 +3,7 @@ export interface UserConfig { anthropic?: string; openai?: string; google?: string; + zhipu?: string; }; ai?: { provider?: string; @@ -29,6 +30,28 @@ export interface UserConfig { showStrategy?: boolean; showRecommendations?: boolean; }; + /** + * Peer Review configuration - integrates with issue trackers (Jira, etc.) + * to validate PRs against tickets and acceptance criteria + */ + peerReview?: { + enabled?: boolean; + provider?: string; + useMcp?: boolean; + instanceUrl?: string; + email?: string; + apiToken?: string; + defaultProject?: string; + acceptanceCriteriaField?: string; + storyPointsField?: string; + ticketPatterns?: string[]; + analyzeAcceptanceCriteria?: boolean; + rateTicketQuality?: boolean; + generateTestSuggestions?: boolean; + checkScopeCreep?: boolean; + includeTicketDetails?: boolean; + verbose?: boolean; + }; } /** * Find config file in current directory or parent directories diff --git a/dist/cli/utils/config-loader.js b/dist/cli/utils/config-loader.js index 43cb91a..137458f 100644 --- a/dist/cli/utils/config-loader.js +++ b/dist/cli/utils/config-loader.js @@ -130,6 +130,7 @@ export function getApiKey(provider, config) { anthropic: 'ANTHROPIC_API_KEY', openai: 'OPENAI_API_KEY', google: 'GOOGLE_API_KEY', + zhipu: 'ZHIPU_API_KEY', }; const envVar = envVarMap[provider.toLowerCase()]; if (envVar) { diff --git a/dist/cli/utils/config-loader.js.map b/dist/cli/utils/config-loader.js.map index d5a9e9d..0168443 100644 --- a/dist/cli/utils/config-loader.js.map +++ b/dist/cli/utils/config-loader.js.map @@ -1 +1 @@ -{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../../src/cli/utils/config-loader.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../../src/cli/utils/config-loader.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index ea02011..d08cd61 100644 --- a/dist/index.js +++ b/dist/index.js @@ -36482,763 +36482,6 @@ function parseParams (str) { module.exports = parseParams -/***/ }), - -/***/ 2561: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.InternalServerError = exports.RateLimitError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIUserAbortError = exports.APIError = exports.AnthropicError = void 0; -const errors_1 = __nccwpck_require__(7038); -class AnthropicError extends Error { -} -exports.AnthropicError = AnthropicError; -class APIError extends AnthropicError { - constructor(status, error, message, headers) { - super(`${APIError.makeMessage(status, error, message)}`); - this.status = status; - this.headers = headers; - this.requestID = headers?.get('request-id'); - this.error = error; - } - static makeMessage(status, error, message) { - const msg = error?.message ? - typeof error.message === 'string' ? - error.message - : JSON.stringify(error.message) - : error ? JSON.stringify(error) - : message; - if (status && msg) { - return `${status} ${msg}`; - } - if (status) { - return `${status} status code (no body)`; - } - if (msg) { - return msg; - } - return '(no status code or body)'; - } - static generate(status, errorResponse, message, headers) { - if (!status || !headers) { - return new APIConnectionError({ message, cause: (0, errors_1.castToError)(errorResponse) }); - } - const error = errorResponse; - if (status === 400) { - return new BadRequestError(status, error, message, headers); - } - if (status === 401) { - return new AuthenticationError(status, error, message, headers); - } - if (status === 403) { - return new PermissionDeniedError(status, error, message, headers); - } - if (status === 404) { - return new NotFoundError(status, error, message, headers); - } - if (status === 409) { - return new ConflictError(status, error, message, headers); - } - if (status === 422) { - return new UnprocessableEntityError(status, error, message, headers); - } - if (status === 429) { - return new RateLimitError(status, error, message, headers); - } - if (status >= 500) { - return new InternalServerError(status, error, message, headers); - } - return new APIError(status, error, message, headers); - } -} -exports.APIError = APIError; -class APIUserAbortError extends APIError { - constructor({ message } = {}) { - super(undefined, undefined, message || 'Request was aborted.', undefined); - } -} -exports.APIUserAbortError = APIUserAbortError; -class APIConnectionError extends APIError { - constructor({ message, cause }) { - super(undefined, undefined, message || 'Connection error.', undefined); - // in some environments the 'cause' property is already declared - // @ts-ignore - if (cause) - this.cause = cause; - } -} -exports.APIConnectionError = APIConnectionError; -class APIConnectionTimeoutError extends APIConnectionError { - constructor({ message } = {}) { - super({ message: message ?? 'Request timed out.' }); - } -} -exports.APIConnectionTimeoutError = APIConnectionTimeoutError; -class BadRequestError extends APIError { -} -exports.BadRequestError = BadRequestError; -class AuthenticationError extends APIError { -} -exports.AuthenticationError = AuthenticationError; -class PermissionDeniedError extends APIError { -} -exports.PermissionDeniedError = PermissionDeniedError; -class NotFoundError extends APIError { -} -exports.NotFoundError = NotFoundError; -class ConflictError extends APIError { -} -exports.ConflictError = ConflictError; -class UnprocessableEntityError extends APIError { -} -exports.UnprocessableEntityError = UnprocessableEntityError; -class RateLimitError extends APIError { -} -exports.RateLimitError = RateLimitError; -class InternalServerError extends APIError { -} -exports.InternalServerError = InternalServerError; -//# sourceMappingURL=error.js.map - -/***/ }), - -/***/ 7038: -/***/ ((__unused_webpack_module, exports) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.castToError = void 0; -exports.isAbortError = isAbortError; -function isAbortError(err) { - return (typeof err === 'object' && - err !== null && - // Spec-compliant fetch implementations - (('name' in err && err.name === 'AbortError') || - // Expo fetch - ('message' in err && String(err.message).includes('FetchRequestCanceledException')))); -} -const castToError = (err) => { - if (err instanceof Error) - return err; - if (typeof err === 'object' && err !== null) { - try { - if (Object.prototype.toString.call(err) === '[object Error]') { - // @ts-ignore - not all envs have native support for cause yet - const error = new Error(err.message, err.cause ? { cause: err.cause } : {}); - if (err.stack) - error.stack = err.stack; - // @ts-ignore - not all envs have native support for cause yet - if (err.cause && !error.cause) - error.cause = err.cause; - if (err.name) - error.name = err.name; - return error; - } - } - catch { } - try { - return new Error(JSON.stringify(err)); - } - catch { } - } - return new Error(err); -}; -exports.castToError = castToError; -//# sourceMappingURL=errors.js.map - -/***/ }), - -/***/ 4253: -/***/ ((__unused_webpack_module, exports) => { - - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.__setModuleDefault = exports.__createBinding = void 0; -exports.__classPrivateFieldSet = __classPrivateFieldSet; -exports.__classPrivateFieldGet = __classPrivateFieldGet; -exports.__exportStar = __exportStar; -exports.__importStar = __importStar; -function __classPrivateFieldSet(receiver, state, value, kind, f) { - if (kind === "m") - throw new TypeError("Private method is not writable"); - if (kind === "a" && !f) - throw new TypeError("Private accessor was defined without a setter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) - throw new TypeError("Cannot write private member to an object whose class did not declare it"); - return kind === "a" ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value; -} -function __classPrivateFieldGet(receiver, state, kind, f) { - if (kind === "a" && !f) - throw new TypeError("Private accessor was defined without a getter"); - if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) - throw new TypeError("Cannot read private member from an object whose class did not declare it"); - return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); -} -var __createBinding = Object.create - ? function (o, m, k, k2) { - if (k2 === void 0) - k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; - }, - }; - } - Object.defineProperty(o, k2, desc); - } - : function (o, m, k, k2) { - if (k2 === void 0) - k2 = k; - o[k2] = m[k]; - }; -exports.__createBinding = __createBinding; -function __exportStar(m, o) { - for (var p in m) - if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) - __createBinding(o, m, p); -} -var __setModuleDefault = Object.create - ? function (o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); - } - : function (o, v) { - o["default"] = v; - }; -exports.__setModuleDefault = __setModuleDefault; -var ownKeys = function (o) { - ownKeys = - Object.getOwnPropertyNames || - function (o2) { - var ar = []; - for (var k in o2) - if (Object.prototype.hasOwnProperty.call(o2, k)) - ar[ar.length] = k; - return ar; - }; - return ownKeys(o); -}; -function __importStar(mod) { - if (mod && mod.__esModule) - return mod; - var result = {}; - if (mod != null) { - for (var k = ownKeys(mod), i = 0; i < k.length; i++) - if (k[i] !== "default") - __createBinding(result, mod, k[i]); - } - __setModuleDefault(result, mod); - return result; -} - - -/***/ }), - -/***/ 3348: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -const tslib_1 = __nccwpck_require__(4253); -tslib_1.__exportStar(__nccwpck_require__(537), exports); -tslib_1.__exportStar(__nccwpck_require__(2695), exports); -tslib_1.__exportStar(__nccwpck_require__(4644), exports); -tslib_1.__exportStar(__nccwpck_require__(4685), exports); -tslib_1.__exportStar(__nccwpck_require__(4248), exports); -tslib_1.__exportStar(__nccwpck_require__(2752), exports); -//# sourceMappingURL=utils.js.map - -/***/ }), - -/***/ 2695: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.fromBase64 = exports.toBase64 = void 0; -const error_1 = __nccwpck_require__(2561); -const bytes_1 = __nccwpck_require__(688); -const toBase64 = (data) => { - if (!data) - return ''; - if (typeof globalThis.Buffer !== 'undefined') { - return globalThis.Buffer.from(data).toString('base64'); - } - if (typeof data === 'string') { - data = (0, bytes_1.encodeUTF8)(data); - } - if (typeof btoa !== 'undefined') { - return btoa(String.fromCharCode.apply(null, data)); - } - throw new error_1.AnthropicError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); -}; -exports.toBase64 = toBase64; -const fromBase64 = (str) => { - if (typeof globalThis.Buffer !== 'undefined') { - const buf = globalThis.Buffer.from(str, 'base64'); - return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); - } - if (typeof atob !== 'undefined') { - const bstr = atob(str); - const buf = new Uint8Array(bstr.length); - for (let i = 0; i < bstr.length; i++) { - buf[i] = bstr.charCodeAt(i); - } - return buf; - } - throw new error_1.AnthropicError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined'); -}; -exports.fromBase64 = fromBase64; -//# sourceMappingURL=base64.js.map - -/***/ }), - -/***/ 688: -/***/ ((__unused_webpack_module, exports) => { - - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.concatBytes = concatBytes; -exports.encodeUTF8 = encodeUTF8; -exports.decodeUTF8 = decodeUTF8; -function concatBytes(buffers) { - let length = 0; - for (const buffer of buffers) { - length += buffer.length; - } - const output = new Uint8Array(length); - let index = 0; - for (const buffer of buffers) { - output.set(buffer, index); - index += buffer.length; - } - return output; -} -let encodeUTF8_; -function encodeUTF8(str) { - let encoder; - return (encodeUTF8_ ?? - ((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str); -} -let decodeUTF8_; -function decodeUTF8(bytes) { - let decoder; - return (decodeUTF8_ ?? - ((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes); -} -//# sourceMappingURL=bytes.js.map - -/***/ }), - -/***/ 4644: -/***/ ((__unused_webpack_module, exports) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.readEnv = void 0; -/** - * Read an environment variable. - * - * Trims beginning and trailing whitespace. - * - * Will return undefined if the environment variable doesn't exist or cannot be accessed. - */ -const readEnv = (env) => { - if (typeof globalThis.process !== 'undefined') { - return globalThis.process.env?.[env]?.trim() ?? undefined; - } - if (typeof globalThis.Deno !== 'undefined') { - return globalThis.Deno.env?.get?.(env)?.trim(); - } - return undefined; -}; -exports.readEnv = readEnv; -//# sourceMappingURL=env.js.map - -/***/ }), - -/***/ 4685: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.formatRequestDetails = exports.parseLogLevel = void 0; -exports.loggerFor = loggerFor; -const values_1 = __nccwpck_require__(537); -const levelNumbers = { - off: 0, - error: 200, - warn: 300, - info: 400, - debug: 500, -}; -const parseLogLevel = (maybeLevel, sourceName, client) => { - if (!maybeLevel) { - return undefined; - } - if ((0, values_1.hasOwn)(levelNumbers, maybeLevel)) { - return maybeLevel; - } - loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`); - return undefined; -}; -exports.parseLogLevel = parseLogLevel; -function noop() { } -function makeLogFn(fnLevel, logger, logLevel) { - if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) { - return noop; - } - else { - // Don't wrap logger functions, we want the stacktrace intact! - return logger[fnLevel].bind(logger); - } -} -const noopLogger = { - error: noop, - warn: noop, - info: noop, - debug: noop, -}; -let cachedLoggers = /* @__PURE__ */ new WeakMap(); -function loggerFor(client) { - const logger = client.logger; - const logLevel = client.logLevel ?? 'off'; - if (!logger) { - return noopLogger; - } - const cachedLogger = cachedLoggers.get(logger); - if (cachedLogger && cachedLogger[0] === logLevel) { - return cachedLogger[1]; - } - const levelLogger = { - error: makeLogFn('error', logger, logLevel), - warn: makeLogFn('warn', logger, logLevel), - info: makeLogFn('info', logger, logLevel), - debug: makeLogFn('debug', logger, logLevel), - }; - cachedLoggers.set(logger, [logLevel, levelLogger]); - return levelLogger; -} -const formatRequestDetails = (details) => { - if (details.options) { - details.options = { ...details.options }; - delete details.options['headers']; // redundant + leaks internals - } - if (details.headers) { - details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [ - name, - (name.toLowerCase() === 'x-api-key' || - name.toLowerCase() === 'authorization' || - name.toLowerCase() === 'cookie' || - name.toLowerCase() === 'set-cookie') ? - '***' - : value, - ])); - } - if ('retryOfRequestLogID' in details) { - if (details.retryOfRequestLogID) { - details.retryOf = details.retryOfRequestLogID; - } - delete details.retryOfRequestLogID; - } - return details; -}; -exports.formatRequestDetails = formatRequestDetails; -//# sourceMappingURL=log.js.map - -/***/ }), - -/***/ 2752: -/***/ ((__unused_webpack_module, exports) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.sleep = void 0; -const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); -exports.sleep = sleep; -//# sourceMappingURL=sleep.js.map - -/***/ }), - -/***/ 4248: -/***/ ((__unused_webpack_module, exports) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.uuid4 = void 0; -/** - * https://stackoverflow.com/a/2117523 - */ -let uuid4 = function () { - const { crypto } = globalThis; - if (crypto?.randomUUID) { - exports.uuid4 = crypto.randomUUID.bind(crypto); - return crypto.randomUUID(); - } - const u8 = new Uint8Array(1); - const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff; - return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16)); -}; -exports.uuid4 = uuid4; -//# sourceMappingURL=uuid.js.map - -/***/ }), - -/***/ 537: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - - -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.pop = exports.safeJSON = exports.maybeCoerceBoolean = exports.maybeCoerceFloat = exports.maybeCoerceInteger = exports.coerceBoolean = exports.coerceFloat = exports.coerceInteger = exports.validatePositiveInteger = exports.ensurePresent = exports.isReadonlyArray = exports.isArray = exports.isAbsoluteURL = void 0; -exports.maybeObj = maybeObj; -exports.isEmptyObj = isEmptyObj; -exports.hasOwn = hasOwn; -exports.isObj = isObj; -const error_1 = __nccwpck_require__(2561); -// https://url.spec.whatwg.org/#url-scheme-string -const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i; -const isAbsoluteURL = (url) => { - return startsWithSchemeRegexp.test(url); -}; -exports.isAbsoluteURL = isAbsoluteURL; -let isArray = (val) => ((exports.isArray = Array.isArray), (0, exports.isArray)(val)); -exports.isArray = isArray; -exports.isReadonlyArray = exports.isArray; -/** Returns an object if the given value isn't an object, otherwise returns as-is */ -function maybeObj(x) { - if (typeof x !== 'object') { - return {}; - } - return x ?? {}; -} -// https://stackoverflow.com/a/34491287 -function isEmptyObj(obj) { - if (!obj) - return true; - for (const _k in obj) - return false; - return true; -} -// https://eslint.org/docs/latest/rules/no-prototype-builtins -function hasOwn(obj, key) { - return Object.prototype.hasOwnProperty.call(obj, key); -} -function isObj(obj) { - return obj != null && typeof obj === 'object' && !Array.isArray(obj); -} -const ensurePresent = (value) => { - if (value == null) { - throw new error_1.AnthropicError(`Expected a value to be given but received ${value} instead.`); - } - return value; -}; -exports.ensurePresent = ensurePresent; -const validatePositiveInteger = (name, n) => { - if (typeof n !== 'number' || !Number.isInteger(n)) { - throw new error_1.AnthropicError(`${name} must be an integer`); - } - if (n < 0) { - throw new error_1.AnthropicError(`${name} must be a positive integer`); - } - return n; -}; -exports.validatePositiveInteger = validatePositiveInteger; -const coerceInteger = (value) => { - if (typeof value === 'number') - return Math.round(value); - if (typeof value === 'string') - return parseInt(value, 10); - throw new error_1.AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`); -}; -exports.coerceInteger = coerceInteger; -const coerceFloat = (value) => { - if (typeof value === 'number') - return value; - if (typeof value === 'string') - return parseFloat(value); - throw new error_1.AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`); -}; -exports.coerceFloat = coerceFloat; -const coerceBoolean = (value) => { - if (typeof value === 'boolean') - return value; - if (typeof value === 'string') - return value === 'true'; - return Boolean(value); -}; -exports.coerceBoolean = coerceBoolean; -const maybeCoerceInteger = (value) => { - if (value == null) { - return undefined; - } - return (0, exports.coerceInteger)(value); -}; -exports.maybeCoerceInteger = maybeCoerceInteger; -const maybeCoerceFloat = (value) => { - if (value == null) { - return undefined; - } - return (0, exports.coerceFloat)(value); -}; -exports.maybeCoerceFloat = maybeCoerceFloat; -const maybeCoerceBoolean = (value) => { - if (value == null) { - return undefined; - } - return (0, exports.coerceBoolean)(value); -}; -exports.maybeCoerceBoolean = maybeCoerceBoolean; -const safeJSON = (text) => { - try { - return JSON.parse(text); - } - catch (err) { - return undefined; - } -}; -exports.safeJSON = safeJSON; -// Gets a value from an object, deletes the key, and returns the value (or undefined if not found) -const pop = (obj, key) => { - const value = obj[key]; - delete obj[key]; - return value; -}; -exports.pop = pop; -//# sourceMappingURL=values.js.map - -/***/ }), - -/***/ 1252: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -var __webpack_unused_export__; - -__webpack_unused_export__ = ({ value: true }); -exports.W = transformJSONSchema; -const utils_1 = __nccwpck_require__(3348); -// Supported string formats -const SUPPORTED_STRING_FORMATS = new Set([ - 'date-time', - 'time', - 'date', - 'duration', - 'email', - 'hostname', - 'uri', - 'ipv4', - 'ipv6', - 'uuid', -]); -function deepClone(obj) { - return JSON.parse(JSON.stringify(obj)); -} -function transformJSONSchema(jsonSchema) { - const workingCopy = deepClone(jsonSchema); - return _transformJSONSchema(workingCopy); -} -function _transformJSONSchema(jsonSchema) { - const strictSchema = {}; - const ref = (0, utils_1.pop)(jsonSchema, '$ref'); - if (ref !== undefined) { - strictSchema['$ref'] = ref; - return strictSchema; - } - const defs = (0, utils_1.pop)(jsonSchema, '$defs'); - if (defs !== undefined) { - const strictDefs = {}; - strictSchema['$defs'] = strictDefs; - for (const [name, defSchema] of Object.entries(defs)) { - strictDefs[name] = _transformJSONSchema(defSchema); - } - } - const type = (0, utils_1.pop)(jsonSchema, 'type'); - const anyOf = (0, utils_1.pop)(jsonSchema, 'anyOf'); - const oneOf = (0, utils_1.pop)(jsonSchema, 'oneOf'); - const allOf = (0, utils_1.pop)(jsonSchema, 'allOf'); - if (Array.isArray(anyOf)) { - strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant)); - } - else if (Array.isArray(oneOf)) { - strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant)); - } - else if (Array.isArray(allOf)) { - strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry)); - } - else { - if (type === undefined) { - throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used'); - } - strictSchema['type'] = type; - } - const description = (0, utils_1.pop)(jsonSchema, 'description'); - if (description !== undefined) { - strictSchema['description'] = description; - } - const title = (0, utils_1.pop)(jsonSchema, 'title'); - if (title !== undefined) { - strictSchema['title'] = title; - } - if (type === 'object') { - const properties = (0, utils_1.pop)(jsonSchema, 'properties') || {}; - strictSchema['properties'] = Object.fromEntries(Object.entries(properties).map(([key, propSchema]) => [ - key, - _transformJSONSchema(propSchema), - ])); - (0, utils_1.pop)(jsonSchema, 'additionalProperties'); - strictSchema['additionalProperties'] = false; - const required = (0, utils_1.pop)(jsonSchema, 'required'); - if (required !== undefined) { - strictSchema['required'] = required; - } - } - else if (type === 'string') { - const format = (0, utils_1.pop)(jsonSchema, 'format'); - if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) { - strictSchema['format'] = format; - } - else if (format !== undefined) { - jsonSchema['format'] = format; - } - } - else if (type === 'array') { - const items = (0, utils_1.pop)(jsonSchema, 'items'); - if (items !== undefined) { - strictSchema['items'] = _transformJSONSchema(items); - } - const minItems = (0, utils_1.pop)(jsonSchema, 'minItems'); - if (minItems !== undefined && (minItems === 0 || minItems === 1)) { - strictSchema['minItems'] = minItems; - } - else if (minItems !== undefined) { - jsonSchema['minItems'] = minItems; - } - } - if (Object.keys(jsonSchema).length > 0) { - const existingDescription = strictSchema['description']; - strictSchema['description'] = - (existingDescription ? existingDescription + '\n\n' : '') + - '{' + - Object.entries(jsonSchema) - .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) - .join(', ') + - '}'; - } - return strictSchema; -} -//# sourceMappingURL=transform-json-schema.js.map - /***/ }) /******/ }); @@ -37385,6 +36628,223 @@ __nccwpck_require__.d(regexes_namespaceObject, { xid: () => (xid) }); +// NAMESPACE OBJECT: ./node_modules/zod/v4/classic/checks.js +var classic_checks_namespaceObject = {}; +__nccwpck_require__.r(classic_checks_namespaceObject); +__nccwpck_require__.d(classic_checks_namespaceObject, { + endsWith: () => (_endsWith), + gt: () => (_gt), + gte: () => (_gte), + includes: () => (_includes), + length: () => (_length), + lowercase: () => (_lowercase), + lt: () => (_lt), + lte: () => (_lte), + maxLength: () => (_maxLength), + maxSize: () => (_maxSize), + mime: () => (_mime), + minLength: () => (_minLength), + minSize: () => (_minSize), + multipleOf: () => (_multipleOf), + negative: () => (_negative), + nonnegative: () => (_nonnegative), + nonpositive: () => (_nonpositive), + normalize: () => (_normalize), + overwrite: () => (_overwrite), + positive: () => (_positive), + property: () => (_property), + regex: () => (_regex), + size: () => (_size), + slugify: () => (_slugify), + startsWith: () => (_startsWith), + toLowerCase: () => (_toLowerCase), + toUpperCase: () => (_toUpperCase), + trim: () => (_trim), + uppercase: () => (_uppercase) +}); + +// NAMESPACE OBJECT: ./node_modules/zod/v4/classic/iso.js +var iso_namespaceObject = {}; +__nccwpck_require__.r(iso_namespaceObject); +__nccwpck_require__.d(iso_namespaceObject, { + ZodISODate: () => (ZodISODate), + ZodISODateTime: () => (ZodISODateTime), + ZodISODuration: () => (ZodISODuration), + ZodISOTime: () => (ZodISOTime), + date: () => (iso_date), + datetime: () => (iso_datetime), + duration: () => (iso_duration), + time: () => (iso_time) +}); + +// NAMESPACE OBJECT: ./node_modules/zod/v4/classic/schemas.js +var classic_schemas_namespaceObject = {}; +__nccwpck_require__.r(classic_schemas_namespaceObject); +__nccwpck_require__.d(classic_schemas_namespaceObject, { + ZodAny: () => (schemas_ZodAny), + ZodArray: () => (schemas_ZodArray), + ZodBase64: () => (ZodBase64), + ZodBase64URL: () => (ZodBase64URL), + ZodBigInt: () => (schemas_ZodBigInt), + ZodBigIntFormat: () => (ZodBigIntFormat), + ZodBoolean: () => (schemas_ZodBoolean), + ZodCIDRv4: () => (ZodCIDRv4), + ZodCIDRv6: () => (ZodCIDRv6), + ZodCUID: () => (ZodCUID), + ZodCUID2: () => (ZodCUID2), + ZodCatch: () => (schemas_ZodCatch), + ZodCodec: () => (ZodCodec), + ZodCustom: () => (ZodCustom), + ZodCustomStringFormat: () => (ZodCustomStringFormat), + ZodDate: () => (schemas_ZodDate), + ZodDefault: () => (schemas_ZodDefault), + ZodDiscriminatedUnion: () => (schemas_ZodDiscriminatedUnion), + ZodE164: () => (ZodE164), + ZodEmail: () => (ZodEmail), + ZodEmoji: () => (ZodEmoji), + ZodEnum: () => (schemas_ZodEnum), + ZodFile: () => (ZodFile), + ZodFunction: () => (schemas_ZodFunction), + ZodGUID: () => (ZodGUID), + ZodIPv4: () => (ZodIPv4), + ZodIPv6: () => (ZodIPv6), + ZodIntersection: () => (schemas_ZodIntersection), + ZodJWT: () => (ZodJWT), + ZodKSUID: () => (ZodKSUID), + ZodLazy: () => (schemas_ZodLazy), + ZodLiteral: () => (schemas_ZodLiteral), + ZodMAC: () => (ZodMAC), + ZodMap: () => (schemas_ZodMap), + ZodNaN: () => (schemas_ZodNaN), + ZodNanoID: () => (ZodNanoID), + ZodNever: () => (schemas_ZodNever), + ZodNonOptional: () => (ZodNonOptional), + ZodNull: () => (schemas_ZodNull), + ZodNullable: () => (schemas_ZodNullable), + ZodNumber: () => (schemas_ZodNumber), + ZodNumberFormat: () => (ZodNumberFormat), + ZodObject: () => (schemas_ZodObject), + ZodOptional: () => (schemas_ZodOptional), + ZodPipe: () => (ZodPipe), + ZodPrefault: () => (ZodPrefault), + ZodPromise: () => (schemas_ZodPromise), + ZodReadonly: () => (schemas_ZodReadonly), + ZodRecord: () => (schemas_ZodRecord), + ZodSet: () => (schemas_ZodSet), + ZodString: () => (schemas_ZodString), + ZodStringFormat: () => (ZodStringFormat), + ZodSuccess: () => (ZodSuccess), + ZodSymbol: () => (schemas_ZodSymbol), + ZodTemplateLiteral: () => (ZodTemplateLiteral), + ZodTransform: () => (ZodTransform), + ZodTuple: () => (schemas_ZodTuple), + ZodType: () => (schemas_ZodType), + ZodULID: () => (ZodULID), + ZodURL: () => (ZodURL), + ZodUUID: () => (ZodUUID), + ZodUndefined: () => (schemas_ZodUndefined), + ZodUnion: () => (schemas_ZodUnion), + ZodUnknown: () => (schemas_ZodUnknown), + ZodVoid: () => (schemas_ZodVoid), + ZodXID: () => (ZodXID), + ZodXor: () => (ZodXor), + _ZodString: () => (_ZodString), + _default: () => (schemas_default), + _function: () => (_function), + any: () => (any), + array: () => (array), + base64: () => (schemas_base64), + base64url: () => (schemas_base64url), + bigint: () => (schemas_bigint), + boolean: () => (schemas_boolean), + "catch": () => (schemas_catch), + check: () => (check), + cidrv4: () => (schemas_cidrv4), + cidrv6: () => (schemas_cidrv6), + codec: () => (codec), + cuid: () => (schemas_cuid), + cuid2: () => (schemas_cuid2), + custom: () => (schemas_custom), + date: () => (schemas_date), + describe: () => (schemas_describe), + discriminatedUnion: () => (discriminatedUnion), + e164: () => (schemas_e164), + email: () => (schemas_email), + emoji: () => (schemas_emoji), + "enum": () => (schemas_enum), + file: () => (file), + float32: () => (float32), + float64: () => (float64), + "function": () => (_function), + guid: () => (schemas_guid), + hash: () => (hash), + hex: () => (schemas_hex), + hostname: () => (schemas_hostname), + httpUrl: () => (httpUrl), + "instanceof": () => (_instanceof), + int: () => (schemas_int), + int32: () => (int32), + int64: () => (int64), + intersection: () => (intersection), + ipv4: () => (schemas_ipv4), + ipv6: () => (schemas_ipv6), + json: () => (json), + jwt: () => (jwt), + keyof: () => (keyof), + ksuid: () => (schemas_ksuid), + lazy: () => (lazy), + literal: () => (literal), + looseObject: () => (looseObject), + looseRecord: () => (looseRecord), + mac: () => (schemas_mac), + map: () => (map), + meta: () => (schemas_meta), + nan: () => (nan), + nanoid: () => (schemas_nanoid), + nativeEnum: () => (nativeEnum), + never: () => (schemas_never), + nonoptional: () => (nonoptional), + "null": () => (schemas_null), + nullable: () => (nullable), + nullish: () => (schemas_nullish), + number: () => (schemas_number), + object: () => (object), + optional: () => (optional), + partialRecord: () => (partialRecord), + pipe: () => (pipe), + prefault: () => (prefault), + preprocess: () => (preprocess), + promise: () => (promise), + readonly: () => (readonly), + record: () => (record), + refine: () => (refine), + set: () => (set), + strictObject: () => (strictObject), + string: () => (schemas_string), + stringFormat: () => (stringFormat), + stringbool: () => (stringbool), + success: () => (success), + superRefine: () => (superRefine), + symbol: () => (symbol), + templateLiteral: () => (templateLiteral), + transform: () => (transform), + tuple: () => (tuple), + uint32: () => (uint32), + uint64: () => (uint64), + ulid: () => (schemas_ulid), + undefined: () => (schemas_undefined), + union: () => (union), + unknown: () => (unknown), + url: () => (url), + uuid: () => (schemas_uuid), + uuidv4: () => (uuidv4), + uuidv6: () => (uuidv6), + uuidv7: () => (schemas_uuidv7), + "void": () => (schemas_void), + xid: () => (schemas_xid), + xor: () => (xor) +}); + // EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js var core = __nccwpck_require__(7484); // EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js @@ -37439,10 +36899,107 @@ function mapKeys(fields, mapper, map) { //#endregion //# sourceMappingURL=map_keys.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/load/validation.js +//#region src/load/validation.ts +/** +* Sentinel key used to mark escaped user objects during serialization. +* +* When a plain object contains 'lc' key (which could be confused with LC objects), +* we wrap it as `{"__lc_escaped__": {...original...}}`. +*/ +const LC_ESCAPED_KEY = "__lc_escaped__"; +/** +* Check if an object needs escaping to prevent confusion with LC objects. +* +* An object needs escaping if: +* 1. It has an `'lc'` key (could be confused with LC serialization format) +* 2. It has only the escape key (would be mistaken for an escaped object) +*/ +function needsEscaping(obj) { + return "lc" in obj || Object.keys(obj).length === 1 && LC_ESCAPED_KEY in obj; +} +/** +* Wrap an object in the escape marker. +* +* @example +* ```typescript +* {"key": "value"} // becomes {"__lc_escaped__": {"key": "value"}} +* ``` +*/ +function escapeObject(obj) { + return { [LC_ESCAPED_KEY]: obj }; +} +/** +* Check if an object is an escaped user object. +* +* @example +* ```typescript +* {"__lc_escaped__": {...}} // is an escaped object +* ``` +*/ +function isEscapedObject(obj) { + return Object.keys(obj).length === 1 && LC_ESCAPED_KEY in obj; +} +/** +* Check if an object looks like a Serializable instance (duck typing). +*/ +function isSerializableLike(obj) { + return obj !== null && typeof obj === "object" && "lc_serializable" in obj && typeof obj.toJSON === "function"; +} +/** +* Escape a value if it needs escaping (contains `lc` key). +* +* This is a simpler version of `serializeValue` that doesn't handle Serializable +* objects - it's meant to be called on kwargs values that have already been +* processed by `toJSON()`. +* +* @param value - The value to potentially escape. +* @returns The value with any `lc`-containing objects wrapped in escape markers. +*/ +function escapeIfNeeded(value) { + if (value !== null && typeof value === "object" && !Array.isArray(value)) { + if (isSerializableLike(value)) return value; + const record = value; + if (needsEscaping(record)) return escapeObject(record); + const result = {}; + for (const [key, val] of Object.entries(record)) result[key] = escapeIfNeeded(val); + return result; + } + if (Array.isArray(value)) return value.map((item) => escapeIfNeeded(item)); + return value; +} +/** +* Unescape a value, processing escape markers in object values and arrays. +* +* When an escaped object is encountered (`{"__lc_escaped__": ...}`), it's +* unwrapped and the contents are returned AS-IS (no further processing). +* The contents represent user data that should not be modified. +* +* For regular objects and arrays, we recurse to find any nested escape markers. +* +* @param obj - The value to unescape. +* @returns The unescaped value. +*/ +function unescapeValue(obj) { + if (obj !== null && typeof obj === "object" && !Array.isArray(obj)) { + const record = obj; + if (isEscapedObject(record)) return record[LC_ESCAPED_KEY]; + const result = {}; + for (const [key, value] of Object.entries(record)) result[key] = unescapeValue(value); + return result; + } + if (Array.isArray(obj)) return obj.map((item) => unescapeValue(item)); + return obj; +} + +//#endregion + +//# sourceMappingURL=validation.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/load/serializable.js + //#region src/load/serializable.ts var serializable_exports = {}; __export(serializable_exports, { @@ -37564,11 +37121,15 @@ var Serializable = class Serializable { } if (last in read && read[last] !== void 0) write[last] = write[last] || read[last]; }); + const escapedKwargs = {}; + for (const [key, value] of Object.entries(kwargs)) escapedKwargs[key] = escapeIfNeeded(value); + const kwargsWithSecrets = Object.keys(secrets).length ? replaceSecrets(escapedKwargs, secrets) : escapedKwargs; + const processedKwargs = mapKeys(kwargsWithSecrets, keyToJson, aliases); return { lc: 1, type: "constructor", id: this.lc_id, - kwargs: mapKeys(Object.keys(secrets).length ? replaceSecrets(kwargs, secrets) : kwargs, keyToJson, aliases) + kwargs: processedKwargs }; } toJSONNotImplemented() { @@ -38606,7 +38167,7 @@ function convertToPrettyString(message) { lines.push(` ${tc.name} (${tc.id})`); lines.push(` Call ID: ${tc.id}`); lines.push(" Args:"); - for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${value}`); + for (const [key, value] of Object.entries(tc.args)) lines.push(` ${key}: ${typeof value === "object" ? JSON.stringify(value) : value}`); } } } @@ -38704,6 +38265,7 @@ var BaseMessage = class extends Serializable { } [MESSAGE_SYMBOL] = true; id; + /** @inheritdoc */ name; content; additional_kwargs; @@ -38825,8 +38387,9 @@ function _mergeDicts(left = {}, right = {}) { "name", "output_version", "model_provider" - ].includes(key)) merged[key] = value; - else merged[key] += value; + ].includes(key)) { + if (value) merged[key] = value; + } else merged[key] += value; else if (typeof merged[key] === "object" && !Array.isArray(merged[key])) merged[key] = _mergeDicts(merged[key], value); else if (Array.isArray(merged[key])) merged[key] = _mergeLists(merged[key], value); else if (merged[key] === value) continue; @@ -38854,8 +38417,8 @@ function _mergeLists(left, right) { } } function _mergeObj(left, right) { - if (!left && !right) throw new Error("Cannot merge two undefined objects."); - if (!left || !right) return left || right; + if (left === void 0 && right === void 0) return void 0; + if (left === void 0 || right === void 0) return left ?? right; else if (typeof left !== typeof right) throw new Error(`Cannot merge objects of different types.\nLeft ${typeof left}\nRight ${typeof right}`); else if (typeof left === "string" && typeof right === "string") return left + right; else if (Array.isArray(left) && Array.isArray(right)) return _mergeLists(left, right); @@ -38959,42 +38522,632 @@ var ToolMessage = class extends BaseMessage { static isInstance(message) { return super.isInstance(message) && message.type === "tool"; } - get _printableFields() { - return { - ...super._printableFields, - tool_call_id: this.tool_call_id, - artifact: this.artifact - }; + get _printableFields() { + return { + ...super._printableFields, + tool_call_id: this.tool_call_id, + artifact: this.artifact + }; + } +}; +/** +* Represents a chunk of a tool message, which can be concatenated +* with other tool message chunks. +*/ +var ToolMessageChunk = class extends BaseMessageChunk { + type = "tool"; + tool_call_id; + /** + * Status of the tool invocation. + * @version 0.2.19 + */ + status; + /** + * Artifact of the Tool execution which is not meant to be sent to the model. + * + * Should only be specified if it is different from the message content, e.g. if only + * a subset of the full tool output is being passed as message content but the full + * output is needed in other parts of the code. + */ + artifact; + constructor(fields) { + super(fields); + this.tool_call_id = fields.tool_call_id; + this.artifact = fields.artifact; + this.status = fields.status; + } + static lc_name() { + return "ToolMessageChunk"; + } + concat(chunk) { + const Cls = this.constructor; + return new Cls({ + content: mergeContent(this.content, chunk.content), + additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), + response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), + artifact: _mergeObj(this.artifact, chunk.artifact), + tool_call_id: this.tool_call_id, + id: this.id ?? chunk.id, + status: _mergeStatus(this.status, chunk.status) + }); + } + get _printableFields() { + return { + ...super._printableFields, + tool_call_id: this.tool_call_id, + artifact: this.artifact + }; + } +}; +function defaultToolCallParser(rawToolCalls) { + const toolCalls = []; + const invalidToolCalls = []; + for (const toolCall of rawToolCalls) if (!toolCall.function) continue; + else { + const functionName = toolCall.function.name; + try { + const functionArgs = JSON.parse(toolCall.function.arguments); + toolCalls.push({ + name: functionName || "", + args: functionArgs || {}, + id: toolCall.id + }); + } catch { + invalidToolCalls.push({ + name: functionName, + args: toolCall.function.arguments, + id: toolCall.id, + error: "Malformed args." + }); + } + } + return [toolCalls, invalidToolCalls]; +} +/** +* @deprecated Use {@link ToolMessage.isInstance} instead +*/ +function isToolMessage(x) { + return typeof x === "object" && x !== null && "getType" in x && typeof x.getType === "function" && x.getType() === "tool"; +} +/** +* @deprecated Use {@link ToolMessageChunk.isInstance} instead +*/ +function isToolMessageChunk(x) { + return x._getType() === "tool"; +} + +//#endregion + +//# sourceMappingURL=tool.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/errors/index.js +//#region src/errors/index.ts +function addLangChainErrorFields(error, lc_error_code) { + error.lc_error_code = lc_error_code; + error.message = `${error.message}\n\nTroubleshooting URL: https://docs.langchain.com/oss/javascript/langchain/errors/${lc_error_code}/\n`; + return error; +} + +//#endregion + +//# sourceMappingURL=index.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/tools/utils.js +//#region src/tools/utils.ts +function _isToolCall(toolCall) { + return !!(toolCall && typeof toolCall === "object" && "type" in toolCall && toolCall.type === "tool_call"); +} +function _configHasToolCallId(config) { + return !!(config && typeof config === "object" && "toolCall" in config && config.toolCall != null && typeof config.toolCall === "object" && "id" in config.toolCall && typeof config.toolCall.id === "string"); +} +/** +* Custom error class used to handle exceptions related to tool input parsing. +* It extends the built-in `Error` class and adds an optional `output` +* property that can hold the output that caused the exception. +*/ +var ToolInputParsingException = class extends Error { + output; + constructor(message, output) { + super(message); + this.output = output; + } +}; + +//#endregion + +//# sourceMappingURL=utils.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/json.js +//#region src/utils/json.ts +function parseJsonMarkdown(s, parser = parsePartialJson) { + s = s.trim(); + const firstFenceIndex = s.indexOf("```"); + if (firstFenceIndex === -1) return parser(s); + let contentAfterFence = s.substring(firstFenceIndex + 3); + if (contentAfterFence.startsWith("json\n")) contentAfterFence = contentAfterFence.substring(5); + else if (contentAfterFence.startsWith("json")) contentAfterFence = contentAfterFence.substring(4); + else if (contentAfterFence.startsWith("\n")) contentAfterFence = contentAfterFence.substring(1); + const closingFenceIndex = contentAfterFence.indexOf("```"); + let finalContent = contentAfterFence; + if (closingFenceIndex !== -1) finalContent = contentAfterFence.substring(0, closingFenceIndex); + return parser(finalContent.trim()); +} +/** +* Recursive descent partial JSON parser. +* @param s - The string to parse. +* @returns The parsed value. +* @throws Error if the input is a malformed JSON string. +*/ +function strictParsePartialJson(s) { + try { + return JSON.parse(s); + } catch {} + const buffer = s.trim(); + if (buffer.length === 0) throw new Error("Unexpected end of JSON input"); + let pos = 0; + function skipWhitespace() { + while (pos < buffer.length && /\s/.test(buffer[pos])) pos += 1; + } + function parseString() { + if (buffer[pos] !== "\"") throw new Error(`Expected '"' at position ${pos}, got '${buffer[pos]}'`); + pos += 1; + let result = ""; + let escaped = false; + while (pos < buffer.length) { + const char = buffer[pos]; + if (escaped) { + if (char === "n") result += "\n"; + else if (char === "t") result += " "; + else if (char === "r") result += "\r"; + else if (char === "\\") result += "\\"; + else if (char === "\"") result += "\""; + else if (char === "b") result += "\b"; + else if (char === "f") result += "\f"; + else if (char === "/") result += "/"; + else if (char === "u") { + const hex = buffer.substring(pos + 1, pos + 5); + if (/^[0-9A-Fa-f]{0,4}$/.test(hex)) { + if (hex.length === 4) result += String.fromCharCode(Number.parseInt(hex, 16)); + else result += `u${hex}`; + pos += hex.length; + } else throw new Error(`Invalid unicode escape sequence '\\u${hex}' at position ${pos}`); + } else throw new Error(`Invalid escape sequence '\\${char}' at position ${pos}`); + escaped = false; + } else if (char === "\\") escaped = true; + else if (char === "\"") { + pos += 1; + return result; + } else result += char; + pos += 1; + } + if (escaped) result += "\\"; + return result; + } + function parseNumber() { + const start = pos; + let numStr = ""; + if (buffer[pos] === "-") { + numStr += "-"; + pos += 1; + } + if (pos < buffer.length && buffer[pos] === "0") { + numStr += "0"; + pos += 1; + if (buffer[pos] >= "0" && buffer[pos] <= "9") throw new Error(`Invalid number at position ${start}`); + } + if (pos < buffer.length && buffer[pos] >= "1" && buffer[pos] <= "9") while (pos < buffer.length && buffer[pos] >= "0" && buffer[pos] <= "9") { + numStr += buffer[pos]; + pos += 1; + } + if (pos < buffer.length && buffer[pos] === ".") { + numStr += "."; + pos += 1; + while (pos < buffer.length && buffer[pos] >= "0" && buffer[pos] <= "9") { + numStr += buffer[pos]; + pos += 1; + } + } + if (pos < buffer.length && (buffer[pos] === "e" || buffer[pos] === "E")) { + numStr += buffer[pos]; + pos += 1; + if (pos < buffer.length && (buffer[pos] === "+" || buffer[pos] === "-")) { + numStr += buffer[pos]; + pos += 1; + } + while (pos < buffer.length && buffer[pos] >= "0" && buffer[pos] <= "9") { + numStr += buffer[pos]; + pos += 1; + } + } + if (numStr === "-") return -0; + const num = Number.parseFloat(numStr); + if (Number.isNaN(num)) { + pos = start; + throw new Error(`Invalid number '${numStr}' at position ${start}`); + } + return num; + } + function parseValue() { + skipWhitespace(); + if (pos >= buffer.length) throw new Error(`Unexpected end of input at position ${pos}`); + const char = buffer[pos]; + if (char === "{") return parseObject(); + if (char === "[") return parseArray(); + if (char === "\"") return parseString(); + if ("null".startsWith(buffer.substring(pos, pos + 4))) { + pos += Math.min(4, buffer.length - pos); + return null; + } + if ("true".startsWith(buffer.substring(pos, pos + 4))) { + pos += Math.min(4, buffer.length - pos); + return true; + } + if ("false".startsWith(buffer.substring(pos, pos + 5))) { + pos += Math.min(5, buffer.length - pos); + return false; + } + if (char === "-" || char >= "0" && char <= "9") return parseNumber(); + throw new Error(`Unexpected character '${char}' at position ${pos}`); + } + function parseArray() { + if (buffer[pos] !== "[") throw new Error(`Expected '[' at position ${pos}, got '${buffer[pos]}'`); + const arr = []; + pos += 1; + skipWhitespace(); + if (pos >= buffer.length) return arr; + if (buffer[pos] === "]") { + pos += 1; + return arr; + } + while (pos < buffer.length) { + skipWhitespace(); + if (pos >= buffer.length) return arr; + arr.push(parseValue()); + skipWhitespace(); + if (pos >= buffer.length) return arr; + if (buffer[pos] === "]") { + pos += 1; + return arr; + } else if (buffer[pos] === ",") { + pos += 1; + continue; + } + throw new Error(`Expected ',' or ']' at position ${pos}, got '${buffer[pos]}'`); + } + return arr; + } + function parseObject() { + if (buffer[pos] !== "{") throw new Error(`Expected '{' at position ${pos}, got '${buffer[pos]}'`); + const obj = {}; + pos += 1; + skipWhitespace(); + if (pos >= buffer.length) return obj; + if (buffer[pos] === "}") { + pos += 1; + return obj; + } + while (pos < buffer.length) { + skipWhitespace(); + if (pos >= buffer.length) return obj; + const key = parseString(); + skipWhitespace(); + if (pos >= buffer.length) return obj; + if (buffer[pos] !== ":") throw new Error(`Expected ':' at position ${pos}, got '${buffer[pos]}'`); + pos += 1; + skipWhitespace(); + if (pos >= buffer.length) return obj; + obj[key] = parseValue(); + skipWhitespace(); + if (pos >= buffer.length) return obj; + if (buffer[pos] === "}") { + pos += 1; + return obj; + } else if (buffer[pos] === ",") { + pos += 1; + continue; + } + throw new Error(`Expected ',' or '}' at position ${pos}, got '${buffer[pos]}'`); + } + return obj; + } + const value = parseValue(); + skipWhitespace(); + if (pos < buffer.length) throw new Error(`Unexpected character '${buffer[pos]}' at position ${pos}`); + return value; +} +function parsePartialJson(s) { + try { + if (typeof s === "undefined") return null; + return strictParsePartialJson(s); + } catch { + return null; + } +} + +//#endregion + +//# sourceMappingURL=json.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/chat.js + + +//#region src/messages/chat.ts +/** +* Represents a chat message in a conversation. +*/ +var ChatMessage = class ChatMessage extends BaseMessage { + static lc_name() { + return "ChatMessage"; + } + type = "generic"; + role; + static _chatMessageClass() { + return ChatMessage; + } + constructor(fields, role) { + if (typeof fields === "string" || Array.isArray(fields)) fields = { + content: fields, + role + }; + super(fields); + this.role = fields.role; + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "generic"; + } + get _printableFields() { + return { + ...super._printableFields, + role: this.role + }; + } +}; +/** +* Represents a chunk of a chat message, which can be concatenated with +* other chat message chunks. +*/ +var ChatMessageChunk = class extends BaseMessageChunk { + static lc_name() { + return "ChatMessageChunk"; + } + type = "generic"; + role; + constructor(fields, role) { + if (typeof fields === "string" || Array.isArray(fields)) fields = { + content: fields, + role + }; + super(fields); + this.role = fields.role; + } + concat(chunk) { + const Cls = this.constructor; + return new Cls({ + content: mergeContent(this.content, chunk.content), + additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), + response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), + role: this.role, + id: this.id ?? chunk.id + }); + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "generic"; + } + get _printableFields() { + return { + ...super._printableFields, + role: this.role + }; + } +}; +/** +* @deprecated Use {@link ChatMessage.isInstance} instead +*/ +function isChatMessage(x) { + return x._getType() === "generic"; +} +/** +* @deprecated Use {@link ChatMessageChunk.isInstance} instead +*/ +function isChatMessageChunk(x) { + return x._getType() === "generic"; +} + +//#endregion + +//# sourceMappingURL=chat.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/function.js + + +//#region src/messages/function.ts +/** +* Represents a function message in a conversation. +*/ +var FunctionMessage = class extends BaseMessage { + static lc_name() { + return "FunctionMessage"; + } + type = "function"; + name; + constructor(fields) { + super(fields); + this.name = fields.name; + } +}; +/** +* Represents a chunk of a function message, which can be concatenated +* with other function message chunks. +*/ +var FunctionMessageChunk = class extends BaseMessageChunk { + static lc_name() { + return "FunctionMessageChunk"; + } + type = "function"; + concat(chunk) { + const Cls = this.constructor; + return new Cls({ + content: mergeContent(this.content, chunk.content), + additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), + response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), + name: this.name ?? "", + id: this.id ?? chunk.id + }); + } +}; +function isFunctionMessage(x) { + return x._getType() === "function"; +} +function isFunctionMessageChunk(x) { + return x._getType() === "function"; +} + +//#endregion + +//# sourceMappingURL=function.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/human.js + + +//#region src/messages/human.ts +/** +* Represents a human message in a conversation. +*/ +var HumanMessage = class extends BaseMessage { + static lc_name() { + return "HumanMessage"; + } + type = "human"; + constructor(fields) { + super(fields); + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "human"; + } +}; +/** +* Represents a chunk of a human message, which can be concatenated with +* other human message chunks. +*/ +var HumanMessageChunk = class extends BaseMessageChunk { + static lc_name() { + return "HumanMessageChunk"; + } + type = "human"; + constructor(fields) { + super(fields); + } + concat(chunk) { + const Cls = this.constructor; + return new Cls({ + content: mergeContent(this.content, chunk.content), + additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), + response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), + id: this.id ?? chunk.id + }); + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "human"; + } +}; +/** +* @deprecated Use {@link HumanMessage.isInstance} instead +*/ +function isHumanMessage(x) { + return x.getType() === "human"; +} +/** +* @deprecated Use {@link HumanMessageChunk.isInstance} instead +*/ +function isHumanMessageChunk(x) { + return x.getType() === "human"; +} + +//#endregion + +//# sourceMappingURL=human.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/modifier.js + + +//#region src/messages/modifier.ts +/** +* Message responsible for deleting other messages. +*/ +var RemoveMessage = class extends BaseMessage { + type = "remove"; + /** + * The ID of the message to remove. + */ + id; + constructor(fields) { + super({ + ...fields, + content: [] + }); + this.id = fields.id; + } + get _printableFields() { + return { + ...super._printableFields, + id: this.id + }; + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "remove"; + } +}; + +//#endregion + +//# sourceMappingURL=modifier.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/system.js + + +//#region src/messages/system.ts +/** +* Represents a system message in a conversation. +*/ +var SystemMessage = class SystemMessage extends BaseMessage { + static lc_name() { + return "SystemMessage"; + } + type = "system"; + constructor(fields) { + super(fields); + } + /** + * Concatenates a string or another system message with the current system message. + * @param chunk - The chunk to concatenate with the system message. + * @returns A new system message with the concatenated content. + */ + concat(chunk) { + if (typeof chunk === "string") return new SystemMessage({ + ...this, + content: mergeContent(this.content, chunk) + }); + if (SystemMessage.isInstance(chunk)) return new SystemMessage({ + ...this, + additional_kwargs: { + ...this.additional_kwargs, + ...chunk.additional_kwargs + }, + response_metadata: { + ...this.response_metadata, + ...chunk.response_metadata + }, + content: mergeContent(this.content, chunk.content) + }); + throw new Error("Unexpected chunk type for system message"); + } + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "system"; } }; /** -* Represents a chunk of a tool message, which can be concatenated -* with other tool message chunks. +* Represents a chunk of a system message, which can be concatenated with +* other system message chunks. */ -var ToolMessageChunk = class extends BaseMessageChunk { - type = "tool"; - tool_call_id; - /** - * Status of the tool invocation. - * @version 0.2.19 - */ - status; - /** - * Artifact of the Tool execution which is not meant to be sent to the model. - * - * Should only be specified if it is different from the message content, e.g. if only - * a subset of the full tool output is being passed as message content but the full - * output is needed in other parts of the code. - */ - artifact; +var SystemMessageChunk = class extends BaseMessageChunk { + static lc_name() { + return "SystemMessageChunk"; + } + type = "system"; constructor(fields) { super(fields); - this.tool_call_id = fields.tool_call_id; - this.artifact = fields.artifact; - this.status = fields.status; - } - static lc_name() { - return "ToolMessageChunk"; } concat(chunk) { const Cls = this.constructor; @@ -39002,110 +39155,29 @@ var ToolMessageChunk = class extends BaseMessageChunk { content: mergeContent(this.content, chunk.content), additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), - artifact: _mergeObj(this.artifact, chunk.artifact), - tool_call_id: this.tool_call_id, - id: this.id ?? chunk.id, - status: _mergeStatus(this.status, chunk.status) + id: this.id ?? chunk.id }); } - get _printableFields() { - return { - ...super._printableFields, - tool_call_id: this.tool_call_id, - artifact: this.artifact - }; + static isInstance(obj) { + return super.isInstance(obj) && obj.type === "system"; } }; -function defaultToolCallParser(rawToolCalls) { - const toolCalls = []; - const invalidToolCalls = []; - for (const toolCall of rawToolCalls) if (!toolCall.function) continue; - else { - const functionName = toolCall.function.name; - try { - const functionArgs = JSON.parse(toolCall.function.arguments); - toolCalls.push({ - name: functionName || "", - args: functionArgs || {}, - id: toolCall.id - }); - } catch { - invalidToolCalls.push({ - name: functionName, - args: toolCall.function.arguments, - id: toolCall.id, - error: "Malformed args." - }); - } - } - return [toolCalls, invalidToolCalls]; -} /** -* @deprecated Use {@link ToolMessage.isInstance} instead +* @deprecated Use {@link SystemMessage.isInstance} instead */ -function isToolMessage(x) { - return typeof x === "object" && x !== null && "getType" in x && typeof x.getType === "function" && x.getType() === "tool"; +function isSystemMessage(x) { + return x._getType() === "system"; } /** -* @deprecated Use {@link ToolMessageChunk.isInstance} instead +* @deprecated Use {@link SystemMessageChunk.isInstance} instead */ -function isToolMessageChunk(x) { - return x._getType() === "tool"; -} - -//#endregion - -//# sourceMappingURL=tool.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/json.js -//#region src/utils/json.ts -function parseJsonMarkdown(s, parser = parsePartialJson) { - s = s.trim(); - const firstFenceIndex = s.indexOf("```"); - if (firstFenceIndex === -1) return parser(s); - let contentAfterFence = s.substring(firstFenceIndex + 3); - if (contentAfterFence.startsWith("json\n")) contentAfterFence = contentAfterFence.substring(5); - else if (contentAfterFence.startsWith("json")) contentAfterFence = contentAfterFence.substring(4); - else if (contentAfterFence.startsWith("\n")) contentAfterFence = contentAfterFence.substring(1); - const closingFenceIndex = contentAfterFence.indexOf("```"); - let finalContent = contentAfterFence; - if (closingFenceIndex !== -1) finalContent = contentAfterFence.substring(0, closingFenceIndex); - return parser(finalContent.trim()); -} -function parsePartialJson(s) { - if (typeof s === "undefined") return null; - try { - return JSON.parse(s); - } catch {} - let new_s = ""; - const stack = []; - let isInsideString = false; - let escaped = false; - for (let char of s) { - if (isInsideString) if (char === "\"" && !escaped) isInsideString = false; - else if (char === "\n" && !escaped) char = "\\n"; - else if (char === "\\") escaped = !escaped; - else escaped = false; - else if (char === "\"") { - isInsideString = true; - escaped = false; - } else if (char === "{") stack.push("}"); - else if (char === "[") stack.push("]"); - else if (char === "}" || char === "]") if (stack && stack[stack.length - 1] === char) stack.pop(); - else return null; - new_s += char; - } - if (isInsideString) new_s += "\""; - for (let i = stack.length - 1; i >= 0; i -= 1) new_s += stack[i]; - try { - return JSON.parse(new_s); - } catch { - return null; - } +function isSystemMessageChunk(x) { + return x._getType() === "system"; } //#endregion -//# sourceMappingURL=json.js.map +//# sourceMappingURL=system.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/block_translators/bedrock_converse.js @@ -39681,53 +39753,11 @@ var AIMessageChunk = class extends BaseMessageChunk { tool_call_chunks: [], usage_metadata: fields.usage_metadata !== void 0 ? fields.usage_metadata : void 0 }; - else { - const toolCallChunks = fields.tool_call_chunks ?? []; - const groupedToolCallChunks = toolCallChunks.reduce((acc, chunk) => { - const matchedChunkIndex = acc.findIndex(([match]) => { - if ("id" in chunk && chunk.id && "index" in chunk && chunk.index !== void 0) return chunk.id === match.id && chunk.index === match.index; - if ("id" in chunk && chunk.id) return chunk.id === match.id; - if ("index" in chunk && chunk.index !== void 0) return chunk.index === match.index; - return false; - }); - if (matchedChunkIndex !== -1) acc[matchedChunkIndex].push(chunk); - else acc.push([chunk]); - return acc; - }, []); - const toolCalls = []; - const invalidToolCalls = []; - for (const chunks of groupedToolCallChunks) { - let parsedArgs = null; - const name = chunks[0]?.name ?? ""; - const joinedArgs = chunks.map((c) => c.args || "").join(""); - const argsStr = joinedArgs.length ? joinedArgs : "{}"; - const id = chunks[0]?.id; - try { - parsedArgs = parsePartialJson(argsStr); - if (!id || parsedArgs === null || typeof parsedArgs !== "object" || Array.isArray(parsedArgs)) throw new Error("Malformed tool call chunk args."); - toolCalls.push({ - name, - args: parsedArgs, - id, - type: "tool_call" - }); - } catch { - invalidToolCalls.push({ - name, - args: argsStr, - id, - error: "Malformed args.", - type: "invalid_tool_call" - }); - } - } - initParams = { - ...fields, - tool_calls: toolCalls, - invalid_tool_calls: invalidToolCalls, - usage_metadata: fields.usage_metadata !== void 0 ? fields.usage_metadata : void 0 - }; - } + else initParams = { + ...fields, + ...collapseToolCallChunks(fields.tool_call_chunks ?? []), + usage_metadata: fields.usage_metadata !== void 0 ? fields.usage_metadata : void 0 + }; super(initParams); this.tool_call_chunks = initParams.tool_call_chunks ?? this.tool_call_chunks; this.tool_calls = initParams.tool_calls ?? this.tool_calls; @@ -39799,355 +39829,6 @@ var AIMessageChunk = class extends BaseMessageChunk { //#endregion //# sourceMappingURL=ai.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/chat.js - - -//#region src/messages/chat.ts -/** -* Represents a chat message in a conversation. -*/ -var ChatMessage = class ChatMessage extends BaseMessage { - static lc_name() { - return "ChatMessage"; - } - type = "generic"; - role; - static _chatMessageClass() { - return ChatMessage; - } - constructor(fields, role) { - if (typeof fields === "string" || Array.isArray(fields)) fields = { - content: fields, - role - }; - super(fields); - this.role = fields.role; - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "generic"; - } - get _printableFields() { - return { - ...super._printableFields, - role: this.role - }; - } -}; -/** -* Represents a chunk of a chat message, which can be concatenated with -* other chat message chunks. -*/ -var ChatMessageChunk = class extends BaseMessageChunk { - static lc_name() { - return "ChatMessageChunk"; - } - type = "generic"; - role; - constructor(fields, role) { - if (typeof fields === "string" || Array.isArray(fields)) fields = { - content: fields, - role - }; - super(fields); - this.role = fields.role; - } - concat(chunk) { - const Cls = this.constructor; - return new Cls({ - content: mergeContent(this.content, chunk.content), - additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), - response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), - role: this.role, - id: this.id ?? chunk.id - }); - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "generic"; - } - get _printableFields() { - return { - ...super._printableFields, - role: this.role - }; - } -}; -/** -* @deprecated Use {@link ChatMessage.isInstance} instead -*/ -function isChatMessage(x) { - return x._getType() === "generic"; -} -/** -* @deprecated Use {@link ChatMessageChunk.isInstance} instead -*/ -function isChatMessageChunk(x) { - return x._getType() === "generic"; -} - -//#endregion - -//# sourceMappingURL=chat.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/function.js - - -//#region src/messages/function.ts -/** -* Represents a function message in a conversation. -*/ -var FunctionMessage = class extends BaseMessage { - static lc_name() { - return "FunctionMessage"; - } - type = "function"; - name; - constructor(fields) { - super(fields); - this.name = fields.name; - } -}; -/** -* Represents a chunk of a function message, which can be concatenated -* with other function message chunks. -*/ -var FunctionMessageChunk = class extends BaseMessageChunk { - static lc_name() { - return "FunctionMessageChunk"; - } - type = "function"; - concat(chunk) { - const Cls = this.constructor; - return new Cls({ - content: mergeContent(this.content, chunk.content), - additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), - response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), - name: this.name ?? "", - id: this.id ?? chunk.id - }); - } -}; -function isFunctionMessage(x) { - return x._getType() === "function"; -} -function isFunctionMessageChunk(x) { - return x._getType() === "function"; -} - -//#endregion - -//# sourceMappingURL=function.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/human.js - - -//#region src/messages/human.ts -/** -* Represents a human message in a conversation. -*/ -var HumanMessage = class extends BaseMessage { - static lc_name() { - return "HumanMessage"; - } - type = "human"; - constructor(fields) { - super(fields); - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "human"; - } -}; -/** -* Represents a chunk of a human message, which can be concatenated with -* other human message chunks. -*/ -var HumanMessageChunk = class extends BaseMessageChunk { - static lc_name() { - return "HumanMessageChunk"; - } - type = "human"; - constructor(fields) { - super(fields); - } - concat(chunk) { - const Cls = this.constructor; - return new Cls({ - content: mergeContent(this.content, chunk.content), - additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), - response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), - id: this.id ?? chunk.id - }); - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "human"; - } -}; -/** -* @deprecated Use {@link HumanMessage.isInstance} instead -*/ -function isHumanMessage(x) { - return x.getType() === "human"; -} -/** -* @deprecated Use {@link HumanMessageChunk.isInstance} instead -*/ -function isHumanMessageChunk(x) { - return x.getType() === "human"; -} - -//#endregion - -//# sourceMappingURL=human.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/system.js - - -//#region src/messages/system.ts -/** -* Represents a system message in a conversation. -*/ -var SystemMessage = class SystemMessage extends BaseMessage { - static lc_name() { - return "SystemMessage"; - } - type = "system"; - constructor(fields) { - super(fields); - } - /** - * Concatenates a string or another system message with the current system message. - * @param chunk - The chunk to concatenate with the system message. - * @returns A new system message with the concatenated content. - */ - concat(chunk) { - if (typeof chunk === "string") return new SystemMessage({ - ...this, - content: mergeContent(this.content, chunk) - }); - if (SystemMessage.isInstance(chunk)) return new SystemMessage({ - ...this, - additional_kwargs: { - ...this.additional_kwargs, - ...chunk.additional_kwargs - }, - response_metadata: { - ...this.response_metadata, - ...chunk.response_metadata - }, - content: mergeContent(this.content, chunk.content) - }); - throw new Error("Unexpected chunk type for system message"); - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "system"; - } -}; -/** -* Represents a chunk of a system message, which can be concatenated with -* other system message chunks. -*/ -var SystemMessageChunk = class extends BaseMessageChunk { - static lc_name() { - return "SystemMessageChunk"; - } - type = "system"; - constructor(fields) { - super(fields); - } - concat(chunk) { - const Cls = this.constructor; - return new Cls({ - content: mergeContent(this.content, chunk.content), - additional_kwargs: _mergeDicts(this.additional_kwargs, chunk.additional_kwargs), - response_metadata: _mergeDicts(this.response_metadata, chunk.response_metadata), - id: this.id ?? chunk.id - }); - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "system"; - } -}; -/** -* @deprecated Use {@link SystemMessage.isInstance} instead -*/ -function isSystemMessage(x) { - return x._getType() === "system"; -} -/** -* @deprecated Use {@link SystemMessageChunk.isInstance} instead -*/ -function isSystemMessageChunk(x) { - return x._getType() === "system"; -} - -//#endregion - -//# sourceMappingURL=system.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/errors/index.js -//#region src/errors/index.ts -function addLangChainErrorFields(error, lc_error_code) { - error.lc_error_code = lc_error_code; - error.message = `${error.message}\n\nTroubleshooting URL: https://docs.langchain.com/oss/javascript/langchain/errors/${lc_error_code}/\n`; - return error; -} - -//#endregion - -//# sourceMappingURL=index.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/tools/utils.js -//#region src/tools/utils.ts -function _isToolCall(toolCall) { - return !!(toolCall && typeof toolCall === "object" && "type" in toolCall && toolCall.type === "tool_call"); -} -function _configHasToolCallId(config) { - return !!(config && typeof config === "object" && "toolCall" in config && config.toolCall != null && typeof config.toolCall === "object" && "id" in config.toolCall && typeof config.toolCall.id === "string"); -} -/** -* Custom error class used to handle exceptions related to tool input parsing. -* It extends the built-in `Error` class and adds an optional `output` -* property that can hold the output that caused the exception. -*/ -var ToolInputParsingException = class extends Error { - output; - constructor(message, output) { - super(message); - this.output = output; - } -}; - -//#endregion - -//# sourceMappingURL=utils.js.map -;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/modifier.js - - -//#region src/messages/modifier.ts -/** -* Message responsible for deleting other messages. -*/ -var RemoveMessage = class extends BaseMessage { - type = "remove"; - /** - * The ID of the message to remove. - */ - id; - constructor(fields) { - super({ - ...fields, - content: [] - }); - this.id = fields.id; - } - get _printableFields() { - return { - ...super._printableFields, - id: this.id - }; - } - static isInstance(obj) { - return super.isInstance(obj) && obj.type === "remove"; - } -}; - -//#endregion - -//# sourceMappingURL=modifier.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/messages/utils.js @@ -40160,6 +39841,7 @@ var RemoveMessage = class extends BaseMessage { + //#region src/messages/utils.ts /** * Immediately-invoked function expression. @@ -40347,6 +40029,77 @@ function convertToChunk(message) { else if (ChatMessage.isInstance(message)) return new ChatMessageChunk({ ...message }); else throw new Error("Unknown message type."); } +/** +* Collapses an array of tool call chunks into complete tool calls. +* +* This function groups tool call chunks by their id and/or index, then attempts to +* parse and validate the accumulated arguments for each group. Successfully parsed +* tool calls are returned as valid `ToolCall` objects, while malformed ones are +* returned as `InvalidToolCall` objects. +* +* @param chunks - An array of `ToolCallChunk` objects to collapse +* @returns An object containing: +* - `tool_call_chunks`: The original input chunks +* - `tool_calls`: An array of successfully parsed and validated tool calls +* - `invalid_tool_calls`: An array of tool calls that failed parsing or validation +* +* @remarks +* Chunks are grouped using the following matching logic: +* - If a chunk has both an id and index, it matches chunks with the same id and index +* - If a chunk has only an id, it matches chunks with the same id +* - If a chunk has only an index, it matches chunks with the same index +* +* For each group, the function: +* 1. Concatenates all `args` strings from the chunks +* 2. Attempts to parse the concatenated string as JSON +* 3. Validates that the result is a non-null object with a valid id +* 4. Creates either a `ToolCall` (if valid) or `InvalidToolCall` (if invalid) +*/ +function collapseToolCallChunks(chunks) { + const groupedToolCallChunks = chunks.reduce((acc, chunk) => { + const matchedChunkIndex = acc.findIndex(([match]) => { + if ("id" in chunk && chunk.id && "index" in chunk && chunk.index !== void 0) return chunk.id === match.id && chunk.index === match.index; + if ("id" in chunk && chunk.id) return chunk.id === match.id; + if ("index" in chunk && chunk.index !== void 0) return chunk.index === match.index; + return false; + }); + if (matchedChunkIndex !== -1) acc[matchedChunkIndex].push(chunk); + else acc.push([chunk]); + return acc; + }, []); + const toolCalls = []; + const invalidToolCalls = []; + for (const chunks$1 of groupedToolCallChunks) { + let parsedArgs = null; + const name = chunks$1[0]?.name ?? ""; + const joinedArgs = chunks$1.map((c) => c.args || "").join("").trim(); + const argsStr = joinedArgs.length ? joinedArgs : "{}"; + const id = chunks$1[0]?.id; + try { + parsedArgs = parsePartialJson(argsStr); + if (!id || parsedArgs === null || typeof parsedArgs !== "object" || Array.isArray(parsedArgs)) throw new Error("Malformed tool call chunk args."); + toolCalls.push({ + name, + args: parsedArgs, + id, + type: "tool_call" + }); + } catch { + invalidToolCalls.push({ + name, + args: argsStr, + id, + error: "Malformed args.", + type: "invalid_tool_call" + }); + } + } + return { + tool_call_chunks: chunks, + tool_calls: toolCalls, + invalid_tool_calls: invalidToolCalls + }; +} //#endregion @@ -40520,7 +40273,7 @@ var BaseCallbackHandler = class extends BaseCallbackHandlerMethodsClass { } static fromMethods(methods) { class Handler extends BaseCallbackHandler { - name = v4(); + name = v7(); constructor() { super(); Object.assign(this, methods); @@ -40740,7 +40493,7 @@ function uuid7() { // Update using yarn bump-version -const __version__ = "0.3.82"; +const __version__ = "0.4.2"; ;// CONCATENATED MODULE: ./node_modules/langsmith/dist/utils/env.js // Inlined from https://github.com/flexdinesh/browser-or-node @@ -42021,6 +41774,33 @@ class LangSmithConflictError extends Error { this.status = 409; } } +/** + * LangSmithNotFoundError + * + * Represents an error that occurs when a requested resource is not found, + * typically corresponding to HTTP 404 status code responses. + * + * @extends Error + */ +class LangSmithNotFoundError extends Error { + constructor(message) { + super(message); + Object.defineProperty(this, "status", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); + this.name = "LangSmithNotFoundError"; + this.status = 404; + } +} +function isLangSmithNotFoundError(error) { + return (error != null && + typeof error === "object" && + "name" in error && + error?.name === "LangSmithNotFoundError"); +} /** * Throws an appropriate error based on the response status and body. * @@ -42068,6 +41848,9 @@ async function raiseForStatus(response, context, consumeOnSuccess) { } } const fullMessage = `Failed to ${context}. Received status [${response.status}]: ${response.statusText}. Message: ${errorBody}`; + if (response.status === 404) { + throw new LangSmithNotFoundError(fullMessage); + } if (response.status === 409) { throw new LangSmithConflictError(fullMessage); } @@ -42392,7 +42175,10 @@ function replaceGetterValues(replacer) { -function mergeRuntimeEnvIntoRun(run, cachedEnvVars) { +function mergeRuntimeEnvIntoRun(run, cachedEnvVars, omitTracedRuntimeInfo) { + if (omitTracedRuntimeInfo) { + return run; + } const runtimeEnv = env_getRuntimeEnvironment(); const envVars = cachedEnvVars ?? getLangSmithEnvVarsMetadata(); const extra = run.extra ?? {}; @@ -42635,6 +42421,12 @@ class Client { writable: true, value: void 0 }); + Object.defineProperty(this, "omitTracedRuntimeInfo", { + enumerable: true, + configurable: true, + writable: true, + value: void 0 + }); Object.defineProperty(this, "tracingSampleRate", { enumerable: true, configurable: true, @@ -42750,6 +42542,12 @@ class Client { writable: true, value: false }); + Object.defineProperty(this, "_multipartDisabled", { + enumerable: true, + configurable: true, + writable: true, + value: false + }); Object.defineProperty(this, "debug", { enumerable: true, configurable: true, @@ -42795,6 +42593,7 @@ class Client { config.hideInputs ?? config.anonymizer ?? defaultConfig.hideInputs; this.hideOutputs = config.hideOutputs ?? config.anonymizer ?? defaultConfig.hideOutputs; + this.omitTracedRuntimeInfo = config.omitTracedRuntimeInfo ?? false; this.autoBatchTracing = config.autoBatchTracing ?? this.autoBatchTracing; this.autoBatchQueue = new AutoBatchQueue(maxMemory); this.blockOnRootRunFinalization = @@ -43041,7 +42840,7 @@ class Client { async _getBatchSizeLimitBytes() { const serverInfo = await this._ensureServerInfo(); return (this.batchSizeBytesLimit ?? - serverInfo.batch_ingest_config?.size_limit_bytes ?? + serverInfo?.batch_ingest_config?.size_limit_bytes ?? DEFAULT_UNCOMPRESSED_BATCH_SIZE_LIMIT_BYTES); } /** @@ -43050,7 +42849,7 @@ class Client { async _getBatchSizeLimit() { const serverInfo = await this._ensureServerInfo(); return (this.batchSizeLimit ?? - serverInfo.batch_ingest_config?.size_limit ?? + serverInfo?.batch_ingest_config?.size_limit ?? DEFAULT_BATCH_SIZE_LIMIT); } async _getDatasetExamplesMultiPartSupport() { @@ -43113,13 +42912,32 @@ class Client { .map((item) => item.item), }; const serverInfo = await this._ensureServerInfo(); - if (serverInfo?.batch_ingest_config?.use_multipart_endpoint) { + const useMultipart = !this._multipartDisabled && + (serverInfo?.batch_ingest_config?.use_multipart_endpoint ?? true); + if (useMultipart) { const useGzip = serverInfo?.instance_flags?.gzip_body_enabled; - await this.multipartIngestRuns(ingestParams, { - ...options, - useGzip, - sizeBytes: batchSizeBytes, - }); + try { + await this.multipartIngestRuns(ingestParams, { + ...options, + useGzip, + sizeBytes: batchSizeBytes, + }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } + catch (e) { + if (isLangSmithNotFoundError(e)) { + // Fallback to batch ingest if multipart endpoint returns 404 + // Disable multipart for future requests + this._multipartDisabled = true; + await this.batchIngestRuns(ingestParams, { + ...options, + sizeBytes: batchSizeBytes, + }); + } + else { + throw e; + } + } } else { await this.batchIngestRuns(ingestParams, { @@ -43164,7 +42982,7 @@ class Client { async processRunOperation(item) { clearTimeout(this.autoBatchTimeout); this.autoBatchTimeout = undefined; - item.item = mergeRuntimeEnvIntoRun(item.item, this.cachedLSEnvVarsForMetadata); + item.item = mergeRuntimeEnvIntoRun(item.item, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo); const itemPromise = this.autoBatchQueue.push(item); if (this.manualFlushMode) { // Rely on manual flushing in serverless environments @@ -43286,7 +43104,7 @@ class Client { }).catch(console.error); return; } - const mergedRunCreateParam = mergeRuntimeEnvIntoRun(runCreate, this.cachedLSEnvVarsForMetadata); + const mergedRunCreateParam = mergeRuntimeEnvIntoRun(runCreate, this.cachedLSEnvVarsForMetadata, this.omitTracedRuntimeInfo); if (options?.apiKey !== undefined) { headers["x-api-key"] = options.apiKey; } @@ -43648,6 +43466,10 @@ class Client { // eslint-disable-next-line @typescript-eslint/no-explicit-any } catch (e) { + // Re-throw 404 errors so caller can fall back to batch ingest + if (isLangSmithNotFoundError(e)) { + throw e; + } console.warn(`${e.message.trim()}\n\nContext: ${context}`); } } @@ -45038,6 +44860,49 @@ class Client { return res; }); } + /** + * Delete multiple examples by ID. + * @param exampleIds - The IDs of the examples to delete + * @param options - Optional settings for deletion + * @param options.hardDelete - If true, permanently delete examples. If false (default), soft delete them. + */ + async deleteExamples(exampleIds, options) { + // Validate all UUIDs + exampleIds.forEach((id) => assertUuid(id)); + if (options?.hardDelete) { + // Hard delete uses POST to a different platform endpoint + const path = this._getPlatformEndpointPath("datasets/examples/delete"); + await this.caller.call(async () => { + const res = await this._fetch(`${this.apiUrl}${path}`, { + method: "POST", + headers: { ...this.headers, "Content-Type": "application/json" }, + body: JSON.stringify({ + example_ids: exampleIds, + hard_delete: true, + }), + signal: AbortSignal.timeout(this.timeout_ms), + ...this.fetchOptions, + }); + await raiseForStatus(res, "hard delete examples", true); + return res; + }); + } + else { + // Soft delete uses DELETE with query params + const params = new URLSearchParams(); + exampleIds.forEach((id) => params.append("example_ids", id)); + await this.caller.call(async () => { + const res = await this._fetch(`${this.apiUrl}/examples?${params.toString()}`, { + method: "DELETE", + headers: this.headers, + signal: AbortSignal.timeout(this.timeout_ms), + ...this.fetchOptions, + }); + await raiseForStatus(res, "delete examples", true); + return res; + }); + } + } async updateExample(exampleIdOrUpdate, update) { let exampleId; if (update) { @@ -45185,29 +45050,6 @@ class Client { return res; }); } - /** - * @deprecated This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead. - */ - async evaluateRun(run, evaluator, { sourceInfo, loadChildRuns, referenceExample, } = { loadChildRuns: false }) { - warn_warnOnce("This method is deprecated and will be removed in future LangSmith versions, use `evaluate` from `langsmith/evaluation` instead."); - let run_; - if (typeof run === "string") { - run_ = await this.readRun(run, { loadChildRuns }); - } - else if (typeof run === "object" && "id" in run) { - run_ = run; - } - else { - throw new Error(`Invalid run type: ${typeof run}`); - } - if (run_.reference_example_id !== null && - run_.reference_example_id !== undefined) { - referenceExample = await this.readExample(run_.reference_example_id); - } - const feedbackResult = await evaluator.evaluateRun(run_, referenceExample); - const [_, feedbacks] = await this._logEvaluationFeedback(feedbackResult, run_, sourceInfo); - return feedbacks[0]; - } async createFeedback(runId, key, { score, value, correction, comment, sourceInfo, feedbackSourceType = "api", sourceRunId, feedbackId, feedbackConfig, projectId, comparativeExperimentId, }) { if (!runId && !projectId) { throw new Error("One of runId or projectId must be provided"); @@ -46237,6 +46079,21 @@ class Client { console.warn("[WARNING]: When tracing in manual flush mode, you must call `await client.flush()` manually to submit trace batches."); return Promise.resolve(); } + /** + * traceables use a backgrounded promise before updating runs to avoid blocking + * and to allow waiting for child runs to end. Waiting a small amount of time + * here ensures that they are able to enqueue their run operation before we await + * queued run operations below: + * + * ```ts + * const run = await traceable(async () => { + * return "Hello, world!"; + * }, { client })(); + * + * await client.awaitPendingTraceBatches(); + * ``` + */ + await new Promise((resolve) => setTimeout(resolve, 1)); await Promise.all([ ...this.autoBatchQueue.items.map(({ itemPromise }) => itemPromise), this.batchIngestCaller.queue.onIdle(), @@ -46262,6 +46119,7 @@ const isTracingEnabled = (tracingEnabled) => { ;// CONCATENATED MODULE: ./node_modules/langsmith/dist/singletons/constants.js const _LC_CONTEXT_VARIABLES_KEY = Symbol.for("lc:context_variables"); +const _LC_CHILD_RUN_END_PROMISES_KEY = Symbol.for("lc:child_run_end_promises"); const _REPLICA_TRACE_ROOTS_KEY = Symbol.for("langsmith:replica_trace_roots"); ;// CONCATENATED MODULE: ./node_modules/langsmith/dist/utils/context_vars.js @@ -46966,6 +46824,7 @@ class run_trees_RunTree { await childRun.postRun(false); } } + this.child_runs = []; } catch (error) { console.error(`Error in postRun for run ${this.id}:`, error); @@ -47047,6 +46906,7 @@ class run_trees_RunTree { console.error(`Error in patchRun for run ${this.id}`, error); } } + this.child_runs = []; } toJSON() { return this._convertToCreate(this, undefined, false); @@ -47198,12 +47058,14 @@ function isRunnableConfigLike(x) { // Check that it's an object with a callbacks arg // that has either a CallbackManagerLike object with a langchain tracer within it // or an array with a LangChainTracerLike object within it + const callbacks = x?.callbacks; return (x != null && - typeof x.callbacks === "object" && + typeof callbacks === "object" && // Callback manager with a langchain tracer - (containsLangChainTracerLike(x.callbacks?.handlers) || + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (containsLangChainTracerLike(callbacks?.handlers) || // Or it's an array with a LangChainTracerLike object within it - containsLangChainTracerLike(x.callbacks))); + containsLangChainTracerLike(callbacks))); } function _getWriteReplicasFromEnv() { const envVar = env_getEnvironmentVariable("LANGSMITH_RUNS_ENDPOINTS"); @@ -47359,17 +47221,16 @@ var BaseTracer = class extends BaseCallbackHandler { const { dottedOrder: currentDottedOrder, microsecondPrecisionDatestring } = convertToDottedOrderFormat(new Date(run.start_time).getTime(), run.id, run.execution_order); const storedRun = { ...run }; const parentRun = this.getRunById(storedRun.parent_run_id); - if (storedRun.parent_run_id !== void 0) { - if (parentRun) { - this._addChildRun(parentRun, storedRun); - parentRun.child_execution_order = Math.max(parentRun.child_execution_order, storedRun.child_execution_order); - storedRun.trace_id = parentRun.trace_id; - if (parentRun.dotted_order !== void 0) { - storedRun.dotted_order = [parentRun.dotted_order, currentDottedOrder].join("."); - storedRun._serialized_start_time = microsecondPrecisionDatestring; - } + if (storedRun.parent_run_id !== void 0) if (parentRun) { + this._addChildRun(parentRun, storedRun); + parentRun.child_execution_order = Math.max(parentRun.child_execution_order, storedRun.child_execution_order); + storedRun.trace_id = parentRun.trace_id; + if (parentRun.dotted_order !== void 0) { + storedRun.dotted_order = [parentRun.dotted_order, currentDottedOrder].join("."); + storedRun._serialized_start_time = microsecondPrecisionDatestring; } - } else { + } else storedRun.parent_run_id = void 0; + else { storedRun.trace_id = storedRun.id; storedRun.dotted_order = currentDottedOrder; storedRun._serialized_start_time = microsecondPrecisionDatestring; @@ -47508,7 +47369,7 @@ var BaseTracer = class extends BaseCallbackHandler { * This must sometimes be done synchronously to avoid race conditions * when callbacks are backgrounded, so we expose it as a separate method here. */ - _createRunForChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name) { + _createRunForChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, name, extra) { const execution_order = this._getExecutionOrder(parentRunId); const start_time = Date.now(); const run = { @@ -47526,7 +47387,10 @@ var BaseTracer = class extends BaseCallbackHandler { child_execution_order: execution_order, run_type: runType ?? "chain", child_runs: [], - extra: metadata ? { metadata } : {}, + extra: metadata ? { + ...extra, + metadata + } : { ...extra }, tags: tags || [] }; return this._addRunToRunMap(run); @@ -48026,9 +47890,22 @@ function isTraceableFunction(x + + //#region src/tracers/tracer_langchain.ts var tracer_langchain_exports = {}; __export(tracer_langchain_exports, { LangChainTracer: () => LangChainTracer }); +/** +* Extract usage_metadata from chat generations. +* +* Iterates through generations to find and aggregates all usage_metadata +* found in chat messages. This is typically present in chat model outputs. +*/ +function _getUsageMetadataFromGenerations(generations) { + let output = void 0; + for (const generationBatch of generations) for (const generation of generationBatch) if (AIMessage.isInstance(generation.message) && generation.message.usage_metadata !== void 0) output = mergeUsageMetadata(output, generation.message.usage_metadata); + return output; +} var LangChainTracer = class LangChainTracer extends BaseTracer { name = "langchain_tracer"; projectName; @@ -48048,12 +47925,27 @@ var LangChainTracer = class LangChainTracer extends BaseTracer { } async persistRun(_run) {} async onRunCreate(run) { - const runTree = this.getRunTreeWithTracingConfig(run.id); - await runTree?.postRun(); + if (!run.extra?.lc_defers_inputs) { + const runTree = this.getRunTreeWithTracingConfig(run.id); + await runTree?.postRun(); + } } async onRunUpdate(run) { const runTree = this.getRunTreeWithTracingConfig(run.id); - await runTree?.patchRun(); + if (run.extra?.lc_defers_inputs) await runTree?.postRun(); + else await runTree?.patchRun(); + } + onLLMEnd(run) { + const outputs = run.outputs; + if (outputs?.generations) { + const usageMetadata = _getUsageMetadataFromGenerations(outputs.generations); + if (usageMetadata !== void 0) { + run.extra = run.extra ?? {}; + const metadata = run.extra.metadata ?? {}; + metadata.usage_metadata = usageMetadata; + run.extra.metadata = metadata; + } + } } getRun(id) { return this.runTreeMap.get(id); @@ -48654,7 +48546,7 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { } async handleLLMStart(llm, prompts, runId = void 0, _parentRunId = void 0, extraParams = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { return Promise.all(prompts.map(async (prompt, idx) => { - const runId_ = idx === 0 && runId ? runId : v4(); + const runId_ = idx === 0 && runId ? runId : v7(); await Promise.all(this.handlers.map((handler) => { if (handler.ignoreLLM) return; if (isBaseTracer(handler)) handler._createRunForLLMStart(llm, [prompt], runId_, this._parentRunId, extraParams, this.tags, this.metadata, runName); @@ -48673,7 +48565,7 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { } async handleChatModelStart(llm, messages, runId = void 0, _parentRunId = void 0, extraParams = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { return Promise.all(messages.map(async (messageGroup, idx) => { - const runId_ = idx === 0 && runId ? runId : v4(); + const runId_ = idx === 0 && runId ? runId : v7(); await Promise.all(this.handlers.map((handler) => { if (handler.ignoreLLM) return; if (isBaseTracer(handler)) handler._createRunForChatModelStart(llm, [messageGroup], runId_, this._parentRunId, extraParams, this.tags, this.metadata, runName); @@ -48694,13 +48586,13 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { return new CallbackManagerForLLMRun(runId_, this.handlers, this.inheritableHandlers, this.tags, this.inheritableTags, this.metadata, this.inheritableMetadata, this._parentRunId); })); } - async handleChainStart(chain, inputs, runId = v4(), runType = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { + async handleChainStart(chain, inputs, runId = v7(), runType = void 0, _tags = void 0, _metadata = void 0, runName = void 0, _parentRunId = void 0, extra = void 0) { await Promise.all(this.handlers.map((handler) => { if (handler.ignoreChain) return; - if (isBaseTracer(handler)) handler._createRunForChainStart(chain, inputs, runId, this._parentRunId, this.tags, this.metadata, runType, runName); + if (isBaseTracer(handler)) handler._createRunForChainStart(chain, inputs, runId, this._parentRunId, this.tags, this.metadata, runType, runName, extra); return consumeCallback(async () => { try { - await handler.handleChainStart?.(chain, inputs, runId, this._parentRunId, this.tags, this.metadata, runType, runName); + await handler.handleChainStart?.(chain, inputs, runId, this._parentRunId, this.tags, this.metadata, runType, runName, extra); } catch (err) { const logFunction = handler.raiseError ? console.error : console.warn; logFunction(`Error in handler ${handler.constructor.name}, handleChainStart: ${err}`); @@ -48710,7 +48602,7 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { })); return new CallbackManagerForChainRun(runId, this.handlers, this.inheritableHandlers, this.tags, this.inheritableTags, this.metadata, this.inheritableMetadata, this._parentRunId); } - async handleToolStart(tool, input, runId = v4(), _parentRunId = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { + async handleToolStart(tool, input, runId = v7(), _parentRunId = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { await Promise.all(this.handlers.map((handler) => { if (handler.ignoreAgent) return; if (isBaseTracer(handler)) handler._createRunForToolStart(tool, input, runId, this._parentRunId, this.tags, this.metadata, runName); @@ -48726,7 +48618,7 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { })); return new CallbackManagerForToolRun(runId, this.handlers, this.inheritableHandlers, this.tags, this.inheritableTags, this.metadata, this.inheritableMetadata, this._parentRunId); } - async handleRetrieverStart(retriever, query, runId = v4(), _parentRunId = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { + async handleRetrieverStart(retriever, query, runId = v7(), _parentRunId = void 0, _tags = void 0, _metadata = void 0, runName = void 0) { await Promise.all(this.handlers.map((handler) => { if (handler.ignoreRetriever) return; if (isBaseTracer(handler)) handler._createRunForRetrieverStart(retriever, query, runId, this._parentRunId, this.tags, this.metadata, runName); @@ -48813,7 +48705,7 @@ var CallbackManager = class CallbackManager extends BaseCallbackManager { } static fromHandlers(handlers) { class Handler extends BaseCallbackHandler { - name = v4(); + name = v7(); constructor() { super(); Object.assign(this, handlers); @@ -49367,10 +49259,24 @@ function ensureConfig(config) { } if (empty.timeout !== void 0) { if (empty.timeout <= 0) throw new Error("Timeout must be a positive number"); - const timeoutSignal = AbortSignal.timeout(empty.timeout); + const originalTimeoutMs = empty.timeout; + const timeoutSignal = AbortSignal.timeout(originalTimeoutMs); + if (!empty.metadata) empty.metadata = {}; + if (empty.metadata.timeoutMs === void 0) empty.metadata.timeoutMs = originalTimeoutMs; if (empty.signal !== void 0) { if ("any" in AbortSignal) empty.signal = AbortSignal.any([empty.signal, timeoutSignal]); } else empty.signal = timeoutSignal; + /** + * We are deleting the timeout key for the following reasons: + * - Idempotent normalization: ensureConfig may be called multiple times down the stack. If timeout remains, + * each call would synthesize new timeout signals and combine them, changing the effective timeout unpredictably. + * - Single enforcement path: downstream code relies on signal to enforce cancellation. Leaving timeout means two + * competing mechanisms (numeric timeout and signal) can be applied, sometimes with different semantics. + * - Propagation to children: pickRunnableConfigKeys would keep forwarding timeout to nested runnables, causing + * repeated re-normalization and stacked timeouts. + * - Backward compatibility: a lot of components and tests assume ensureConfig removes timeout post-normalization; + * changing that would be a breaking change. + */ delete empty.timeout; } return empty; @@ -49773,12 +49679,21 @@ __export(core_exports, { }); const JsonPatchError = PatchError; const deepClone = _deepClone; +/** +* Check if a key is a dangerous prototype property that could lead to prototype pollution. +* This provides defense-in-depth alongside the check in applyOperation. +*/ +function isDangerousKey(key) { + return Object.getOwnPropertyNames(Object.prototype).includes(key); +} const objOps = { add: function(obj, key, document) { + if (isDangerousKey(key)) throw new TypeError("JSON-Patch: modifying `__proto__`, `constructor`, or `prototype` prop is banned for security reasons"); obj[key] = this.value; return { newDocument: document }; }, remove: function(obj, key, document) { + if (isDangerousKey(key)) throw new TypeError("JSON-Patch: modifying `__proto__`, `constructor`, or `prototype` prop is banned for security reasons"); var removed = obj[key]; delete obj[key]; return { @@ -49787,6 +49702,7 @@ const objOps = { }; }, replace: function(obj, key, document) { + if (isDangerousKey(key)) throw new TypeError("JSON-Patch: modifying `__proto__`, `constructor`, or `prototype` prop is banned for security reasons"); var removed = obj[key]; obj[key] = this.value; return { @@ -50499,90 +50415,52 @@ var ChatGenerationChunk = class ChatGenerationChunk extends GenerationChunk { //#endregion //# sourceMappingURL=outputs.js.map -;// CONCATENATED MODULE: ./node_modules/is-network-error/index.js +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/is-network-error/index.js +//#region src/utils/is-network-error/index.js const is_network_error_objectToString = Object.prototype.toString; - -const is_network_error_isError = value => is_network_error_objectToString.call(value) === '[object Error]'; - +const is_network_error_isError = (value) => is_network_error_objectToString.call(value) === "[object Error]"; const is_network_error_errorMessages = new Set([ - 'network error', // Chrome - 'Failed to fetch', // Chrome - 'NetworkError when attempting to fetch resource.', // Firefox - 'The Internet connection appears to be offline.', // Safari 16 - 'Network request failed', // `cross-fetch` - 'fetch failed', // Undici (Node.js) - 'terminated', // Undici (Node.js) - ' A network error occurred.', // Bun (WebKit) - 'Network connection lost', // Cloudflare Workers (fetch) + "network error", + "Failed to fetch", + "NetworkError when attempting to fetch resource.", + "The Internet connection appears to be offline.", + "Network request failed", + "fetch failed", + "terminated", + " A network error occurred.", + "Network connection lost" ]); - function is_network_error_isNetworkError(error) { - const isValid = error - && is_network_error_isError(error) - && error.name === 'TypeError' - && typeof error.message === 'string'; - - if (!isValid) { - return false; - } - - const {message, stack} = error; - - // Safari 17+ has generic message but no stack for network errors - if (message === 'Load failed') { - return stack === undefined - // Sentry adds its own stack trace to the fetch error, so also check for that - || '__sentry_captured__' in error; - } - - // Deno network errors start with specific text - if (message.startsWith('error sending request for url')) { - return true; - } - - // Standard network error messages + const isValid = error && is_network_error_isError(error) && error.name === "TypeError" && typeof error.message === "string"; + if (!isValid) return false; + const { message, stack } = error; + if (message === "Load failed") return stack === void 0 || "__sentry_captured__" in error; + if (message.startsWith("error sending request for url")) return true; return is_network_error_errorMessages.has(message); } -;// CONCATENATED MODULE: ./node_modules/p-retry/index.js - - -function p_retry_validateRetries(retries) { - if (typeof retries === 'number') { - if (retries < 0) { - throw new TypeError('Expected `retries` to be a non-negative number.'); - } - - if (Number.isNaN(retries)) { - throw new TypeError('Expected `retries` to be a valid number or Infinity, got NaN.'); - } - } else if (retries !== undefined) { - throw new TypeError('Expected `retries` to be a number or Infinity.'); - } -} - -function p_retry_validateNumberOption(name, value, {min = 0, allowInfinity = false} = {}) { - if (value === undefined) { - return; - } - - if (typeof value !== 'number' || Number.isNaN(value)) { - throw new TypeError(`Expected \`${name}\` to be a number${allowInfinity ? ' or Infinity' : ''}.`); - } +//#endregion - if (!allowInfinity && !Number.isFinite(value)) { - throw new TypeError(`Expected \`${name}\` to be a finite number.`); - } +//# sourceMappingURL=index.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/p-retry/index.js - if (value < min) { - throw new TypeError(`Expected \`${name}\` to be \u2265 ${min}.`); - } -} -class p_retry_AbortError extends Error { +//#region src/utils/p-retry/index.js +function p_retry_validateRetries(retries) { + if (typeof retries === "number") { + if (retries < 0) throw new TypeError("Expected `retries` to be a non-negative number."); + if (Number.isNaN(retries)) throw new TypeError("Expected `retries` to be a valid number or Infinity, got NaN."); + } else if (retries !== void 0) throw new TypeError("Expected `retries` to be a number or Infinity."); +} +function p_retry_validateNumberOption(name, value, { min = 0, allowInfinity = false } = {}) { + if (value === void 0) return; + if (typeof value !== "number" || Number.isNaN(value)) throw new TypeError(`Expected \`${name}\` to be a number${allowInfinity ? " or Infinity" : ""}.`); + if (!allowInfinity && !Number.isFinite(value)) throw new TypeError(`Expected \`${name}\` to be a finite number.`); + if (value < min) throw new TypeError(`Expected \`${name}\` to be \u2265 ${min}.`); +} +var p_retry_AbortError = class extends Error { constructor(message) { super(); - if (message instanceof Error) { this.originalError = message; ({message} = message); @@ -50590,159 +50468,105 @@ class p_retry_AbortError extends Error { this.originalError = new Error(message); this.originalError.stack = this.stack; } - - this.name = 'AbortError'; + this.name = "AbortError"; this.message = message; } -} - +}; function p_retry_calculateDelay(retriesConsumed, options) { const attempt = Math.max(1, retriesConsumed + 1); - const random = options.randomize ? (Math.random() + 1) : 1; - - let timeout = Math.round(random * options.minTimeout * (options.factor ** (attempt - 1))); + const random = options.randomize ? Math.random() + 1 : 1; + let timeout = Math.round(random * options.minTimeout * options.factor ** (attempt - 1)); timeout = Math.min(timeout, options.maxTimeout); - return timeout; } - function p_retry_calculateRemainingTime(start, max) { - if (!Number.isFinite(max)) { - return max; - } - + if (!Number.isFinite(max)) return max; return max - (performance.now() - start); } - -async function p_retry_onAttemptFailure({error, attemptNumber, retriesConsumed, startTime, options}) { - const normalizedError = error instanceof Error - ? error - : new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`); - - if (normalizedError instanceof p_retry_AbortError) { - throw normalizedError.originalError; - } - - const retriesLeft = Number.isFinite(options.retries) - ? Math.max(0, options.retries - retriesConsumed) - : options.retries; - +async function p_retry_onAttemptFailure({ error, attemptNumber, retriesConsumed, startTime, options }) { + const normalizedError = error instanceof Error ? error : /* @__PURE__ */ new TypeError(`Non-error was thrown: "${error}". You should only throw errors.`); + if (normalizedError instanceof p_retry_AbortError) throw normalizedError.originalError; + const retriesLeft = Number.isFinite(options.retries) ? Math.max(0, options.retries - retriesConsumed) : options.retries; const maxRetryTime = options.maxRetryTime ?? Number.POSITIVE_INFINITY; - const context = Object.freeze({ error: normalizedError, attemptNumber, retriesLeft, - retriesConsumed, + retriesConsumed }); - await options.onFailedAttempt(context); - - if (p_retry_calculateRemainingTime(startTime, maxRetryTime) <= 0) { - throw normalizedError; - } - + if (p_retry_calculateRemainingTime(startTime, maxRetryTime) <= 0) throw normalizedError; const consumeRetry = await options.shouldConsumeRetry(context); - const remainingTime = p_retry_calculateRemainingTime(startTime, maxRetryTime); - - if (remainingTime <= 0 || retriesLeft <= 0) { - throw normalizedError; - } - + if (remainingTime <= 0 || retriesLeft <= 0) throw normalizedError; if (normalizedError instanceof TypeError && !is_network_error_isNetworkError(normalizedError)) { - if (consumeRetry) { - throw normalizedError; - } - + if (consumeRetry) throw normalizedError; options.signal?.throwIfAborted(); return false; } - - if (!await options.shouldRetry(context)) { - throw normalizedError; - } - + if (!await options.shouldRetry(context)) throw normalizedError; if (!consumeRetry) { options.signal?.throwIfAborted(); return false; } - const delayTime = p_retry_calculateDelay(retriesConsumed, options); const finalDelay = Math.min(delayTime, remainingTime); - - if (finalDelay > 0) { - await new Promise((resolve, reject) => { - const onAbort = () => { - clearTimeout(timeoutToken); - options.signal?.removeEventListener('abort', onAbort); - reject(options.signal.reason); - }; - - const timeoutToken = setTimeout(() => { - options.signal?.removeEventListener('abort', onAbort); - resolve(); - }, finalDelay); - - if (options.unref) { - timeoutToken.unref?.(); - } - - options.signal?.addEventListener('abort', onAbort, {once: true}); - }); - } - + if (finalDelay > 0) await new Promise((resolve, reject) => { + const onAbort = () => { + clearTimeout(timeoutToken); + options.signal?.removeEventListener("abort", onAbort); + reject(options.signal.reason); + }; + const timeoutToken = setTimeout(() => { + options.signal?.removeEventListener("abort", onAbort); + resolve(); + }, finalDelay); + if (options.unref) timeoutToken.unref?.(); + options.signal?.addEventListener("abort", onAbort, { once: true }); + }); options.signal?.throwIfAborted(); - return true; } - async function p_retry_pRetry(input, options = {}) { - options = {...options}; - + options = { ...options }; p_retry_validateRetries(options.retries); - - if (Object.hasOwn(options, 'forever')) { - throw new Error('The `forever` option is no longer supported. For many use-cases, you can set `retries: Infinity` instead.'); - } - + if (Object.hasOwn(options, "forever")) throw new Error("The `forever` option is no longer supported. For many use-cases, you can set `retries: Infinity` instead."); options.retries ??= 10; options.factor ??= 2; - options.minTimeout ??= 1000; + options.minTimeout ??= 1e3; options.maxTimeout ??= Number.POSITIVE_INFINITY; options.maxRetryTime ??= Number.POSITIVE_INFINITY; options.randomize ??= false; options.onFailedAttempt ??= () => {}; options.shouldRetry ??= () => true; options.shouldConsumeRetry ??= () => true; - - // Validate numeric options and normalize edge cases - p_retry_validateNumberOption('factor', options.factor, {min: 0, allowInfinity: false}); - p_retry_validateNumberOption('minTimeout', options.minTimeout, {min: 0, allowInfinity: false}); - p_retry_validateNumberOption('maxTimeout', options.maxTimeout, {min: 0, allowInfinity: true}); - p_retry_validateNumberOption('maxRetryTime', options.maxRetryTime, {min: 0, allowInfinity: true}); - - // Treat non-positive factor as 1 to avoid zero backoff or negative behavior - if (!(options.factor > 0)) { - options.factor = 1; - } - + p_retry_validateNumberOption("factor", options.factor, { + min: 0, + allowInfinity: false + }); + p_retry_validateNumberOption("minTimeout", options.minTimeout, { + min: 0, + allowInfinity: false + }); + p_retry_validateNumberOption("maxTimeout", options.maxTimeout, { + min: 0, + allowInfinity: true + }); + p_retry_validateNumberOption("maxRetryTime", options.maxRetryTime, { + min: 0, + allowInfinity: true + }); + if (!(options.factor > 0)) options.factor = 1; options.signal?.throwIfAborted(); - let attemptNumber = 0; let retriesConsumed = 0; const startTime = performance.now(); - while (Number.isFinite(options.retries) ? retriesConsumed <= options.retries : true) { attemptNumber++; - try { options.signal?.throwIfAborted(); - const result = await input(attemptNumber); - options.signal?.throwIfAborted(); - return result; } catch (error) { if (await p_retry_onAttemptFailure({ @@ -50750,23 +50574,16 @@ async function p_retry_pRetry(input, options = {}) { attemptNumber, retriesConsumed, startTime, - options, - })) { - retriesConsumed++; - } + options + })) retriesConsumed++; } } - - // Should not reach here, but in case it does, throw an error - throw new Error('Retry attempts exhausted without throwing an error.'); + throw new Error("Retry attempts exhausted without throwing an error."); } -function p_retry_makeRetriable(function_, options) { - return function (...arguments_) { - return p_retry_pRetry(() => function_.apply(this, arguments_), options); - }; -} +//#endregion +//# sourceMappingURL=index.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/async_caller.js @@ -50823,7 +50640,7 @@ var async_caller_AsyncCaller = class { const PQueue = true ? p_queue_dist["default"] : p_queue_dist; this.queue = new PQueue({ concurrency: this.maxConcurrency }); } - call(callable, ...args) { + async call(callable, ...args) { return this.queue.add(() => p_retry_pRetry(() => callable(...args).catch((error) => { if (error instanceof Error) throw error; else throw new Error(error); @@ -50943,7 +50760,7 @@ function assertNotEqual(val) { } function assertIs(_arg) { } function assertNever(_x) { - throw new Error(); + throw new Error("Unexpected value in exhaustive check"); } function assert(_) { } function getEnumValues(entries) { @@ -52570,8 +52387,8 @@ class Doc { ;// CONCATENATED MODULE: ./node_modules/zod/v4/core/versions.js const versions_version = { major: 4, - minor: 1, - patch: 13, + minor: 2, + patch: 1, }; ;// CONCATENATED MODULE: ./node_modules/zod/v4/core/schemas.js @@ -52649,16 +52466,6 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => { } return payload; }; - // const handleChecksResult = ( - // checkResult: ParsePayload, - // originalResult: ParsePayload, - // ctx: ParseContextInternal - // ): util.MaybeAsync => { - // // if the checks mutated the value && there are no issues, re-parse the result - // if (checkResult.value !== originalResult.value && !checkResult.issues.length) - // return inst._zod.parse(checkResult, ctx); - // return originalResult; - // }; const handleCanaryResult = (canary, payload, ctx) => { // abort if the canary is aborted if (aborted(canary)) { @@ -53549,9 +53356,68 @@ const $ZodUnion = /*@__PURE__*/ $constructor("$ZodUnion", (inst, def) => { }); }; }); +function handleExclusiveUnionResults(results, final, inst, ctx) { + const successes = results.filter((r) => r.issues.length === 0); + if (successes.length === 1) { + final.value = successes[0].value; + return final; + } + if (successes.length === 0) { + // No matches - same as regular union + final.issues.push({ + code: "invalid_union", + input: final.value, + inst, + errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config()))), + }); + } + else { + // Multiple matches - exclusive union failure + final.issues.push({ + code: "invalid_union", + input: final.value, + inst, + errors: [], + inclusive: false, + }); + } + return final; +} +const $ZodXor = /*@__PURE__*/ $constructor("$ZodXor", (inst, def) => { + $ZodUnion.init(inst, def); + def.inclusive = false; + const single = def.options.length === 1; + const first = def.options[0]._zod.run; + inst._zod.parse = (payload, ctx) => { + if (single) { + return first(payload, ctx); + } + let async = false; + const results = []; + for (const option of def.options) { + const result = option._zod.run({ + value: payload.value, + issues: [], + }, ctx); + if (result instanceof Promise) { + results.push(result); + async = true; + } + else { + results.push(result); + } + } + if (!async) + return handleExclusiveUnionResults(results, payload, inst, ctx); + return Promise.all(results).then((results) => { + return handleExclusiveUnionResults(results, payload, inst, ctx); + }); + }; +}); const $ZodDiscriminatedUnion = /*@__PURE__*/ $constructor("$ZodDiscriminatedUnion", (inst, def) => { + def.inclusive = false; $ZodUnion.init(inst, def); const _super = inst._zod.parse; defineLazy(inst._zod, "propValues", () => { @@ -53833,15 +53699,21 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => { throw new Error("Async schemas not supported in object keys currently"); } if (keyResult.issues.length) { - payload.issues.push({ - code: "invalid_key", - origin: "record", - issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())), - input: key, - path: [key], - inst, - }); - payload.value[keyResult.value] = keyResult.value; + if (def.mode === "loose") { + // Pass through unchanged + payload.value[key] = input[key]; + } + else { + // Default "strict" behavior: error on invalid key + payload.issues.push({ + code: "invalid_key", + origin: "record", + issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())), + input: key, + path: [key], + inst, + }); + } continue; } const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx); @@ -61047,6 +60919,14 @@ function _union(Class, options, params) { ...normalizeParams(params), }); } +function _xor(Class, options, params) { + return new Class({ + type: "union", + options, + inclusive: false, + ...normalizeParams(params), + }); +} function _discriminatedUnion(Class, discriminator, options, params) { return new Class({ type: "union", @@ -61371,825 +61251,313 @@ function _stringFormat(Class, format, fnOrRegex, _params = {}) { ;// CONCATENATED MODULE: ./node_modules/zod/v4/core/to-json-schema.js - -class JSONSchemaGenerator { - constructor(params) { - this.counter = 0; - this.metadataRegistry = params?.metadata ?? globalRegistry; - this.target = params?.target ?? "draft-2020-12"; - this.unrepresentable = params?.unrepresentable ?? "throw"; - this.override = params?.override ?? (() => { }); - this.io = params?.io ?? "output"; - this.seen = new Map(); +// function initializeContext(inputs: JSONSchemaGeneratorParams): ToJSONSchemaContext { +// return { +// processor: inputs.processor, +// metadataRegistry: inputs.metadata ?? globalRegistry, +// target: inputs.target ?? "draft-2020-12", +// unrepresentable: inputs.unrepresentable ?? "throw", +// }; +// } +function initializeContext(params) { + // Normalize target: convert old non-hyphenated versions to hyphenated versions + let target = params?.target ?? "draft-2020-12"; + if (target === "draft-4") + target = "draft-04"; + if (target === "draft-7") + target = "draft-07"; + return { + processors: params.processors ?? {}, + metadataRegistry: params?.metadata ?? globalRegistry, + target, + unrepresentable: params?.unrepresentable ?? "throw", + override: params?.override ?? (() => { }), + io: params?.io ?? "output", + counter: 0, + seen: new Map(), + cycles: params?.cycles ?? "ref", + reused: params?.reused ?? "inline", + external: params?.external ?? undefined, + }; +} +function to_json_schema_process(schema, ctx, _params = { path: [], schemaPath: [] }) { + var _a; + const def = schema._zod.def; + // check for schema in seens + const seen = ctx.seen.get(schema); + if (seen) { + seen.count++; + // check if cycle + const isCycle = _params.schemaPath.includes(schema); + if (isCycle) { + seen.cycle = _params.path; + } + return seen.schema; + } + // initialize + const result = { schema: {}, count: 1, cycle: undefined, path: _params.path }; + ctx.seen.set(schema, result); + // custom method overrides default behavior + const overrideSchema = schema._zod.toJSONSchema?.(); + if (overrideSchema) { + result.schema = overrideSchema; } - process(schema, _params = { path: [], schemaPath: [] }) { - var _a; - const def = schema._zod.def; - const formatMap = { - guid: "uuid", - url: "uri", - datetime: "date-time", - json_string: "json-string", - regex: "", // do not set + else { + const params = { + ..._params, + schemaPath: [..._params.schemaPath, schema], + path: _params.path, }; - // check for schema in seens - const seen = this.seen.get(schema); - if (seen) { - seen.count++; - // check if cycle - const isCycle = _params.schemaPath.includes(schema); - if (isCycle) { - seen.cycle = _params.path; - } - return seen.schema; - } - // initialize - const result = { schema: {}, count: 1, cycle: undefined, path: _params.path }; - this.seen.set(schema, result); - // custom method overrides default behavior - const overrideSchema = schema._zod.toJSONSchema?.(); - if (overrideSchema) { - result.schema = overrideSchema; + const parent = schema._zod.parent; + if (parent) { + // schema was cloned from another schema + result.ref = parent; + to_json_schema_process(parent, ctx, params); + ctx.seen.get(parent).isParent = true; } - else { - const params = { - ..._params, - schemaPath: [..._params.schemaPath, schema], - path: _params.path, - }; - const parent = schema._zod.parent; - if (parent) { - // schema was cloned from another schema - result.ref = parent; - this.process(parent, params); - this.seen.get(parent).isParent = true; - } - else { - const _json = result.schema; - switch (def.type) { - case "string": { - const json = _json; - json.type = "string"; - const { minimum, maximum, format, patterns, contentEncoding } = schema._zod - .bag; - if (typeof minimum === "number") - json.minLength = minimum; - if (typeof maximum === "number") - json.maxLength = maximum; - // custom pattern overrides format - if (format) { - json.format = formatMap[format] ?? format; - if (json.format === "") - delete json.format; // empty format is not valid - } - if (contentEncoding) - json.contentEncoding = contentEncoding; - if (patterns && patterns.size > 0) { - const regexes = [...patterns]; - if (regexes.length === 1) - json.pattern = regexes[0].source; - else if (regexes.length > 1) { - result.schema.allOf = [ - ...regexes.map((regex) => ({ - ...(this.target === "draft-7" || this.target === "draft-4" || this.target === "openapi-3.0" - ? { type: "string" } - : {}), - pattern: regex.source, - })), - ]; - } - } - break; - } - case "number": { - const json = _json; - const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag; - if (typeof format === "string" && format.includes("int")) - json.type = "integer"; - else - json.type = "number"; - if (typeof exclusiveMinimum === "number") { - if (this.target === "draft-4" || this.target === "openapi-3.0") { - json.minimum = exclusiveMinimum; - json.exclusiveMinimum = true; - } - else { - json.exclusiveMinimum = exclusiveMinimum; - } - } - if (typeof minimum === "number") { - json.minimum = minimum; - if (typeof exclusiveMinimum === "number" && this.target !== "draft-4") { - if (exclusiveMinimum >= minimum) - delete json.minimum; - else - delete json.exclusiveMinimum; - } - } - if (typeof exclusiveMaximum === "number") { - if (this.target === "draft-4" || this.target === "openapi-3.0") { - json.maximum = exclusiveMaximum; - json.exclusiveMaximum = true; - } - else { - json.exclusiveMaximum = exclusiveMaximum; - } - } - if (typeof maximum === "number") { - json.maximum = maximum; - if (typeof exclusiveMaximum === "number" && this.target !== "draft-4") { - if (exclusiveMaximum <= maximum) - delete json.maximum; - else - delete json.exclusiveMaximum; - } - } - if (typeof multipleOf === "number") - json.multipleOf = multipleOf; - break; - } - case "boolean": { - const json = _json; - json.type = "boolean"; - break; - } - case "bigint": { - if (this.unrepresentable === "throw") { - throw new Error("BigInt cannot be represented in JSON Schema"); - } - break; - } - case "symbol": { - if (this.unrepresentable === "throw") { - throw new Error("Symbols cannot be represented in JSON Schema"); - } - break; - } - case "null": { - if (this.target === "openapi-3.0") { - _json.type = "string"; - _json.nullable = true; - _json.enum = [null]; - } - else - _json.type = "null"; - break; - } - case "any": { - break; - } - case "unknown": { - break; - } - case "undefined": { - if (this.unrepresentable === "throw") { - throw new Error("Undefined cannot be represented in JSON Schema"); - } - break; - } - case "void": { - if (this.unrepresentable === "throw") { - throw new Error("Void cannot be represented in JSON Schema"); - } - break; - } - case "never": { - _json.not = {}; - break; - } - case "date": { - if (this.unrepresentable === "throw") { - throw new Error("Date cannot be represented in JSON Schema"); - } - break; - } - case "array": { - const json = _json; - const { minimum, maximum } = schema._zod.bag; - if (typeof minimum === "number") - json.minItems = minimum; - if (typeof maximum === "number") - json.maxItems = maximum; - json.type = "array"; - json.items = this.process(def.element, { ...params, path: [...params.path, "items"] }); - break; - } - case "object": { - const json = _json; - json.type = "object"; - json.properties = {}; - const shape = def.shape; // params.shapeCache.get(schema)!; - for (const key in shape) { - json.properties[key] = this.process(shape[key], { - ...params, - path: [...params.path, "properties", key], - }); - } - // required keys - const allKeys = new Set(Object.keys(shape)); - // const optionalKeys = new Set(def.optional); - const requiredKeys = new Set([...allKeys].filter((key) => { - const v = def.shape[key]._zod; - if (this.io === "input") { - return v.optin === undefined; - } - else { - return v.optout === undefined; - } - })); - if (requiredKeys.size > 0) { - json.required = Array.from(requiredKeys); - } - // catchall - if (def.catchall?._zod.def.type === "never") { - // strict - json.additionalProperties = false; - } - else if (!def.catchall) { - // regular - if (this.io === "output") - json.additionalProperties = false; - } - else if (def.catchall) { - json.additionalProperties = this.process(def.catchall, { - ...params, - path: [...params.path, "additionalProperties"], - }); - } - break; - } - case "union": { - const json = _json; - // Discriminated unions use oneOf (exactly one match) instead of anyOf (one or more matches) - // because the discriminator field ensures mutual exclusivity between options in JSON Schema - const isDiscriminated = def.discriminator !== undefined; - const options = def.options.map((x, i) => this.process(x, { - ...params, - path: [...params.path, isDiscriminated ? "oneOf" : "anyOf", i], - })); - if (isDiscriminated) { - json.oneOf = options; - } - else { - json.anyOf = options; - } - break; - } - case "intersection": { - const json = _json; - const a = this.process(def.left, { - ...params, - path: [...params.path, "allOf", 0], - }); - const b = this.process(def.right, { - ...params, - path: [...params.path, "allOf", 1], - }); - const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1; - const allOf = [ - ...(isSimpleIntersection(a) ? a.allOf : [a]), - ...(isSimpleIntersection(b) ? b.allOf : [b]), - ]; - json.allOf = allOf; - break; - } - case "tuple": { - const json = _json; - json.type = "array"; - const prefixPath = this.target === "draft-2020-12" ? "prefixItems" : "items"; - const restPath = this.target === "draft-2020-12" ? "items" : this.target === "openapi-3.0" ? "items" : "additionalItems"; - const prefixItems = def.items.map((x, i) => this.process(x, { - ...params, - path: [...params.path, prefixPath, i], - })); - const rest = def.rest - ? this.process(def.rest, { - ...params, - path: [...params.path, restPath, ...(this.target === "openapi-3.0" ? [def.items.length] : [])], - }) - : null; - if (this.target === "draft-2020-12") { - json.prefixItems = prefixItems; - if (rest) { - json.items = rest; - } - } - else if (this.target === "openapi-3.0") { - json.items = { - anyOf: prefixItems, - }; - if (rest) { - json.items.anyOf.push(rest); - } - json.minItems = prefixItems.length; - if (!rest) { - json.maxItems = prefixItems.length; - } - } - else { - json.items = prefixItems; - if (rest) { - json.additionalItems = rest; - } - } - // length - const { minimum, maximum } = schema._zod.bag; - if (typeof minimum === "number") - json.minItems = minimum; - if (typeof maximum === "number") - json.maxItems = maximum; - break; - } - case "record": { - const json = _json; - json.type = "object"; - if (this.target === "draft-7" || this.target === "draft-2020-12") { - json.propertyNames = this.process(def.keyType, { - ...params, - path: [...params.path, "propertyNames"], - }); - } - json.additionalProperties = this.process(def.valueType, { - ...params, - path: [...params.path, "additionalProperties"], - }); - break; - } - case "map": { - if (this.unrepresentable === "throw") { - throw new Error("Map cannot be represented in JSON Schema"); - } - break; - } - case "set": { - if (this.unrepresentable === "throw") { - throw new Error("Set cannot be represented in JSON Schema"); - } - break; - } - case "enum": { - const json = _json; - const values = getEnumValues(def.entries); - // Number enums can have both string and number values - if (values.every((v) => typeof v === "number")) - json.type = "number"; - if (values.every((v) => typeof v === "string")) - json.type = "string"; - json.enum = values; - break; - } - case "literal": { - const json = _json; - const vals = []; - for (const val of def.values) { - if (val === undefined) { - if (this.unrepresentable === "throw") { - throw new Error("Literal `undefined` cannot be represented in JSON Schema"); - } - else { - // do not add to vals - } - } - else if (typeof val === "bigint") { - if (this.unrepresentable === "throw") { - throw new Error("BigInt literals cannot be represented in JSON Schema"); - } - else { - vals.push(Number(val)); - } - } - else { - vals.push(val); - } - } - if (vals.length === 0) { - // do nothing (an undefined literal was stripped) - } - else if (vals.length === 1) { - const val = vals[0]; - json.type = val === null ? "null" : typeof val; - if (this.target === "draft-4" || this.target === "openapi-3.0") { - json.enum = [val]; - } - else { - json.const = val; - } - } - else { - if (vals.every((v) => typeof v === "number")) - json.type = "number"; - if (vals.every((v) => typeof v === "string")) - json.type = "string"; - if (vals.every((v) => typeof v === "boolean")) - json.type = "string"; - if (vals.every((v) => v === null)) - json.type = "null"; - json.enum = vals; - } - break; - } - case "file": { - const json = _json; - const file = { - type: "string", - format: "binary", - contentEncoding: "binary", - }; - const { minimum, maximum, mime } = schema._zod.bag; - if (minimum !== undefined) - file.minLength = minimum; - if (maximum !== undefined) - file.maxLength = maximum; - if (mime) { - if (mime.length === 1) { - file.contentMediaType = mime[0]; - Object.assign(json, file); - } - else { - json.anyOf = mime.map((m) => { - const mFile = { ...file, contentMediaType: m }; - return mFile; - }); - } - } - else { - Object.assign(json, file); - } - // if (this.unrepresentable === "throw") { - // throw new Error("File cannot be represented in JSON Schema"); - // } - break; - } - case "transform": { - if (this.unrepresentable === "throw") { - throw new Error("Transforms cannot be represented in JSON Schema"); - } - break; - } - case "nullable": { - const inner = this.process(def.innerType, params); - if (this.target === "openapi-3.0") { - result.ref = def.innerType; - _json.nullable = true; - } - else { - _json.anyOf = [inner, { type: "null" }]; - } - break; - } - case "nonoptional": { - this.process(def.innerType, params); - result.ref = def.innerType; - break; - } - case "success": { - const json = _json; - json.type = "boolean"; - break; - } - case "default": { - this.process(def.innerType, params); - result.ref = def.innerType; - _json.default = JSON.parse(JSON.stringify(def.defaultValue)); - break; - } - case "prefault": { - this.process(def.innerType, params); - result.ref = def.innerType; - if (this.io === "input") - _json._prefault = JSON.parse(JSON.stringify(def.defaultValue)); - break; - } - case "catch": { - // use conditionals - this.process(def.innerType, params); - result.ref = def.innerType; - let catchValue; - try { - catchValue = def.catchValue(undefined); - } - catch { - throw new Error("Dynamic catch values are not supported in JSON Schema"); - } - _json.default = catchValue; - break; - } - case "nan": { - if (this.unrepresentable === "throw") { - throw new Error("NaN cannot be represented in JSON Schema"); - } - break; - } - case "template_literal": { - const json = _json; - const pattern = schema._zod.pattern; - if (!pattern) - throw new Error("Pattern not found in template literal"); - json.type = "string"; - json.pattern = pattern.source; - break; - } - case "pipe": { - const innerType = this.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out; - this.process(innerType, params); - result.ref = innerType; - break; - } - case "readonly": { - this.process(def.innerType, params); - result.ref = def.innerType; - _json.readOnly = true; - break; - } - // passthrough types - case "promise": { - this.process(def.innerType, params); - result.ref = def.innerType; - break; - } - case "optional": { - this.process(def.innerType, params); - result.ref = def.innerType; - break; - } - case "lazy": { - const innerType = schema._zod.innerType; - this.process(innerType, params); - result.ref = innerType; - break; - } - case "custom": { - if (this.unrepresentable === "throw") { - throw new Error("Custom types cannot be represented in JSON Schema"); - } - break; - } - case "function": { - if (this.unrepresentable === "throw") { - throw new Error("Function types cannot be represented in JSON Schema"); - } - break; - } - default: { - def; - } - } - } + else if (schema._zod.processJSONSchema) { + schema._zod.processJSONSchema(ctx, result.schema, params); } - // metadata - const meta = this.metadataRegistry.get(schema); - if (meta) - Object.assign(result.schema, meta); - if (this.io === "input" && isTransforming(schema)) { - // examples/defaults only apply to output type of pipe - delete result.schema.examples; - delete result.schema.default; + else { + const _json = result.schema; + const processor = ctx.processors[def.type]; + if (!processor) { + throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`); + } + processor(schema, ctx, _json, params); + } + } + // metadata + const meta = ctx.metadataRegistry.get(schema); + if (meta) + Object.assign(result.schema, meta); + if (ctx.io === "input" && isTransforming(schema)) { + // examples/defaults only apply to output type of pipe + delete result.schema.examples; + delete result.schema.default; + } + // set prefault as default + if (ctx.io === "input" && result.schema._prefault) + (_a = result.schema).default ?? (_a.default = result.schema._prefault); + delete result.schema._prefault; + // pulling fresh from ctx.seen in case it was overwritten + const _result = ctx.seen.get(schema); + return _result.schema; +} +function extractDefs(ctx, schema +// params: EmitParams +) { + // iterate over seen map; + const root = ctx.seen.get(schema); + if (!root) + throw new Error("Unprocessed schema. This is a bug in Zod."); + // returns a ref to the schema + // defId will be empty if the ref points to an external schema (or #) + const makeURI = (entry) => { + // comparing the seen objects because sometimes + // multiple schemas map to the same seen object. + // e.g. lazy + // external is configured + const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions"; + if (ctx.external) { + const externalId = ctx.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${ctx.counter++}`; + // check if schema is in the external registry + const uriGenerator = ctx.external.uri ?? ((id) => id); + if (externalId) { + return { ref: uriGenerator(externalId) }; + } + // otherwise, add to __shared + const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`; + entry[1].defId = id; // set defId so it will be reused if needed + return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` }; + } + if (entry[1] === root) { + return { ref: "#" }; + } + // self-contained schema + const uriPrefix = `#`; + const defUriPrefix = `${uriPrefix}/${defsSegment}/`; + const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`; + return { defId, ref: defUriPrefix + defId }; + }; + // stored cached version in `def` property + // remove all properties, set $ref + const extractToDef = (entry) => { + // if the schema is already a reference, do not extract it + if (entry[1].schema.$ref) { + return; } - // set prefault as default - if (this.io === "input" && result.schema._prefault) - (_a = result.schema).default ?? (_a.default = result.schema._prefault); - delete result.schema._prefault; - // pulling fresh from this.seen in case it was overwritten - const _result = this.seen.get(schema); - return _result.schema; - } - emit(schema, _params) { - const params = { - cycles: _params?.cycles ?? "ref", - reused: _params?.reused ?? "inline", - // unrepresentable: _params?.unrepresentable ?? "throw", - // uri: _params?.uri ?? ((id) => `${id}`), - external: _params?.external ?? undefined, - }; - // iterate over seen map; - const root = this.seen.get(schema); - if (!root) - throw new Error("Unprocessed schema. This is a bug in Zod."); - // initialize result with root schema fields - // Object.assign(result, seen.cached); - // returns a ref to the schema - // defId will be empty if the ref points to an external schema (or #) - const makeURI = (entry) => { - // comparing the seen objects because sometimes - // multiple schemas map to the same seen object. - // e.g. lazy - // external is configured - const defsSegment = this.target === "draft-2020-12" ? "$defs" : "definitions"; - if (params.external) { - const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`; - // check if schema is in the external registry - const uriGenerator = params.external.uri ?? ((id) => id); - if (externalId) { - return { ref: uriGenerator(externalId) }; - } - // otherwise, add to __shared - const id = entry[1].defId ?? entry[1].schema.id ?? `schema${this.counter++}`; - entry[1].defId = id; // set defId so it will be reused if needed - return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` }; - } - if (entry[1] === root) { - return { ref: "#" }; - } - // self-contained schema - const uriPrefix = `#`; - const defUriPrefix = `${uriPrefix}/${defsSegment}/`; - const defId = entry[1].schema.id ?? `__schema${this.counter++}`; - return { defId, ref: defUriPrefix + defId }; - }; - // stored cached version in `def` property - // remove all properties, set $ref - const extractToDef = (entry) => { - // if the schema is already a reference, do not extract it - if (entry[1].schema.$ref) { - return; - } + const seen = entry[1]; + const { ref, defId } = makeURI(entry); + seen.def = { ...seen.schema }; + // defId won't be set if the schema is a reference to an external schema + // or if the schema is the root schema + if (defId) + seen.defId = defId; + // wipe away all properties except $ref + const schema = seen.schema; + for (const key in schema) { + delete schema[key]; + } + schema.$ref = ref; + }; + // throw on cycles + // break cycles + if (ctx.cycles === "throw") { + for (const entry of ctx.seen.entries()) { const seen = entry[1]; - const { ref, defId } = makeURI(entry); - seen.def = { ...seen.schema }; - // defId won't be set if the schema is a reference to an external schema - if (defId) - seen.defId = defId; - // wipe away all properties except $ref - const schema = seen.schema; - for (const key in schema) { - delete schema[key]; - } - schema.$ref = ref; - }; - // throw on cycles - // break cycles - if (params.cycles === "throw") { - for (const entry of this.seen.entries()) { - const seen = entry[1]; - if (seen.cycle) { - throw new Error("Cycle detected: " + - `#/${seen.cycle?.join("/")}/` + - '\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.'); - } + if (seen.cycle) { + throw new Error("Cycle detected: " + + `#/${seen.cycle?.join("/")}/` + + '\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.'); } } - // extract schemas into $defs - for (const entry of this.seen.entries()) { - const seen = entry[1]; - // convert root schema to # $ref - if (schema === entry[0]) { - extractToDef(entry); // this has special handling for the root schema - continue; - } - // extract schemas that are in the external registry - if (params.external) { - const ext = params.external.registry.get(entry[0])?.id; - if (schema !== entry[0] && ext) { - extractToDef(entry); - continue; - } - } - // extract schemas with `id` meta - const id = this.metadataRegistry.get(entry[0])?.id; - if (id) { - extractToDef(entry); - continue; - } - // break cycles - if (seen.cycle) { - // any + } + // extract schemas into $defs + for (const entry of ctx.seen.entries()) { + const seen = entry[1]; + // convert root schema to # $ref + if (schema === entry[0]) { + extractToDef(entry); // this has special handling for the root schema + continue; + } + // extract schemas that are in the external registry + if (ctx.external) { + const ext = ctx.external.registry.get(entry[0])?.id; + if (schema !== entry[0] && ext) { extractToDef(entry); continue; } - // extract reused schemas - if (seen.count > 1) { - if (params.reused === "ref") { - extractToDef(entry); - // biome-ignore lint: - continue; - } - } - } - // flatten _refs - const flattenRef = (zodSchema, params) => { - const seen = this.seen.get(zodSchema); - const schema = seen.def ?? seen.schema; - const _cached = { ...schema }; - // already seen - if (seen.ref === null) { - return; - } - // flatten ref if defined - const ref = seen.ref; - seen.ref = null; // prevent recursion - if (ref) { - flattenRef(ref, params); - // merge referenced schema into current - const refSchema = this.seen.get(ref).schema; - if (refSchema.$ref && - (params.target === "draft-7" || params.target === "draft-4" || params.target === "openapi-3.0")) { - schema.allOf = schema.allOf ?? []; - schema.allOf.push(refSchema); - } - else { - Object.assign(schema, refSchema); - Object.assign(schema, _cached); // prevent overwriting any fields in the original schema - } - } - // execute overrides - if (!seen.isParent) - this.override({ - zodSchema: zodSchema, - jsonSchema: schema, - path: seen.path ?? [], - }); - }; - for (const entry of [...this.seen.entries()].reverse()) { - flattenRef(entry[0], { target: this.target }); - } - const result = {}; - if (this.target === "draft-2020-12") { - result.$schema = "https://json-schema.org/draft/2020-12/schema"; - } - else if (this.target === "draft-7") { - result.$schema = "http://json-schema.org/draft-07/schema#"; } - else if (this.target === "draft-4") { - result.$schema = "http://json-schema.org/draft-04/schema#"; - } - else if (this.target === "openapi-3.0") { - // OpenAPI 3.0 schema objects should not include a $schema property - } - else { - // @ts-ignore - console.warn(`Invalid target: ${this.target}`); - } - if (params.external?.uri) { - const id = params.external.registry.get(schema)?.id; - if (!id) - throw new Error("Schema is missing an `id` property"); - result.$id = params.external.uri(id); - } - Object.assign(result, root.def); - // build defs object - const defs = params.external?.defs ?? {}; - for (const entry of this.seen.entries()) { - const seen = entry[1]; - if (seen.def && seen.defId) { - defs[seen.defId] = seen.def; - } + // extract schemas with `id` meta + const id = ctx.metadataRegistry.get(entry[0])?.id; + if (id) { + extractToDef(entry); + continue; } - // set definitions in result - if (params.external) { + // break cycles + if (seen.cycle) { + // any + extractToDef(entry); + continue; } - else { - if (Object.keys(defs).length > 0) { - if (this.target === "draft-2020-12") { - result.$defs = defs; - } - else { - result.definitions = defs; - } + // extract reused schemas + if (seen.count > 1) { + if (ctx.reused === "ref") { + extractToDef(entry); + // biome-ignore lint: + continue; } } - try { - // this "finalizes" this schema and ensures all cycles are removed - // each call to .emit() is functionally independent - // though the seen map is shared - return JSON.parse(JSON.stringify(result)); - } - catch (_err) { - throw new Error("Error converting schema to JSON."); - } } } -function toJSONSchema(input, _params) { - if (input instanceof $ZodRegistry) { - const gen = new JSONSchemaGenerator(_params); - const defs = {}; - for (const entry of input._idmap.entries()) { - const [_, schema] = entry; - gen.process(schema); +function finalize(ctx, schema) { + // + // iterate over seen map; + const root = ctx.seen.get(schema); + if (!root) + throw new Error("Unprocessed schema. This is a bug in Zod."); + // flatten _refs + const flattenRef = (zodSchema) => { + const seen = ctx.seen.get(zodSchema); + const schema = seen.def ?? seen.schema; + const _cached = { ...schema }; + // already seen + if (seen.ref === null) { + return; } - const schemas = {}; - const external = { - registry: input, - uri: _params?.uri, - defs, - }; - for (const entry of input._idmap.entries()) { - const [key, schema] = entry; - schemas[key] = gen.emit(schema, { - ..._params, - external, + // flatten ref if defined + const ref = seen.ref; + seen.ref = null; // prevent recursion + if (ref) { + flattenRef(ref); + // merge referenced schema into current + const refSchema = ctx.seen.get(ref).schema; + if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) { + schema.allOf = schema.allOf ?? []; + schema.allOf.push(refSchema); + } + else { + Object.assign(schema, refSchema); + Object.assign(schema, _cached); // prevent overwriting any fields in the original schema + } + } + // execute overrides + if (!seen.isParent) + ctx.override({ + zodSchema: zodSchema, + jsonSchema: schema, + path: seen.path ?? [], }); + }; + for (const entry of [...ctx.seen.entries()].reverse()) { + flattenRef(entry[0]); + } + const result = {}; + if (ctx.target === "draft-2020-12") { + result.$schema = "https://json-schema.org/draft/2020-12/schema"; + } + else if (ctx.target === "draft-07") { + result.$schema = "http://json-schema.org/draft-07/schema#"; + } + else if (ctx.target === "draft-04") { + result.$schema = "http://json-schema.org/draft-04/schema#"; + } + else if (ctx.target === "openapi-3.0") { + // OpenAPI 3.0 schema objects should not include a $schema property + } + else { + // Arbitrary string values are allowed but won't have a $schema property set + } + if (ctx.external?.uri) { + const id = ctx.external.registry.get(schema)?.id; + if (!id) + throw new Error("Schema is missing an `id` property"); + result.$id = ctx.external.uri(id); + } + Object.assign(result, root.def ?? root.schema); + // build defs object + const defs = ctx.external?.defs ?? {}; + for (const entry of ctx.seen.entries()) { + const seen = entry[1]; + if (seen.def && seen.defId) { + defs[seen.defId] = seen.def; } + } + // set definitions in result + if (ctx.external) { + } + else { if (Object.keys(defs).length > 0) { - const defsSegment = gen.target === "draft-2020-12" ? "$defs" : "definitions"; - schemas.__shared = { - [defsSegment]: defs, - }; + if (ctx.target === "draft-2020-12") { + result.$defs = defs; + } + else { + result.definitions = defs; + } } - return { schemas }; } - const gen = new JSONSchemaGenerator(_params); - gen.process(input); - return gen.emit(input, _params); + try { + // this "finalizes" this schema and ensures all cycles are removed + // each call to finalize() is functionally independent + // though the seen map is shared + const finalized = JSON.parse(JSON.stringify(result)); + Object.defineProperty(finalized, "~standard", { + value: { + ...schema["~standard"], + jsonSchema: { + input: createStandardJSONSchemaMethod(schema, "input"), + output: createStandardJSONSchemaMethod(schema, "output"), + }, + }, + enumerable: false, + writable: false, + }); + return finalized; + } + catch (_err) { + throw new Error("Error converting schema to JSON."); + } } function isTransforming(_schema, _ctx) { const ctx = _ctx ?? { seen: new Set() }; @@ -62248,6 +61616,696 @@ function isTransforming(_schema, _ctx) { } return false; } +/** + * Creates a toJSONSchema method for a schema instance. + * This encapsulates the logic of initializing context, processing, extracting defs, and finalizing. + */ +const createToJSONSchemaMethod = (schema, processors = {}) => (params) => { + const ctx = initializeContext({ ...params, processors }); + to_json_schema_process(schema, ctx); + extractDefs(ctx, schema); + return finalize(ctx, schema); +}; +const createStandardJSONSchemaMethod = (schema, io) => (params) => { + const { libraryOptions, target } = params ?? {}; + const ctx = initializeContext({ ...(libraryOptions ?? {}), target, io, processors: {} }); + to_json_schema_process(schema, ctx); + extractDefs(ctx, schema); + return finalize(ctx, schema); +}; + +;// CONCATENATED MODULE: ./node_modules/zod/v4/core/json-schema-processors.js + + +const formatMap = { + guid: "uuid", + url: "uri", + datetime: "date-time", + json_string: "json-string", + regex: "", // do not set +}; +// ==================== SIMPLE TYPE PROCESSORS ==================== +const stringProcessor = (schema, ctx, _json, _params) => { + const json = _json; + json.type = "string"; + const { minimum, maximum, format, patterns, contentEncoding } = schema._zod + .bag; + if (typeof minimum === "number") + json.minLength = minimum; + if (typeof maximum === "number") + json.maxLength = maximum; + // custom pattern overrides format + if (format) { + json.format = formatMap[format] ?? format; + if (json.format === "") + delete json.format; // empty format is not valid + } + if (contentEncoding) + json.contentEncoding = contentEncoding; + if (patterns && patterns.size > 0) { + const regexes = [...patterns]; + if (regexes.length === 1) + json.pattern = regexes[0].source; + else if (regexes.length > 1) { + json.allOf = [ + ...regexes.map((regex) => ({ + ...(ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0" + ? { type: "string" } + : {}), + pattern: regex.source, + })), + ]; + } + } +}; +const numberProcessor = (schema, ctx, _json, _params) => { + const json = _json; + const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag; + if (typeof format === "string" && format.includes("int")) + json.type = "integer"; + else + json.type = "number"; + if (typeof exclusiveMinimum === "number") { + if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") { + json.minimum = exclusiveMinimum; + json.exclusiveMinimum = true; + } + else { + json.exclusiveMinimum = exclusiveMinimum; + } + } + if (typeof minimum === "number") { + json.minimum = minimum; + if (typeof exclusiveMinimum === "number" && ctx.target !== "draft-04") { + if (exclusiveMinimum >= minimum) + delete json.minimum; + else + delete json.exclusiveMinimum; + } + } + if (typeof exclusiveMaximum === "number") { + if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") { + json.maximum = exclusiveMaximum; + json.exclusiveMaximum = true; + } + else { + json.exclusiveMaximum = exclusiveMaximum; + } + } + if (typeof maximum === "number") { + json.maximum = maximum; + if (typeof exclusiveMaximum === "number" && ctx.target !== "draft-04") { + if (exclusiveMaximum <= maximum) + delete json.maximum; + else + delete json.exclusiveMaximum; + } + } + if (typeof multipleOf === "number") + json.multipleOf = multipleOf; +}; +const booleanProcessor = (_schema, _ctx, json, _params) => { + json.type = "boolean"; +}; +const bigintProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("BigInt cannot be represented in JSON Schema"); + } +}; +const symbolProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Symbols cannot be represented in JSON Schema"); + } +}; +const nullProcessor = (_schema, ctx, json, _params) => { + if (ctx.target === "openapi-3.0") { + json.type = "string"; + json.nullable = true; + json.enum = [null]; + } + else { + json.type = "null"; + } +}; +const undefinedProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Undefined cannot be represented in JSON Schema"); + } +}; +const voidProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Void cannot be represented in JSON Schema"); + } +}; +const neverProcessor = (_schema, _ctx, json, _params) => { + json.not = {}; +}; +const anyProcessor = (_schema, _ctx, _json, _params) => { + // empty schema accepts anything +}; +const unknownProcessor = (_schema, _ctx, _json, _params) => { + // empty schema accepts anything +}; +const dateProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Date cannot be represented in JSON Schema"); + } +}; +const enumProcessor = (schema, _ctx, json, _params) => { + const def = schema._zod.def; + const values = getEnumValues(def.entries); + // Number enums can have both string and number values + if (values.every((v) => typeof v === "number")) + json.type = "number"; + if (values.every((v) => typeof v === "string")) + json.type = "string"; + json.enum = values; +}; +const literalProcessor = (schema, ctx, json, _params) => { + const def = schema._zod.def; + const vals = []; + for (const val of def.values) { + if (val === undefined) { + if (ctx.unrepresentable === "throw") { + throw new Error("Literal `undefined` cannot be represented in JSON Schema"); + } + else { + // do not add to vals + } + } + else if (typeof val === "bigint") { + if (ctx.unrepresentable === "throw") { + throw new Error("BigInt literals cannot be represented in JSON Schema"); + } + else { + vals.push(Number(val)); + } + } + else { + vals.push(val); + } + } + if (vals.length === 0) { + // do nothing (an undefined literal was stripped) + } + else if (vals.length === 1) { + const val = vals[0]; + json.type = val === null ? "null" : typeof val; + if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") { + json.enum = [val]; + } + else { + json.const = val; + } + } + else { + if (vals.every((v) => typeof v === "number")) + json.type = "number"; + if (vals.every((v) => typeof v === "string")) + json.type = "string"; + if (vals.every((v) => typeof v === "boolean")) + json.type = "boolean"; + if (vals.every((v) => v === null)) + json.type = "null"; + json.enum = vals; + } +}; +const nanProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("NaN cannot be represented in JSON Schema"); + } +}; +const templateLiteralProcessor = (schema, _ctx, json, _params) => { + const _json = json; + const pattern = schema._zod.pattern; + if (!pattern) + throw new Error("Pattern not found in template literal"); + _json.type = "string"; + _json.pattern = pattern.source; +}; +const fileProcessor = (schema, _ctx, json, _params) => { + const _json = json; + const file = { + type: "string", + format: "binary", + contentEncoding: "binary", + }; + const { minimum, maximum, mime } = schema._zod.bag; + if (minimum !== undefined) + file.minLength = minimum; + if (maximum !== undefined) + file.maxLength = maximum; + if (mime) { + if (mime.length === 1) { + file.contentMediaType = mime[0]; + Object.assign(_json, file); + } + else { + _json.anyOf = mime.map((m) => { + const mFile = { ...file, contentMediaType: m }; + return mFile; + }); + } + } + else { + Object.assign(_json, file); + } +}; +const successProcessor = (_schema, _ctx, json, _params) => { + json.type = "boolean"; +}; +const customProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Custom types cannot be represented in JSON Schema"); + } +}; +const functionProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Function types cannot be represented in JSON Schema"); + } +}; +const transformProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Transforms cannot be represented in JSON Schema"); + } +}; +const mapProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Map cannot be represented in JSON Schema"); + } +}; +const setProcessor = (_schema, ctx, _json, _params) => { + if (ctx.unrepresentable === "throw") { + throw new Error("Set cannot be represented in JSON Schema"); + } +}; +// ==================== COMPOSITE TYPE PROCESSORS ==================== +const arrayProcessor = (schema, ctx, _json, params) => { + const json = _json; + const def = schema._zod.def; + const { minimum, maximum } = schema._zod.bag; + if (typeof minimum === "number") + json.minItems = minimum; + if (typeof maximum === "number") + json.maxItems = maximum; + json.type = "array"; + json.items = to_json_schema_process(def.element, ctx, { ...params, path: [...params.path, "items"] }); +}; +const objectProcessor = (schema, ctx, _json, params) => { + const json = _json; + const def = schema._zod.def; + json.type = "object"; + json.properties = {}; + const shape = def.shape; + for (const key in shape) { + json.properties[key] = to_json_schema_process(shape[key], ctx, { + ...params, + path: [...params.path, "properties", key], + }); + } + // required keys + const allKeys = new Set(Object.keys(shape)); + const requiredKeys = new Set([...allKeys].filter((key) => { + const v = def.shape[key]._zod; + if (ctx.io === "input") { + return v.optin === undefined; + } + else { + return v.optout === undefined; + } + })); + if (requiredKeys.size > 0) { + json.required = Array.from(requiredKeys); + } + // catchall + if (def.catchall?._zod.def.type === "never") { + // strict + json.additionalProperties = false; + } + else if (!def.catchall) { + // regular + if (ctx.io === "output") + json.additionalProperties = false; + } + else if (def.catchall) { + json.additionalProperties = to_json_schema_process(def.catchall, ctx, { + ...params, + path: [...params.path, "additionalProperties"], + }); + } +}; +const unionProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + // Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches) + // This includes both z.xor() and discriminated unions + const isExclusive = def.inclusive === false; + const options = def.options.map((x, i) => to_json_schema_process(x, ctx, { + ...params, + path: [...params.path, isExclusive ? "oneOf" : "anyOf", i], + })); + if (isExclusive) { + json.oneOf = options; + } + else { + json.anyOf = options; + } +}; +const intersectionProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + const a = to_json_schema_process(def.left, ctx, { + ...params, + path: [...params.path, "allOf", 0], + }); + const b = to_json_schema_process(def.right, ctx, { + ...params, + path: [...params.path, "allOf", 1], + }); + const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1; + const allOf = [ + ...(isSimpleIntersection(a) ? a.allOf : [a]), + ...(isSimpleIntersection(b) ? b.allOf : [b]), + ]; + json.allOf = allOf; +}; +const tupleProcessor = (schema, ctx, _json, params) => { + const json = _json; + const def = schema._zod.def; + json.type = "array"; + const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items"; + const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems"; + const prefixItems = def.items.map((x, i) => to_json_schema_process(x, ctx, { + ...params, + path: [...params.path, prefixPath, i], + })); + const rest = def.rest + ? to_json_schema_process(def.rest, ctx, { + ...params, + path: [...params.path, restPath, ...(ctx.target === "openapi-3.0" ? [def.items.length] : [])], + }) + : null; + if (ctx.target === "draft-2020-12") { + json.prefixItems = prefixItems; + if (rest) { + json.items = rest; + } + } + else if (ctx.target === "openapi-3.0") { + json.items = { + anyOf: prefixItems, + }; + if (rest) { + json.items.anyOf.push(rest); + } + json.minItems = prefixItems.length; + if (!rest) { + json.maxItems = prefixItems.length; + } + } + else { + json.items = prefixItems; + if (rest) { + json.additionalItems = rest; + } + } + // length + const { minimum, maximum } = schema._zod.bag; + if (typeof minimum === "number") + json.minItems = minimum; + if (typeof maximum === "number") + json.maxItems = maximum; +}; +const recordProcessor = (schema, ctx, _json, params) => { + const json = _json; + const def = schema._zod.def; + json.type = "object"; + if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") { + json.propertyNames = to_json_schema_process(def.keyType, ctx, { + ...params, + path: [...params.path, "propertyNames"], + }); + } + json.additionalProperties = to_json_schema_process(def.valueType, ctx, { + ...params, + path: [...params.path, "additionalProperties"], + }); +}; +const nullableProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + const inner = to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + if (ctx.target === "openapi-3.0") { + seen.ref = def.innerType; + json.nullable = true; + } + else { + json.anyOf = [inner, { type: "null" }]; + } +}; +const nonoptionalProcessor = (schema, ctx, _json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; +}; +const defaultProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; + json.default = JSON.parse(JSON.stringify(def.defaultValue)); +}; +const prefaultProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; + if (ctx.io === "input") + json._prefault = JSON.parse(JSON.stringify(def.defaultValue)); +}; +const catchProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; + let catchValue; + try { + catchValue = def.catchValue(undefined); + } + catch { + throw new Error("Dynamic catch values are not supported in JSON Schema"); + } + json.default = catchValue; +}; +const pipeProcessor = (schema, ctx, _json, params) => { + const def = schema._zod.def; + const innerType = ctx.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out; + to_json_schema_process(innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = innerType; +}; +const readonlyProcessor = (schema, ctx, json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; + json.readOnly = true; +}; +const promiseProcessor = (schema, ctx, _json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; +}; +const optionalProcessor = (schema, ctx, _json, params) => { + const def = schema._zod.def; + to_json_schema_process(def.innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = def.innerType; +}; +const lazyProcessor = (schema, ctx, _json, params) => { + const innerType = schema._zod.innerType; + to_json_schema_process(innerType, ctx, params); + const seen = ctx.seen.get(schema); + seen.ref = innerType; +}; +// ==================== ALL PROCESSORS ==================== +const allProcessors = { + string: stringProcessor, + number: numberProcessor, + boolean: booleanProcessor, + bigint: bigintProcessor, + symbol: symbolProcessor, + null: nullProcessor, + undefined: undefinedProcessor, + void: voidProcessor, + never: neverProcessor, + any: anyProcessor, + unknown: unknownProcessor, + date: dateProcessor, + enum: enumProcessor, + literal: literalProcessor, + nan: nanProcessor, + template_literal: templateLiteralProcessor, + file: fileProcessor, + success: successProcessor, + custom: customProcessor, + function: functionProcessor, + transform: transformProcessor, + map: mapProcessor, + set: setProcessor, + array: arrayProcessor, + object: objectProcessor, + union: unionProcessor, + intersection: intersectionProcessor, + tuple: tupleProcessor, + record: recordProcessor, + nullable: nullableProcessor, + nonoptional: nonoptionalProcessor, + default: defaultProcessor, + prefault: prefaultProcessor, + catch: catchProcessor, + pipe: pipeProcessor, + readonly: readonlyProcessor, + promise: promiseProcessor, + optional: optionalProcessor, + lazy: lazyProcessor, +}; +function toJSONSchema(input, params) { + if ("_idmap" in input) { + // Registry case + const registry = input; + const ctx = initializeContext({ ...params, processors: allProcessors }); + const defs = {}; + // First pass: process all schemas to build the seen map + for (const entry of registry._idmap.entries()) { + const [_, schema] = entry; + to_json_schema_process(schema, ctx); + } + const schemas = {}; + const external = { + registry, + uri: params?.uri, + defs, + }; + // Update the context with external configuration + ctx.external = external; + // Second pass: emit each schema + for (const entry of registry._idmap.entries()) { + const [key, schema] = entry; + extractDefs(ctx, schema); + schemas[key] = finalize(ctx, schema); + } + if (Object.keys(defs).length > 0) { + const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions"; + schemas.__shared = { + [defsSegment]: defs, + }; + } + return { schemas }; + } + // Single schema case + const ctx = initializeContext({ ...params, processors: allProcessors }); + to_json_schema_process(input, ctx); + extractDefs(ctx, input); + return finalize(ctx, input); +} + +;// CONCATENATED MODULE: ./node_modules/zod/v4/core/json-schema-generator.js + + +/** + * Legacy class-based interface for JSON Schema generation. + * This class wraps the new functional implementation to provide backward compatibility. + * + * @deprecated Use the `toJSONSchema` function instead for new code. + * + * @example + * ```typescript + * // Legacy usage (still supported) + * const gen = new JSONSchemaGenerator({ target: "draft-07" }); + * gen.process(schema); + * const result = gen.emit(schema); + * + * // Preferred modern usage + * const result = toJSONSchema(schema, { target: "draft-07" }); + * ``` + */ +class JSONSchemaGenerator { + /** @deprecated Access via ctx instead */ + get metadataRegistry() { + return this.ctx.metadataRegistry; + } + /** @deprecated Access via ctx instead */ + get target() { + return this.ctx.target; + } + /** @deprecated Access via ctx instead */ + get unrepresentable() { + return this.ctx.unrepresentable; + } + /** @deprecated Access via ctx instead */ + get override() { + return this.ctx.override; + } + /** @deprecated Access via ctx instead */ + get io() { + return this.ctx.io; + } + /** @deprecated Access via ctx instead */ + get counter() { + return this.ctx.counter; + } + set counter(value) { + this.ctx.counter = value; + } + /** @deprecated Access via ctx instead */ + get seen() { + return this.ctx.seen; + } + constructor(params) { + // Normalize target for internal context + let normalizedTarget = params?.target ?? "draft-2020-12"; + if (normalizedTarget === "draft-4") + normalizedTarget = "draft-04"; + if (normalizedTarget === "draft-7") + normalizedTarget = "draft-07"; + this.ctx = initializeContext({ + processors: allProcessors, + target: normalizedTarget, + ...(params?.metadata && { metadata: params.metadata }), + ...(params?.unrepresentable && { unrepresentable: params.unrepresentable }), + ...(params?.override && { override: params.override }), + ...(params?.io && { io: params.io }), + }); + } + /** + * Process a schema to prepare it for JSON Schema generation. + * This must be called before emit(). + */ + process(schema, _params = { path: [], schemaPath: [] }) { + return to_json_schema_process(schema, this.ctx, _params); + } + /** + * Emit the final JSON Schema after processing. + * Must call process() first. + */ + emit(schema, _params) { + // Apply emit params to the context + if (_params) { + if (_params.cycles) + this.ctx.cycles = _params.cycles; + if (_params.reused) + this.ctx.reused = _params.reused; + if (_params.external) + this.ctx.external = _params.external; + } + extractDefs(this.ctx, schema); + const result = finalize(this.ctx, schema); + // Strip ~standard property to match old implementation's return type + const { "~standard": _, ...plainResult } = result; + return plainResult; + } +} ;// CONCATENATED MODULE: ./node_modules/zod/v4/core/json-schema.js @@ -62268,6 +62326,8 @@ function isTransforming(_schema, _ctx) { + + ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/types/zod.js @@ -62500,6 +62560,16 @@ function isZodArrayV4(obj) { if (typeof obj === "object" && obj !== null && "_zod" in obj && typeof obj._zod === "object" && obj._zod !== null && "def" in obj._zod && typeof obj._zod.def === "object" && obj._zod.def !== null && "type" in obj._zod.def && obj._zod.def.type === "array") return true; return false; } +function isZodOptionalV4(obj) { + if (!isZodSchemaV4(obj)) return false; + if (typeof obj === "object" && obj !== null && "_zod" in obj && typeof obj._zod === "object" && obj._zod !== null && "def" in obj._zod && typeof obj._zod.def === "object" && obj._zod.def !== null && "type" in obj._zod.def && obj._zod.def.type === "optional") return true; + return false; +} +function isZodNullableV4(obj) { + if (!isZodSchemaV4(obj)) return false; + if (typeof obj === "object" && obj !== null && "_zod" in obj && typeof obj._zod === "object" && obj._zod !== null && "def" in obj._zod && typeof obj._zod.def === "object" && obj._zod.def !== null && "type" in obj._zod.def && obj._zod.def.type === "nullable") return true; + return false; +} /** * Determines if the provided value is an InteropZodObject (Zod v3 or v4 object schema). * @@ -62677,7 +62747,7 @@ function interopZodTransformInputSchemaImpl(schema, recursive, cache) { if (isZodTransformV4(schema)) outputSchema = interopZodTransformInputSchemaImpl(schema._zod.def.in, recursive, cache); if (recursive) { if (isZodObjectV4(outputSchema)) { - const outputShape = outputSchema._zod.def.shape; + const outputShape = {}; for (const [key, keySchema] of Object.entries(outputSchema._zod.def.shape)) outputShape[key] = interopZodTransformInputSchemaImpl(keySchema, recursive, cache); outputSchema = clone(outputSchema, { ...outputSchema._zod.def, @@ -62689,6 +62759,18 @@ function interopZodTransformInputSchemaImpl(schema, recursive, cache) { ...outputSchema._zod.def, element: elementSchema }); + } else if (isZodOptionalV4(outputSchema)) { + const innerSchema = interopZodTransformInputSchemaImpl(outputSchema._zod.def.innerType, recursive, cache); + outputSchema = clone(outputSchema, { + ...outputSchema._zod.def, + innerType: innerSchema + }); + } else if (isZodNullableV4(outputSchema)) { + const innerSchema = interopZodTransformInputSchemaImpl(outputSchema._zod.def.innerType, recursive, cache); + outputSchema = clone(outputSchema, { + ...outputSchema._zod.def, + innerType: innerSchema + }); } } const meta = globalRegistry.get(schema); @@ -69534,15 +69616,16 @@ __export(json_schema_exports, { /** * Converts a Zod schema or JSON schema to a JSON schema. * @param schema - The schema to convert. +* @param params - The parameters to pass to the toJSONSchema function. * @returns The converted schema. */ -function toJsonSchema(schema) { +function toJsonSchema(schema, params) { if (isZodSchemaV4(schema)) { const inputSchema = interopZodTransformInputSchema(schema, true); if (isZodObjectV4(inputSchema)) { const strictSchema = interopZodObjectStrict(inputSchema, true); - return toJSONSchema(strictSchema); - } else return toJSONSchema(schema); + return toJSONSchema(strictSchema, params); + } else return toJSONSchema(schema, params); } if (isZodSchemaV3(schema)) return zodToJsonSchema_zodToJsonSchema(schema); return schema; @@ -69620,11 +69703,17 @@ var _RootEventFilter = class { return include; } }; +const toBase64Url = (str) => { + const encoded = btoa(str); + return encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); +}; //#endregion //# sourceMappingURL=utils.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/runnables/graph_mermaid.js + + //#region src/runnables/graph_mermaid.ts function _escapeNodeLabel(nodeLabel) { return nodeLabel.replace(/[^a-zA-Z-_0-9]/g, "_"); @@ -69668,14 +69757,21 @@ function drawMermaid(nodes, edges, config) { edgeGroups[commonPrefix].push(edge); } const seenSubgraphs = /* @__PURE__ */ new Set(); + function sortPrefixesByDepth(prefixes) { + return [...prefixes].sort((a, b) => { + return a.split(":").length - b.split(":").length; + }); + } function addSubgraph(edges$1, prefix) { const selfLoop = edges$1.length === 1 && edges$1[0].source === edges$1[0].target; if (prefix && !selfLoop) { const subgraph = prefix.split(":").pop(); - if (seenSubgraphs.has(subgraph)) throw new Error(`Found duplicate subgraph '${subgraph}' -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`); - seenSubgraphs.add(subgraph); + if (seenSubgraphs.has(prefix)) throw new Error(`Found duplicate subgraph '${subgraph}' at '${prefix} -- this likely means that you're reusing a subgraph node with the same name. Please adjust your graph to have subgraph nodes with unique names.`); + seenSubgraphs.add(prefix); mermaidGraph += `\tsubgraph ${subgraph}\n`; } + const nestedPrefixes = sortPrefixesByDepth(Object.keys(edgeGroups).filter((nestedPrefix) => nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix && nestedPrefix.split(":").length === prefix.split(":").length + 1)); + for (const nestedPrefix of nestedPrefixes) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix); for (const edge of edges$1) { const { source, target, data, conditional } = edge; let edgeLabel = ""; @@ -69687,7 +69783,6 @@ function drawMermaid(nodes, edges, config) { } else edgeLabel = conditional ? " -.-> " : " --> "; mermaidGraph += `\t${_escapeNodeLabel(source)}${edgeLabel}${_escapeNodeLabel(target)};\n`; } - for (const nestedPrefix in edgeGroups) if (nestedPrefix.startsWith(`${prefix}:`) && nestedPrefix !== prefix) addSubgraph(edgeGroups[nestedPrefix], nestedPrefix); if (prefix && !selfLoop) mermaidGraph += " end\n"; } addSubgraph(edgeGroups[""] ?? [], ""); @@ -69714,7 +69809,7 @@ function drawMermaid(nodes, edges, config) { async function drawMermaidImage(mermaidSyntax, config) { let backgroundColor = config?.backgroundColor ?? "white"; const imageType = config?.imageType ?? "png"; - const mermaidSyntaxEncoded = btoa(mermaidSyntax); + const mermaidSyntaxEncoded = toBase64Url(mermaidSyntax); if (backgroundColor !== void 0) { const hexColorPattern = /^#(?:[0-9a-fA-F]{3}){1,2}$/; if (!hexColorPattern.test(backgroundColor)) backgroundColor = `!${backgroundColor}`; @@ -69986,6 +70081,7 @@ var EventStreamCallbackHandler = class extends BaseTracer { transformStream; writer; receiveStream; + readableStreamClosed = false; name = "event_stream_tracer"; lc_prefer_streaming = true; constructor(fields) { @@ -70000,7 +70096,9 @@ var EventStreamCallbackHandler = class extends BaseTracer { this.excludeNames = fields?.excludeNames; this.excludeTypes = fields?.excludeTypes; this.excludeTags = fields?.excludeTags; - this.transformStream = new TransformStream(); + this.transformStream = new TransformStream({ flush: () => { + this.readableStreamClosed = true; + } }); this.writer = this.transformStream.writable.getWriter(); this.receiveStream = IterableReadableStream.fromReadableStream(this.transformStream.readable); } @@ -70068,6 +70166,7 @@ var EventStreamCallbackHandler = class extends BaseTracer { } } async send(payload, run) { + if (this.readableStreamClosed) return; if (this._includeRun(run)) await this.writer.write(payload); } async sendEndEvent(payload, run) { @@ -70640,7 +70739,7 @@ var Runnable = class extends Serializable { } let runManager; try { - const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, void 0, void 0, config.runName ?? this.getName()), options?.signal, config); + const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, void 0, void 0, config.runName ?? this.getName(), void 0, { lc_defers_inputs: true }), options?.signal, config); delete config.runId; runManager = pipe.setup; const streamEventsHandler = runManager?.handlers.find(isStreamEventsHandler); @@ -72579,6 +72678,7 @@ __export(messages_exports, { _mergeObj: () => _mergeObj, _mergeStatus: () => _mergeStatus, coerceMessageLikeToMessage: () => utils_coerceMessageLikeToMessage, + collapseToolCallChunks: () => collapseToolCallChunks, convertToChunk: () => convertToChunk, convertToOpenAIImageBlock: () => convertToOpenAIImageBlock, convertToProviderContentBlock: () => convertToProviderContentBlock, @@ -79454,6 +79554,108 @@ var RunCollectorCallbackHandler = class extends BaseTracer { //#endregion //# sourceMappingURL=run_collector.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/utils/context.js + + +//#region src/utils/context.ts +var context_exports = {}; +__export(context_exports, { context: () => context }); +/** +* A tagged template function for creating formatted strings. +* +* This utility provides a clean, template literal-based API for string formatting +* that can be used for prompts, descriptions, and other text formatting needs. +* +* It automatically handles whitespace normalization and indentation, making it +* ideal for multi-line strings in code. +* +* When using this utility, it will: +* - Strip common leading indentation from all lines +* - Trim leading/trailing whitespace +* - Align multi-line interpolated values to match indentation +* - Support escape sequences: `\\n` (newline), `\\`` (backtick), `\\$` (dollar), `\\{` (brace) +* +* @example +* ```typescript +* import { context } from "@langchain/core/utils/context"; +* +* const role = "agent"; +* const prompt = context` +* You are an ${role}. +* Your task is to help users. +* `; +* // Returns: "You are an agent.\nYour task is to help users." +* ``` +* +* @example +* ```typescript +* // Multi-line interpolated values are aligned +* const items = "- Item 1\n- Item 2\n- Item 3"; +* const message = context` +* Shopping list: +* ${items} +* End of list. +* `; +* // The items will be indented to match " " (4 spaces) +* ``` +*/ +function context(strings, ...values) { + const raw = strings.raw; + let result = ""; + for (let i = 0; i < raw.length; i++) { + const next = raw[i].replace(/\\\n[ \t]*/g, "").replace(/\\`/g, "`").replace(/\\\$/g, "$").replace(/\\\{/g, "{"); + result += next; + if (i < values.length) { + const value = alignValue(values[i], result); + result += typeof value === "string" ? value : JSON.stringify(value); + } + } + result = stripIndent(result); + result = result.trim(); + result = result.replace(/\\n/g, "\n"); + return result; +} +/** +* Adjusts the indentation of a multi-line interpolated value to match the current line. +* +* @param value - The interpolated value +* @param precedingText - The text that comes before this value +* @returns The value with adjusted indentation +*/ +function alignValue(value, precedingText) { + if (typeof value !== "string" || !value.includes("\n")) return value; + const currentLine = precedingText.slice(precedingText.lastIndexOf("\n") + 1); + const indentMatch = currentLine.match(/^(\s+)/); + if (indentMatch) { + const indent = indentMatch[1]; + return value.replace(/\n/g, `\n${indent}`); + } + return value; +} +/** +* Strips common leading indentation from all lines. +* +* @param text - The text to process +* @returns The text with common indentation removed +*/ +function stripIndent(text) { + const lines = text.split("\n"); + let minIndent = null; + for (const line of lines) { + const match = line.match(/^(\s+)\S+/); + if (match) { + const indent = match[1].length; + if (minIndent === null) minIndent = indent; + else minIndent = Math.min(minIndent, indent); + } + } + if (minIndent === null) return text; + return lines.map((line) => line[0] === " " || line[0] === " " ? line.slice(minIndent) : line).join("\n"); +} + +//#endregion + +//# sourceMappingURL=context.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/core/dist/output_parsers/openai_functions/json_output_functions_parsers.js @@ -80285,8 +80487,17 @@ const parse_safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError); + + const schemas_ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => { $ZodType.init(inst, def); + Object.assign(inst["~standard"], { + jsonSchema: { + input: createStandardJSONSchemaMethod(inst, "input"), + output: createStandardJSONSchemaMethod(inst, "output"), + }, + }); + inst.toJSONSchema = createToJSONSchemaMethod(inst, {}); inst.def = def; inst.type = def.type; Object.defineProperty(inst, "_def", { value: def }); @@ -80368,6 +80579,7 @@ const schemas_ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => { const _ZodString = /*@__PURE__*/ $constructor("_ZodString", (inst, def) => { $ZodString.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => stringProcessor(inst, ctx, json, params); const bag = inst._zod.bag; inst.format = bag.format ?? null; inst.minLength = bag.minimum ?? null; @@ -80630,6 +80842,7 @@ function hash(alg, params) { const schemas_ZodNumber = /*@__PURE__*/ $constructor("ZodNumber", (inst, def) => { $ZodNumber.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => numberProcessor(inst, ctx, json, params); inst.gt = (value, params) => inst.check(_gt(value, params)); inst.gte = (value, params) => inst.check(_gte(value, params)); inst.min = (value, params) => inst.check(_gte(value, params)); @@ -80680,6 +80893,7 @@ function uint32(params) { const schemas_ZodBoolean = /*@__PURE__*/ $constructor("ZodBoolean", (inst, def) => { $ZodBoolean.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => booleanProcessor(inst, ctx, json, params); }); function schemas_boolean(params) { return _boolean(schemas_ZodBoolean, params); @@ -80687,6 +80901,7 @@ function schemas_boolean(params) { const schemas_ZodBigInt = /*@__PURE__*/ $constructor("ZodBigInt", (inst, def) => { $ZodBigInt.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => bigintProcessor(inst, ctx, json, params); inst.gte = (value, params) => inst.check(_gte(value, params)); inst.min = (value, params) => inst.check(_gte(value, params)); inst.gt = (value, params) => inst.check(_gt(value, params)); @@ -80723,6 +80938,7 @@ function uint64(params) { const schemas_ZodSymbol = /*@__PURE__*/ $constructor("ZodSymbol", (inst, def) => { $ZodSymbol.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => symbolProcessor(inst, ctx, json, params); }); function symbol(params) { return _symbol(schemas_ZodSymbol, params); @@ -80730,6 +80946,7 @@ function symbol(params) { const schemas_ZodUndefined = /*@__PURE__*/ $constructor("ZodUndefined", (inst, def) => { $ZodUndefined.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => undefinedProcessor(inst, ctx, json, params); }); function schemas_undefined(params) { return api_undefined(schemas_ZodUndefined, params); @@ -80738,6 +80955,7 @@ function schemas_undefined(params) { const schemas_ZodNull = /*@__PURE__*/ $constructor("ZodNull", (inst, def) => { $ZodNull.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => nullProcessor(inst, ctx, json, params); }); function schemas_null(params) { return api_null(schemas_ZodNull, params); @@ -80746,6 +80964,7 @@ function schemas_null(params) { const schemas_ZodAny = /*@__PURE__*/ $constructor("ZodAny", (inst, def) => { $ZodAny.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => anyProcessor(inst, ctx, json, params); }); function any() { return _any(schemas_ZodAny); @@ -80753,6 +80972,7 @@ function any() { const schemas_ZodUnknown = /*@__PURE__*/ $constructor("ZodUnknown", (inst, def) => { $ZodUnknown.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => unknownProcessor(inst, ctx, json, params); }); function unknown() { return _unknown(schemas_ZodUnknown); @@ -80760,6 +80980,7 @@ function unknown() { const schemas_ZodNever = /*@__PURE__*/ $constructor("ZodNever", (inst, def) => { $ZodNever.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => neverProcessor(inst, ctx, json, params); }); function schemas_never(params) { return _never(schemas_ZodNever, params); @@ -80767,6 +80988,7 @@ function schemas_never(params) { const schemas_ZodVoid = /*@__PURE__*/ $constructor("ZodVoid", (inst, def) => { $ZodVoid.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => voidProcessor(inst, ctx, json, params); }); function schemas_void(params) { return _void(schemas_ZodVoid, params); @@ -80775,6 +80997,7 @@ function schemas_void(params) { const schemas_ZodDate = /*@__PURE__*/ $constructor("ZodDate", (inst, def) => { $ZodDate.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => dateProcessor(inst, ctx, json, params); inst.min = (value, params) => inst.check(_gte(value, params)); inst.max = (value, params) => inst.check(_lte(value, params)); const c = inst._zod.bag; @@ -80787,6 +81010,7 @@ function schemas_date(params) { const schemas_ZodArray = /*@__PURE__*/ $constructor("ZodArray", (inst, def) => { $ZodArray.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => arrayProcessor(inst, ctx, json, params); inst.element = def.element; inst.min = (minLength, params) => inst.check(_minLength(minLength, params)); inst.nonempty = (params) => inst.check(_minLength(1, params)); @@ -80805,6 +81029,7 @@ function keyof(schema) { const schemas_ZodObject = /*@__PURE__*/ $constructor("ZodObject", (inst, def) => { $ZodObjectJIT.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => objectProcessor(inst, ctx, json, params); defineLazy(inst, "shape", () => { return def.shape; }); @@ -80855,6 +81080,7 @@ function looseObject(shape, params) { const schemas_ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => { $ZodUnion.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => unionProcessor(inst, ctx, json, params); inst.options = def.options; }); function union(options, params) { @@ -80864,6 +81090,23 @@ function union(options, params) { ...normalizeParams(params), }); } +const ZodXor = /*@__PURE__*/ $constructor("ZodXor", (inst, def) => { + schemas_ZodUnion.init(inst, def); + $ZodXor.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => unionProcessor(inst, ctx, json, params); + inst.options = def.options; +}); +/** Creates an exclusive union (XOR) where exactly one option must match. + * Unlike regular unions that succeed when any option matches, xor fails if + * zero or more than one option matches the input. */ +function xor(options, params) { + return new ZodXor({ + type: "union", + options: options, + inclusive: false, + ...normalizeParams(params), + }); +} const schemas_ZodDiscriminatedUnion = /*@__PURE__*/ $constructor("ZodDiscriminatedUnion", (inst, def) => { schemas_ZodUnion.init(inst, def); $ZodDiscriminatedUnion.init(inst, def); @@ -80880,6 +81123,7 @@ function discriminatedUnion(discriminator, options, params) { const schemas_ZodIntersection = /*@__PURE__*/ $constructor("ZodIntersection", (inst, def) => { $ZodIntersection.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => intersectionProcessor(inst, ctx, json, params); }); function intersection(left, right) { return new schemas_ZodIntersection({ @@ -80891,6 +81135,7 @@ function intersection(left, right) { const schemas_ZodTuple = /*@__PURE__*/ $constructor("ZodTuple", (inst, def) => { $ZodTuple.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => tupleProcessor(inst, ctx, json, params); inst.rest = (rest) => inst.clone({ ...inst._zod.def, rest: rest, @@ -80910,6 +81155,7 @@ function tuple(items, _paramsOrRest, _params) { const schemas_ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => { $ZodRecord.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params); inst.keyType = def.keyType; inst.valueType = def.valueType; }); @@ -80932,9 +81178,19 @@ function partialRecord(keyType, valueType, params) { ...normalizeParams(params), }); } +function looseRecord(keyType, valueType, params) { + return new schemas_ZodRecord({ + type: "record", + keyType, + valueType: valueType, + mode: "loose", + ...normalizeParams(params), + }); +} const schemas_ZodMap = /*@__PURE__*/ $constructor("ZodMap", (inst, def) => { $ZodMap.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => mapProcessor(inst, ctx, json, params); inst.keyType = def.keyType; inst.valueType = def.valueType; }); @@ -80949,6 +81205,7 @@ function map(keyType, valueType, params) { const schemas_ZodSet = /*@__PURE__*/ $constructor("ZodSet", (inst, def) => { $ZodSet.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => setProcessor(inst, ctx, json, params); inst.min = (...args) => inst.check(_minSize(...args)); inst.nonempty = (params) => inst.check(_minSize(1, params)); inst.max = (...args) => inst.check(_maxSize(...args)); @@ -80964,6 +81221,7 @@ function set(valueType, params) { const schemas_ZodEnum = /*@__PURE__*/ $constructor("ZodEnum", (inst, def) => { $ZodEnum.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => enumProcessor(inst, ctx, json, params); inst.enum = def.entries; inst.options = Object.values(def.entries); const keys = new Set(Object.keys(def.entries)); @@ -81026,6 +81284,7 @@ function nativeEnum(entries, params) { const schemas_ZodLiteral = /*@__PURE__*/ $constructor("ZodLiteral", (inst, def) => { $ZodLiteral.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params); inst.values = new Set(def.values); Object.defineProperty(inst, "value", { get() { @@ -81046,6 +81305,7 @@ function literal(value, params) { const ZodFile = /*@__PURE__*/ $constructor("ZodFile", (inst, def) => { $ZodFile.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => fileProcessor(inst, ctx, json, params); inst.min = (size, params) => inst.check(_minSize(size, params)); inst.max = (size, params) => inst.check(_maxSize(size, params)); inst.mime = (types, params) => inst.check(_mime(Array.isArray(types) ? types : [types], params)); @@ -81056,6 +81316,7 @@ function file(params) { const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => { $ZodTransform.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => transformProcessor(inst, ctx, json, params); inst._zod.parse = (payload, _ctx) => { if (_ctx.direction === "backward") { throw new $ZodEncodeError(inst.constructor.name); @@ -81096,6 +81357,7 @@ function transform(fn) { const schemas_ZodOptional = /*@__PURE__*/ $constructor("ZodOptional", (inst, def) => { $ZodOptional.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => optionalProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function optional(innerType) { @@ -81107,6 +81369,7 @@ function optional(innerType) { const schemas_ZodNullable = /*@__PURE__*/ $constructor("ZodNullable", (inst, def) => { $ZodNullable.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => nullableProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function nullable(innerType) { @@ -81122,6 +81385,7 @@ function schemas_nullish(innerType) { const schemas_ZodDefault = /*@__PURE__*/ $constructor("ZodDefault", (inst, def) => { $ZodDefault.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => defaultProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; inst.removeDefault = inst.unwrap; }); @@ -81137,6 +81401,7 @@ function schemas_default(innerType, defaultValue) { const ZodPrefault = /*@__PURE__*/ $constructor("ZodPrefault", (inst, def) => { $ZodPrefault.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => prefaultProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function prefault(innerType, defaultValue) { @@ -81151,6 +81416,7 @@ function prefault(innerType, defaultValue) { const ZodNonOptional = /*@__PURE__*/ $constructor("ZodNonOptional", (inst, def) => { $ZodNonOptional.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => nonoptionalProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function nonoptional(innerType, params) { @@ -81163,6 +81429,7 @@ function nonoptional(innerType, params) { const ZodSuccess = /*@__PURE__*/ $constructor("ZodSuccess", (inst, def) => { $ZodSuccess.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => successProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function success(innerType) { @@ -81174,6 +81441,7 @@ function success(innerType) { const schemas_ZodCatch = /*@__PURE__*/ $constructor("ZodCatch", (inst, def) => { $ZodCatch.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => catchProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; inst.removeCatch = inst.unwrap; }); @@ -81188,6 +81456,7 @@ function schemas_catch(innerType, catchValue) { const schemas_ZodNaN = /*@__PURE__*/ $constructor("ZodNaN", (inst, def) => { $ZodNaN.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => nanProcessor(inst, ctx, json, params); }); function nan(params) { return _nan(schemas_ZodNaN, params); @@ -81195,6 +81464,7 @@ function nan(params) { const ZodPipe = /*@__PURE__*/ $constructor("ZodPipe", (inst, def) => { $ZodPipe.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => pipeProcessor(inst, ctx, json, params); inst.in = def.in; inst.out = def.out; }); @@ -81222,6 +81492,7 @@ function codec(in_, out, params) { const schemas_ZodReadonly = /*@__PURE__*/ $constructor("ZodReadonly", (inst, def) => { $ZodReadonly.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => readonlyProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function readonly(innerType) { @@ -81233,6 +81504,7 @@ function readonly(innerType) { const ZodTemplateLiteral = /*@__PURE__*/ $constructor("ZodTemplateLiteral", (inst, def) => { $ZodTemplateLiteral.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => templateLiteralProcessor(inst, ctx, json, params); }); function templateLiteral(parts, params) { return new ZodTemplateLiteral({ @@ -81244,6 +81516,7 @@ function templateLiteral(parts, params) { const schemas_ZodLazy = /*@__PURE__*/ $constructor("ZodLazy", (inst, def) => { $ZodLazy.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => lazyProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.getter(); }); function lazy(getter) { @@ -81255,6 +81528,7 @@ function lazy(getter) { const schemas_ZodPromise = /*@__PURE__*/ $constructor("ZodPromise", (inst, def) => { $ZodPromise.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => promiseProcessor(inst, ctx, json, params); inst.unwrap = () => inst._zod.def.innerType; }); function promise(innerType) { @@ -81266,6 +81540,7 @@ function promise(innerType) { const schemas_ZodFunction = /*@__PURE__*/ $constructor("ZodFunction", (inst, def) => { $ZodFunction.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => functionProcessor(inst, ctx, json, params); }); function _function(params) { return new schemas_ZodFunction({ @@ -81278,6 +81553,7 @@ function _function(params) { const ZodCustom = /*@__PURE__*/ $constructor("ZodCustom", (inst, def) => { $ZodCustom.init(inst, def); schemas_ZodType.init(inst, def); + inst._zod.processJSONSchema = (ctx, json, params) => customProcessor(inst, ctx, json, params); }); // custom checks function check(fn) { @@ -81366,6 +81642,493 @@ var compat_ZodFirstPartyTypeKind; (function (ZodFirstPartyTypeKind) { })(compat_ZodFirstPartyTypeKind || (compat_ZodFirstPartyTypeKind = {})); +;// CONCATENATED MODULE: ./node_modules/zod/v4/classic/from-json-schema.js + + + +// Local z object to avoid circular dependency with ../index.js +const from_json_schema_z = { + ...classic_schemas_namespaceObject, + ...classic_checks_namespaceObject, + iso: iso_namespaceObject, +}; +function detectVersion(schema, defaultTarget) { + const $schema = schema.$schema; + if ($schema === "https://json-schema.org/draft/2020-12/schema") { + return "draft-2020-12"; + } + if ($schema === "http://json-schema.org/draft-07/schema#") { + return "draft-7"; + } + if ($schema === "http://json-schema.org/draft-04/schema#") { + return "draft-4"; + } + // Use defaultTarget if provided, otherwise default to draft-2020-12 + return defaultTarget ?? "draft-2020-12"; +} +function resolveRef(ref, ctx) { + if (!ref.startsWith("#")) { + throw new Error("External $ref is not supported, only local refs (#/...) are allowed"); + } + const path = ref.slice(1).split("/").filter(Boolean); + // Handle root reference "#" + if (path.length === 0) { + return ctx.rootSchema; + } + const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions"; + if (path[0] === defsKey) { + const key = path[1]; + if (!key || !ctx.defs[key]) { + throw new Error(`Reference not found: ${ref}`); + } + return ctx.defs[key]; + } + throw new Error(`Reference not found: ${ref}`); +} +function convertBaseSchema(schema, ctx) { + // Handle unsupported features + if (schema.not !== undefined) { + // Special case: { not: {} } represents never + if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) { + return from_json_schema_z.never(); + } + throw new Error("not is not supported in Zod (except { not: {} } for never)"); + } + if (schema.unevaluatedItems !== undefined) { + throw new Error("unevaluatedItems is not supported"); + } + if (schema.unevaluatedProperties !== undefined) { + throw new Error("unevaluatedProperties is not supported"); + } + if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) { + throw new Error("Conditional schemas (if/then/else) are not supported"); + } + if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) { + throw new Error("dependentSchemas and dependentRequired are not supported"); + } + // Handle $ref + if (schema.$ref) { + const refPath = schema.$ref; + if (ctx.refs.has(refPath)) { + return ctx.refs.get(refPath); + } + if (ctx.processing.has(refPath)) { + // Circular reference - use lazy + return from_json_schema_z.lazy(() => { + if (!ctx.refs.has(refPath)) { + throw new Error(`Circular reference not resolved: ${refPath}`); + } + return ctx.refs.get(refPath); + }); + } + ctx.processing.add(refPath); + const resolved = resolveRef(refPath, ctx); + const zodSchema = convertSchema(resolved, ctx); + ctx.refs.set(refPath, zodSchema); + ctx.processing.delete(refPath); + return zodSchema; + } + // Handle enum + if (schema.enum !== undefined) { + const enumValues = schema.enum; + // Special case: OpenAPI 3.0 null representation { type: "string", nullable: true, enum: [null] } + if (ctx.version === "openapi-3.0" && + schema.nullable === true && + enumValues.length === 1 && + enumValues[0] === null) { + return from_json_schema_z.null(); + } + if (enumValues.length === 0) { + return from_json_schema_z.never(); + } + if (enumValues.length === 1) { + return from_json_schema_z.literal(enumValues[0]); + } + // Check if all values are strings + if (enumValues.every((v) => typeof v === "string")) { + return from_json_schema_z.enum(enumValues); + } + // Mixed types - use union of literals + const literalSchemas = enumValues.map((v) => from_json_schema_z.literal(v)); + if (literalSchemas.length < 2) { + return literalSchemas[0]; + } + return from_json_schema_z.union([literalSchemas[0], literalSchemas[1], ...literalSchemas.slice(2)]); + } + // Handle const + if (schema.const !== undefined) { + return from_json_schema_z.literal(schema.const); + } + // Handle type + const type = schema.type; + if (Array.isArray(type)) { + // Expand type array into anyOf union + const typeSchemas = type.map((t) => { + const typeSchema = { ...schema, type: t }; + return convertBaseSchema(typeSchema, ctx); + }); + if (typeSchemas.length === 0) { + return from_json_schema_z.never(); + } + if (typeSchemas.length === 1) { + return typeSchemas[0]; + } + return from_json_schema_z.union(typeSchemas); + } + if (!type) { + // No type specified - empty schema (any) + return from_json_schema_z.any(); + } + let zodSchema; + switch (type) { + case "string": { + let stringSchema = from_json_schema_z.string(); + // Apply format using .check() with Zod format functions + if (schema.format) { + const format = schema.format; + // Map common formats to Zod check functions + if (format === "email") { + stringSchema = stringSchema.check(from_json_schema_z.email()); + } + else if (format === "uri" || format === "uri-reference") { + stringSchema = stringSchema.check(from_json_schema_z.url()); + } + else if (format === "uuid" || format === "guid") { + stringSchema = stringSchema.check(from_json_schema_z.uuid()); + } + else if (format === "date-time") { + stringSchema = stringSchema.check(from_json_schema_z.iso.datetime()); + } + else if (format === "date") { + stringSchema = stringSchema.check(from_json_schema_z.iso.date()); + } + else if (format === "time") { + stringSchema = stringSchema.check(from_json_schema_z.iso.time()); + } + else if (format === "duration") { + stringSchema = stringSchema.check(from_json_schema_z.iso.duration()); + } + else if (format === "ipv4") { + stringSchema = stringSchema.check(from_json_schema_z.ipv4()); + } + else if (format === "ipv6") { + stringSchema = stringSchema.check(from_json_schema_z.ipv6()); + } + else if (format === "mac") { + stringSchema = stringSchema.check(from_json_schema_z.mac()); + } + else if (format === "cidr") { + stringSchema = stringSchema.check(from_json_schema_z.cidrv4()); + } + else if (format === "cidr-v6") { + stringSchema = stringSchema.check(from_json_schema_z.cidrv6()); + } + else if (format === "base64") { + stringSchema = stringSchema.check(from_json_schema_z.base64()); + } + else if (format === "base64url") { + stringSchema = stringSchema.check(from_json_schema_z.base64url()); + } + else if (format === "e164") { + stringSchema = stringSchema.check(from_json_schema_z.e164()); + } + else if (format === "jwt") { + stringSchema = stringSchema.check(from_json_schema_z.jwt()); + } + else if (format === "emoji") { + stringSchema = stringSchema.check(from_json_schema_z.emoji()); + } + else if (format === "nanoid") { + stringSchema = stringSchema.check(from_json_schema_z.nanoid()); + } + else if (format === "cuid") { + stringSchema = stringSchema.check(from_json_schema_z.cuid()); + } + else if (format === "cuid2") { + stringSchema = stringSchema.check(from_json_schema_z.cuid2()); + } + else if (format === "ulid") { + stringSchema = stringSchema.check(from_json_schema_z.ulid()); + } + else if (format === "xid") { + stringSchema = stringSchema.check(from_json_schema_z.xid()); + } + else if (format === "ksuid") { + stringSchema = stringSchema.check(from_json_schema_z.ksuid()); + } + // Note: json-string format is not currently supported by Zod + // Custom formats are ignored - keep as plain string + } + // Apply constraints + if (typeof schema.minLength === "number") { + stringSchema = stringSchema.min(schema.minLength); + } + if (typeof schema.maxLength === "number") { + stringSchema = stringSchema.max(schema.maxLength); + } + if (schema.pattern) { + // JSON Schema patterns are not implicitly anchored (match anywhere in string) + stringSchema = stringSchema.regex(new RegExp(schema.pattern)); + } + zodSchema = stringSchema; + break; + } + case "number": + case "integer": { + let numberSchema = type === "integer" ? from_json_schema_z.number().int() : from_json_schema_z.number(); + // Apply constraints + if (typeof schema.minimum === "number") { + numberSchema = numberSchema.min(schema.minimum); + } + if (typeof schema.maximum === "number") { + numberSchema = numberSchema.max(schema.maximum); + } + if (typeof schema.exclusiveMinimum === "number") { + numberSchema = numberSchema.gt(schema.exclusiveMinimum); + } + else if (schema.exclusiveMinimum === true && typeof schema.minimum === "number") { + numberSchema = numberSchema.gt(schema.minimum); + } + if (typeof schema.exclusiveMaximum === "number") { + numberSchema = numberSchema.lt(schema.exclusiveMaximum); + } + else if (schema.exclusiveMaximum === true && typeof schema.maximum === "number") { + numberSchema = numberSchema.lt(schema.maximum); + } + if (typeof schema.multipleOf === "number") { + numberSchema = numberSchema.multipleOf(schema.multipleOf); + } + zodSchema = numberSchema; + break; + } + case "boolean": { + zodSchema = from_json_schema_z.boolean(); + break; + } + case "null": { + zodSchema = from_json_schema_z.null(); + break; + } + case "object": { + const shape = {}; + const properties = schema.properties || {}; + const requiredSet = new Set(schema.required || []); + // Convert properties - mark optional ones + for (const [key, propSchema] of Object.entries(properties)) { + const propZodSchema = convertSchema(propSchema, ctx); + // If not in required array, make it optional + shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional(); + } + // Handle propertyNames + if (schema.propertyNames) { + const keySchema = convertSchema(schema.propertyNames, ctx); + const valueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object" + ? convertSchema(schema.additionalProperties, ctx) + : from_json_schema_z.any(); + // Case A: No properties (pure record) + if (Object.keys(shape).length === 0) { + zodSchema = from_json_schema_z.record(keySchema, valueSchema); + break; + } + // Case B: With properties (intersection of object and looseRecord) + const objectSchema = from_json_schema_z.object(shape).passthrough(); + const recordSchema = from_json_schema_z.looseRecord(keySchema, valueSchema); + zodSchema = from_json_schema_z.intersection(objectSchema, recordSchema); + break; + } + // Handle patternProperties + if (schema.patternProperties) { + // patternProperties: keys matching pattern must satisfy corresponding schema + // Use loose records so non-matching keys pass through + const patternProps = schema.patternProperties; + const patternKeys = Object.keys(patternProps); + const looseRecords = []; + for (const pattern of patternKeys) { + const patternValue = convertSchema(patternProps[pattern], ctx); + const keySchema = from_json_schema_z.string().regex(new RegExp(pattern)); + looseRecords.push(from_json_schema_z.looseRecord(keySchema, patternValue)); + } + // Build intersection: object schema + all pattern property records + const schemasToIntersect = []; + if (Object.keys(shape).length > 0) { + // Use passthrough so patternProperties can validate additional keys + schemasToIntersect.push(from_json_schema_z.object(shape).passthrough()); + } + schemasToIntersect.push(...looseRecords); + if (schemasToIntersect.length === 0) { + zodSchema = from_json_schema_z.object({}).passthrough(); + } + else if (schemasToIntersect.length === 1) { + zodSchema = schemasToIntersect[0]; + } + else { + // Chain intersections: (A & B) & C & D ... + let result = from_json_schema_z.intersection(schemasToIntersect[0], schemasToIntersect[1]); + for (let i = 2; i < schemasToIntersect.length; i++) { + result = from_json_schema_z.intersection(result, schemasToIntersect[i]); + } + zodSchema = result; + } + break; + } + // Handle additionalProperties + // In JSON Schema, additionalProperties defaults to true (allow any extra properties) + // In Zod, objects strip unknown keys by default, so we need to handle this explicitly + const objectSchema = from_json_schema_z.object(shape); + if (schema.additionalProperties === false) { + // Strict mode - no extra properties allowed + zodSchema = objectSchema.strict(); + } + else if (typeof schema.additionalProperties === "object") { + // Extra properties must match the specified schema + zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx)); + } + else { + // additionalProperties is true or undefined - allow any extra properties (passthrough) + zodSchema = objectSchema.passthrough(); + } + break; + } + case "array": { + // TODO: uniqueItems is not supported + // TODO: contains/minContains/maxContains are not supported + // Check if this is a tuple (prefixItems or items as array) + const prefixItems = schema.prefixItems; + const items = schema.items; + if (prefixItems && Array.isArray(prefixItems)) { + // Tuple with prefixItems (draft-2020-12) + const tupleItems = prefixItems.map((item) => convertSchema(item, ctx)); + const rest = items && typeof items === "object" && !Array.isArray(items) + ? convertSchema(items, ctx) + : undefined; + if (rest) { + zodSchema = from_json_schema_z.tuple(tupleItems).rest(rest); + } + else { + zodSchema = from_json_schema_z.tuple(tupleItems); + } + // Apply minItems/maxItems constraints to tuples + if (typeof schema.minItems === "number") { + zodSchema = zodSchema.check(from_json_schema_z.minLength(schema.minItems)); + } + if (typeof schema.maxItems === "number") { + zodSchema = zodSchema.check(from_json_schema_z.maxLength(schema.maxItems)); + } + } + else if (Array.isArray(items)) { + // Tuple with items array (draft-7) + const tupleItems = items.map((item) => convertSchema(item, ctx)); + const rest = schema.additionalItems && typeof schema.additionalItems === "object" + ? convertSchema(schema.additionalItems, ctx) + : undefined; // additionalItems: false means no rest, handled by default tuple behavior + if (rest) { + zodSchema = from_json_schema_z.tuple(tupleItems).rest(rest); + } + else { + zodSchema = from_json_schema_z.tuple(tupleItems); + } + // Apply minItems/maxItems constraints to tuples + if (typeof schema.minItems === "number") { + zodSchema = zodSchema.check(from_json_schema_z.minLength(schema.minItems)); + } + if (typeof schema.maxItems === "number") { + zodSchema = zodSchema.check(from_json_schema_z.maxLength(schema.maxItems)); + } + } + else if (items !== undefined) { + // Regular array + const element = convertSchema(items, ctx); + let arraySchema = from_json_schema_z.array(element); + // Apply constraints + if (typeof schema.minItems === "number") { + arraySchema = arraySchema.min(schema.minItems); + } + if (typeof schema.maxItems === "number") { + arraySchema = arraySchema.max(schema.maxItems); + } + zodSchema = arraySchema; + } + else { + // No items specified - array of any + zodSchema = from_json_schema_z.array(from_json_schema_z.any()); + } + break; + } + default: + throw new Error(`Unsupported type: ${type}`); + } + // Apply metadata + if (schema.description) { + zodSchema = zodSchema.describe(schema.description); + } + if (schema.default !== undefined) { + zodSchema = zodSchema.default(schema.default); + } + return zodSchema; +} +function convertSchema(schema, ctx) { + if (typeof schema === "boolean") { + return schema ? from_json_schema_z.any() : from_json_schema_z.never(); + } + // Convert base schema first (ignoring composition keywords) + let baseSchema = convertBaseSchema(schema, ctx); + const hasExplicitType = schema.type || schema.enum !== undefined || schema.const !== undefined; + // Process composition keywords LAST (they can appear together) + // Handle anyOf - wrap base schema with union + if (schema.anyOf && Array.isArray(schema.anyOf)) { + const options = schema.anyOf.map((s) => convertSchema(s, ctx)); + const anyOfUnion = from_json_schema_z.union(options); + baseSchema = hasExplicitType ? from_json_schema_z.intersection(baseSchema, anyOfUnion) : anyOfUnion; + } + // Handle oneOf - exclusive union (exactly one must match) + if (schema.oneOf && Array.isArray(schema.oneOf)) { + const options = schema.oneOf.map((s) => convertSchema(s, ctx)); + const oneOfUnion = from_json_schema_z.xor(options); + baseSchema = hasExplicitType ? from_json_schema_z.intersection(baseSchema, oneOfUnion) : oneOfUnion; + } + // Handle allOf - wrap base schema with intersection + if (schema.allOf && Array.isArray(schema.allOf)) { + if (schema.allOf.length === 0) { + baseSchema = hasExplicitType ? baseSchema : from_json_schema_z.any(); + } + else { + let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx); + const startIdx = hasExplicitType ? 0 : 1; + for (let i = startIdx; i < schema.allOf.length; i++) { + result = from_json_schema_z.intersection(result, convertSchema(schema.allOf[i], ctx)); + } + baseSchema = result; + } + } + // Handle nullable (OpenAPI 3.0) + if (schema.nullable === true && ctx.version === "openapi-3.0") { + baseSchema = from_json_schema_z.nullable(baseSchema); + } + // Handle readOnly + if (schema.readOnly === true) { + baseSchema = from_json_schema_z.readonly(baseSchema); + } + return baseSchema; +} +/** + * Converts a JSON Schema to a Zod schema. This function should be considered semi-experimental. It's behavior is liable to change. */ +function fromJSONSchema(schema, params) { + // Handle boolean schemas + if (typeof schema === "boolean") { + return schema ? from_json_schema_z.any() : from_json_schema_z.never(); + } + const version = detectVersion(schema, params?.defaultTarget); + const defs = (schema.$defs || schema.definitions || {}); + const ctx = { + version, + defs, + refs: new Map(), + processing: new Set(), + rootSchema: schema, + }; + return convertSchema(schema, ctx); +} + ;// CONCATENATED MODULE: ./node_modules/zod/v4/classic/coerce.js @@ -81398,6 +82161,8 @@ function coerce_date(params) { config(en()); + + // iso // must be exported from top-level // https://github.com/colinhacks/zod/issues/4491 @@ -81452,6 +82217,13 @@ __export(tools_exports, { * Base class for Tools that accept input of any shape defined by a Zod schema. */ var StructuredTool = class extends BaseLangChain { + /** + * Optional provider-specific extra fields for the tool. + * + * This is used to pass provider-specific configuration that doesn't fit into + * standard tool fields. + */ + extras; /** * Whether to return the tool's output directly. * @@ -81483,6 +82255,7 @@ var StructuredTool = class extends BaseLangChain { this.responseFormat = fields?.responseFormat ?? this.responseFormat; this.defaultConfig = fields?.defaultConfig ?? this.defaultConfig; this.metadata = fields?.metadata ?? this.metadata; + this.extras = fields?.extras ?? this.extras; } /** * Invokes the tool with the provided input and configuration. @@ -81860,7 +82633,7 @@ var FakeStreamingChatModel = class FakeStreamingChatModel extends BaseChatModel }] }; return generation; } - async *_streamResponseChunks(_messages, _options, runManager) { + async *_streamResponseChunks(_messages, options, runManager) { if (this.thrownErrorString) throw new Error(this.thrownErrorString); if (this.chunks?.length) { for (const msgChunk of this.chunks) { @@ -81872,6 +82645,7 @@ var FakeStreamingChatModel = class FakeStreamingChatModel extends BaseChatModel }), text: msgChunk.content?.toString() ?? "" }); + if (options.signal?.aborted) break; yield cg; await runManager?.handleLLMNewToken(msgChunk.content, void 0, void 0, void 0, void 0, { chunk: cg }); } @@ -81885,6 +82659,7 @@ var FakeStreamingChatModel = class FakeStreamingChatModel extends BaseChatModel message: new AIMessageChunk({ content: ch }), text: ch }); + if (options.signal?.aborted) break; yield cg; await runManager?.handleLLMNewToken(ch, void 0, void 0, void 0, void 0, { chunk: cg }); } @@ -81910,7 +82685,7 @@ var FakeStreamingChatModel = class FakeStreamingChatModel extends BaseChatModel * console.log({ secondResponse }); * ``` */ -var FakeListChatModel = class extends BaseChatModel { +var FakeListChatModel = class FakeListChatModel extends BaseChatModel { static lc_name() { return "FakeListChatModel"; } @@ -81919,12 +82694,16 @@ var FakeListChatModel = class extends BaseChatModel { i = 0; sleep; emitCustomEvent = false; + generationInfo; + tools = []; + toolStyle = "openai"; constructor(params) { super(params); - const { responses, sleep, emitCustomEvent } = params; + const { responses, sleep, emitCustomEvent, generationInfo } = params; this.responses = responses; this.sleep = sleep; this.emitCustomEvent = emitCustomEvent ?? this.emitCustomEvent; + this.generationInfo = generationInfo; } _combineLLMOutput() { return []; @@ -81956,10 +82735,14 @@ var FakeListChatModel = class extends BaseChatModel { const response = this._currentResponse(); this._incrementResponse(); if (this.emitCustomEvent) await runManager?.handleCustomEvent("some_test_event", { someval: true }); - for await (const text of response) { + const responseChars = [...response]; + for (let i = 0; i < responseChars.length; i++) { + const text = responseChars[i]; + const isLastChunk = i === responseChars.length - 1; await this._sleepIfRequested(); if (options?.thrownErrorString) throw new Error(options.thrownErrorString); - const chunk = this._createResponseChunk(text); + const chunk = this._createResponseChunk(text, isLastChunk ? this.generationInfo : void 0); + if (options.signal?.aborted) break; yield chunk; runManager?.handleLLMNewToken(text); } @@ -81972,10 +82755,11 @@ var FakeListChatModel = class extends BaseChatModel { setTimeout(() => resolve(), this.sleep); }); } - _createResponseChunk(text) { + _createResponseChunk(text, generationInfo) { return new ChatGenerationChunk({ message: new AIMessageChunk({ content: text }), - text + text, + generationInfo }); } _currentResponse() { @@ -81985,6 +82769,48 @@ var FakeListChatModel = class extends BaseChatModel { if (this.i < this.responses.length - 1) this.i += 1; else this.i = 0; } + bindTools(tools) { + const merged = [...this.tools, ...tools]; + const toolDicts = merged.map((t) => { + switch (this.toolStyle) { + case "openai": return { + type: "function", + function: { + name: t.name, + description: t.description, + parameters: toJsonSchema(t.schema) + } + }; + case "anthropic": return { + name: t.name, + description: t.description, + input_schema: toJsonSchema(t.schema) + }; + case "bedrock": return { toolSpec: { + name: t.name, + description: t.description, + inputSchema: toJsonSchema(t.schema) + } }; + case "google": return { + name: t.name, + description: t.description, + parameters: toJsonSchema(t.schema) + }; + default: throw new Error(`Unsupported tool style: ${this.toolStyle}`); + } + }); + const wrapped = this.toolStyle === "google" ? [{ functionDeclarations: toolDicts }] : toolDicts; + const next = new FakeListChatModel({ + responses: this.responses, + sleep: this.sleep, + emitCustomEvent: this.emitCustomEvent, + generationInfo: this.generationInfo + }); + next.tools = merged; + next.toolStyle = this.toolStyle; + next.i = this.i; + return next.withConfig({ tools: wrapped }); + } withStructuredOutput(_params, _config) { return RunnableLambda.from(async (input) => { const message = await this.invoke(input); @@ -82541,8 +83367,10 @@ __export(types_exports, { isZodArrayV4: () => isZodArrayV4, isZodLiteralV3: () => isZodLiteralV3, isZodLiteralV4: () => isZodLiteralV4, + isZodNullableV4: () => isZodNullableV4, isZodObjectV3: () => isZodObjectV3, isZodObjectV4: () => isZodObjectV4, + isZodOptionalV4: () => isZodOptionalV4, isZodSchema: () => isZodSchema, isZodSchemaV3: () => isZodSchemaV3, isZodSchemaV4: () => isZodSchemaV4 @@ -84729,6 +85557,7 @@ function matrixMaxVal(arrays) { + //#region src/load/import_map.ts @@ -84777,6 +85606,7 @@ __export(import_map_exports, { types__stream: () => stream_stream_exports, utils__async_caller: () => async_caller_exports, utils__chunk_array: () => chunk_array_exports, + utils__context: () => context_exports, utils__env: () => env_exports, utils__event_source_parse: () => event_source_parse_exports, utils__format: () => format_exports, @@ -84802,7 +85632,13 @@ __export(import_map_exports, { + //#region src/load/index.ts +/** +* Default maximum recursion depth for deserialization. +* This provides protection against DoS attacks via deeply nested structures. +*/ +const DEFAULT_MAX_DEPTH = 50; function combineAliasesAndInvert(constructor) { const aliases = {}; for (let current = constructor; current && current.prototype; current = Object.getPrototypeOf(current)) Object.assign(aliases, Reflect.get(current.prototype, "lc_aliases")); @@ -84811,24 +85647,44 @@ function combineAliasesAndInvert(constructor) { return acc; }, {}); } +/** +* Recursively revive a value, handling escape markers and LC objects. +* +* This function handles: +* 1. Escaped dicts - unwrapped and returned as plain objects +* 2. LC secret objects - resolved from secretsMap or env +* 3. LC constructor objects - instantiated +* 4. Regular objects/arrays - recursed into +*/ async function reviver(value) { - const { optionalImportsMap = {}, optionalImportEntrypoints: optionalImportEntrypoints$1 = [], importMap = {}, secretsMap = {}, path = ["$"] } = this; + const { optionalImportsMap, optionalImportEntrypoints: optionalImportEntrypoints$1, importMap, secretsMap, secretsFromEnv, path, depth, maxDepth } = this; const pathStr = path.join("."); - if (typeof value === "object" && value !== null && !Array.isArray(value) && "lc" in value && "type" in value && "id" in value && value.lc === 1 && value.type === "secret") { - const serialized = value; + if (depth > maxDepth) throw new Error(`Maximum recursion depth (${maxDepth}) exceeded during deserialization. This may indicate a malicious payload or you may need to increase maxDepth.`); + if (typeof value !== "object" || value == null) return value; + if (Array.isArray(value)) return Promise.all(value.map((v, i) => reviver.call({ + ...this, + path: [...path, `${i}`], + depth: depth + 1 + }, v))); + const record = value; + if (isEscapedObject(record)) return unescapeValue(record); + if ("lc" in record && "type" in record && "id" in record && record.lc === 1 && record.type === "secret") { + const serialized = record; const [key] = serialized.id; if (key in secretsMap) return secretsMap[key]; - else { + else if (secretsFromEnv) { const secretValueInEnv = getEnvironmentVariable(key); if (secretValueInEnv) return secretValueInEnv; - else throw new Error(`Missing key "${key}" for ${pathStr} in load(secretsMap={})`); } - } else if (typeof value === "object" && value !== null && !Array.isArray(value) && "lc" in value && "type" in value && "id" in value && value.lc === 1 && value.type === "not_implemented") { - const serialized = value; + throw new Error(`Missing secret "${key}" at ${pathStr}`); + } + if ("lc" in record && "type" in record && "id" in record && record.lc === 1 && record.type === "not_implemented") { + const serialized = record; const str = JSON.stringify(serialized); throw new Error(`Trying to load an object that doesn't implement serialization: ${pathStr} -> ${str}`); - } else if (typeof value === "object" && value !== null && !Array.isArray(value) && "lc" in value && "type" in value && "id" in value && "kwargs" in value && value.lc === 1) { - const serialized = value; + } + if ("lc" in record && "type" in record && "id" in record && "kwargs" in record && record.lc === 1 && record.type === "constructor") { + const serialized = record; const str = JSON.stringify(serialized); const [name, ...namespaceReverse] = serialized.id.slice().reverse(); const namespace = namespaceReverse.reverse(); @@ -84862,26 +85718,60 @@ async function reviver(value) { if (typeof builder !== "function") throw new Error(`Invalid identifer: ${pathStr} -> ${str}`); const kwargs = await reviver.call({ ...this, - path: [...path, "kwargs"] + path: [...path, "kwargs"], + depth: depth + 1 }, serialized.kwargs); - if (serialized.type === "constructor") { - const instance = new builder(mapKeys(kwargs, keyFromJson, combineAliasesAndInvert(builder))); - Object.defineProperty(instance.constructor, "name", { value: name }); - return instance; - } else throw new Error(`Invalid type: ${pathStr} -> ${str}`); - } else if (typeof value === "object" && value !== null) if (Array.isArray(value)) return Promise.all(value.map((v, i) => reviver.call({ - ...this, - path: [...path, `${i}`] - }, v))); - else return Object.fromEntries(await Promise.all(Object.entries(value).map(async ([key, value$1]) => [key, await reviver.call({ + const instance = new builder(mapKeys(kwargs, keyFromJson, combineAliasesAndInvert(builder))); + Object.defineProperty(instance.constructor, "name", { value: name }); + return instance; + } + const result = {}; + for (const [key, val] of Object.entries(record)) result[key] = await reviver.call({ ...this, - path: [...path, key] - }, value$1)]))); - return value; + path: [...path, key], + depth: depth + 1 + }, val); + return result; } -async function load(text, mappings) { +/** +* Load a LangChain object from a JSON string. +* +* @param text - The JSON string to parse and load. +* @param options - Options for loading. +* @returns The loaded LangChain object. +* +* @example +* ```typescript +* import { load } from "@langchain/core/load"; +* import { AIMessage } from "@langchain/core/messages"; +* +* // Basic usage - secrets must be provided explicitly +* const msg = await load(jsonString); +* +* // With secrets from a map +* const msg = await load(jsonString, { +* secretsMap: { OPENAI_API_KEY: "sk-..." } +* }); +* +* // Allow loading secrets from environment (use with caution) +* const msg = await load(jsonString, { +* secretsFromEnv: true +* }); +* ``` +*/ +async function load(text, options) { const json = JSON.parse(text); - return reviver.call({ ...mappings }, json); + const context = { + optionalImportsMap: options?.optionalImportsMap ?? {}, + optionalImportEntrypoints: options?.optionalImportEntrypoints ?? [], + secretsMap: options?.secretsMap ?? {}, + secretsFromEnv: options?.secretsFromEnv ?? false, + importMap: options?.importMap ?? {}, + path: ["$"], + depth: 0, + maxDepth: options?.maxDepth ?? DEFAULT_MAX_DEPTH + }; + return reviver.call(context, json); } //#endregion @@ -86274,8 +87164,13 @@ var BinaryOperatorAggregate = class BinaryOperatorAggregate extends BaseChannel var LastValue = class LastValue extends BaseChannel { lc_graph_name = "LastValue"; value = []; + constructor(initialValueFactory) { + super(); + this.initialValueFactory = initialValueFactory; + if (initialValueFactory) this.value = [initialValueFactory()]; + } fromCheckpoint(checkpoint) { - const empty = new LastValue(); + const empty = new LastValue(this.initialValueFactory); if (typeof checkpoint !== "undefined") empty.value = [checkpoint]; return empty; } @@ -91794,7 +92689,7 @@ var SchemaMetaRegistry = class { for (const [key, channelSchema] of Object.entries(shape)) { const meta = this.get(channelSchema); if (meta?.reducer) channels[key] = new BinaryOperatorAggregate(meta.reducer.fn, meta.default); - else channels[key] = new LastValue(); + else channels[key] = new LastValue(meta?.default); } return channels; } @@ -93381,30 +94276,30 @@ function createCodeSuggestionTool() { }), func: async ({ reviewerComment, codeSnippet, filePath, prTitle, prContext }) => { // Build the fix prompt - const prompt = `You are an expert software engineer and code-fixer. You will take a reviewer comment and the associated code snippet and produce the corrected code snippet only. - -Context: -${prContext || '(no additional context)'} -- PR Title: ${prTitle || '(unknown)'} -- File: ${filePath} - -Reviewer comment: -${reviewerComment.trim()} - -Original code snippet: -\`\`\` -${codeSnippet} -\`\`\` - -Task: -1) Apply the reviewer's requested changes to the provided code snippet. -2) Output rules (MUST follow exactly): - - Return only the corrected code snippet (no explanations, no markdown fences, no extra text). - - If only a few lines changed you may return only the updated lines, but prefer returning the full corrected snippet when structural/context changes are required. - - Preserve original code style and indentation. - - If no changes are needed, reply with exactly: NO CHANGE - - Do not include filenames, metadata, or commentary. - + const prompt = `You are an expert software engineer and code-fixer. You will take a reviewer comment and the associated code snippet and produce the corrected code snippet only. + +Context: +${prContext || '(no additional context)'} +- PR Title: ${prTitle || '(unknown)'} +- File: ${filePath} + +Reviewer comment: +${reviewerComment.trim()} + +Original code snippet: +\`\`\` +${codeSnippet} +\`\`\` + +Task: +1) Apply the reviewer's requested changes to the provided code snippet. +2) Output rules (MUST follow exactly): + - Return only the corrected code snippet (no explanations, no markdown fences, no extra text). + - If only a few lines changed you may return only the updated lines, but prefer returning the full corrected snippet when structural/context changes are required. + - Preserve original code style and indentation. + - If no changes are needed, reply with exactly: NO CHANGE + - Do not include filenames, metadata, or commentary. + Produce the corrected code now.`; return JSON.stringify({ filePath, @@ -93971,9 +94866,9 @@ function filterFindingsByChangedFiles(findings, changedFiles) { function formatSemgrepFinding(finding) { const severity = finding.extra.severity; const icon = severity === 'ERROR' ? '❌' : severity === 'WARNING' ? '⚠️' : 'ℹ️'; - return `${icon} [${severity}] ${finding.extra.message} - File: ${finding.path}:${finding.start.line} - Rule: ${finding.check_id} + return `${icon} [${severity}] ${finding.extra.message} + File: ${finding.path}:${finding.start.line} + Rule: ${finding.check_id} ${finding.extra.metadata.category ? `Category: ${finding.extra.metadata.category}` : ''}`; } @@ -94298,39 +95193,39 @@ class BasePRAgentWorkflow { // Get detailed analysis for important files if (importantFiles.length > 0) { try { - const fileDetailsPrompt = `Analyze these files from a pull request. For EACH file, provide a detailed analysis considering the repository's architecture standards. -${archDocsContext ? '\n' + archDocsContext : ''} - -Files to analyze: -${importantFiles.map(f => ` -File: ${f.path} -Status: ${f.status || 'modified'} -Changes: +${f.additions} -${f.deletions} -Diff preview: -\`\`\` -${f.diff.substring(0, 500)} -\`\`\` -`).join('\n---\n')} - -${archDocsContext ? `CRITICAL INSTRUCTIONS: -- For EACH file, reference the relevant architecture documentation sections above -- Explain how the changes align with or diverge from established patterns -- Identify specific guidelines that apply to each file -- Mention which parts of the architecture are affected -- Compare changes against documented standards - -` : ''} - -Respond with a JSON object mapping file paths to analysis objects: -{ - "path/to/file": { - "summary": "Description that references relevant arch-docs patterns/guidelines", - "risks": ["risk with arch-docs context", "risk2"], - "complexity": 1-5, - "recommendations": ["recommendation based on arch-docs standards"] - } -} - + const fileDetailsPrompt = `Analyze these files from a pull request. For EACH file, provide a detailed analysis considering the repository's architecture standards. +${archDocsContext ? '\n' + archDocsContext : ''} + +Files to analyze: +${importantFiles.map(f => ` +File: ${f.path} +Status: ${f.status || 'modified'} +Changes: +${f.additions} -${f.deletions} +Diff preview: +\`\`\` +${f.diff.substring(0, 500)} +\`\`\` +`).join('\n---\n')} + +${archDocsContext ? `CRITICAL INSTRUCTIONS: +- For EACH file, reference the relevant architecture documentation sections above +- Explain how the changes align with or diverge from established patterns +- Identify specific guidelines that apply to each file +- Mention which parts of the architecture are affected +- Compare changes against documented standards + +` : ''} + +Respond with a JSON object mapping file paths to analysis objects: +{ + "path/to/file": { + "summary": "Description that references relevant arch-docs patterns/guidelines", + "risks": ["risk with arch-docs context", "risk2"], + "complexity": 1-5, + "recommendations": ["recommendation based on arch-docs standards"] + } +} + ${archDocsContext ? 'Each summary MUST reference the specific architecture documentation that applies to this file.' : ''}`; const response = await this.model.invoke(fileDetailsPrompt); const content = response.content; @@ -94510,49 +95405,49 @@ ${archDocsContext ? 'Each summary MUST reference the specific architecture docum securityContext += `\n## Repository Patterns and Best Practices\n\n${patterns.substring(0, 2000)}\n`; } } - const fixesPrompt = `You are a code reviewer analyzing a pull request. Generate CRUCIAL, actionable fixes as PR comments. -${securityContext} - -Analyze the following changes and identify issues that NEED to be fixed. Focus on: -1. **Security Issues**: Exposed credentials, insecure patterns, authentication/authorization problems -2. **Critical Bugs**: Logic errors, null pointer risks, race conditions -3. **Breaking Changes**: API changes without versioning, removed functionality -4. **Code Quality**: Missing error handling, code smells, anti-patterns -5. **Performance**: Inefficient algorithms, memory leaks, N+1 queries - -PR Title: ${context.title || 'No title provided'} - -Files changed: -${fileList} - -Diff: -\`\`\` -${diffSample} -\`\`\` - -${securityContext ? `IMPORTANT: Reference repository documentation when applicable.` : ''} - -For EACH issue found, provide: -- **file**: The file path where the issue exists -- **line**: Approximate line number (if you can identify it from the diff, otherwise omit) -- **comment**: Actionable PR comment explaining the issue and how to fix it. Be specific and helpful. -- **severity**: "critical" (must fix), "warning" (should fix), or "suggestion" (nice to have) - -Return a JSON array of fix objects: -[ - { - "file": "src/path/to/file.ts", - "line": 42, - "comment": "**Security Issue**: Hardcoded API key detected. Use environment variables instead.\n\n**Fix**: Move to process.env.API_KEY or use a secrets manager.", - "severity": "critical" - }, - { - "file": "src/utils/helper.ts", - "comment": "**Missing Error Handling**: This function can throw but errors aren't caught.\n\n**Fix**: Wrap in try-catch or add error handling.", - "severity": "warning" - } -] - + const fixesPrompt = `You are a code reviewer analyzing a pull request. Generate CRUCIAL, actionable fixes as PR comments. +${securityContext} + +Analyze the following changes and identify issues that NEED to be fixed. Focus on: +1. **Security Issues**: Exposed credentials, insecure patterns, authentication/authorization problems +2. **Critical Bugs**: Logic errors, null pointer risks, race conditions +3. **Breaking Changes**: API changes without versioning, removed functionality +4. **Code Quality**: Missing error handling, code smells, anti-patterns +5. **Performance**: Inefficient algorithms, memory leaks, N+1 queries + +PR Title: ${context.title || 'No title provided'} + +Files changed: +${fileList} + +Diff: +\`\`\` +${diffSample} +\`\`\` + +${securityContext ? `IMPORTANT: Reference repository documentation when applicable.` : ''} + +For EACH issue found, provide: +- **file**: The file path where the issue exists +- **line**: Approximate line number (if you can identify it from the diff, otherwise omit) +- **comment**: Actionable PR comment explaining the issue and how to fix it. Be specific and helpful. +- **severity**: "critical" (must fix), "warning" (should fix), or "suggestion" (nice to have) + +Return a JSON array of fix objects: +[ + { + "file": "src/path/to/file.ts", + "line": 42, + "comment": "**Security Issue**: Hardcoded API key detected. Use environment variables instead.\n\n**Fix**: Move to process.env.API_KEY or use a secrets manager.", + "severity": "critical" + }, + { + "file": "src/utils/helper.ts", + "comment": "**Missing Error Handling**: This function can throw but errors aren't caught.\n\n**Fix**: Wrap in try-catch or add error handling.", + "severity": "warning" + } +] + Only include CRUCIAL fixes that matter. If no significant issues, return an empty array [].`; try { const response = await this.model.invoke(fixesPrompt); @@ -94658,23 +95553,23 @@ Only include CRUCIAL fixes that matter. If no significant issues, return an empt semgrepSummaryContext += `- Files with issues: ${semgrepSummary.filesWithIssues.length}\n\n`; } // Create concise prompt for quick reading - const summaryPrompt = `Analyze this pull request and provide a BRIEF, scannable summary (2-3 sentences max). - -Focus on: -- **What**: What does this PR do? (one sentence) -- **Why**: What problem does it solve or what feature does it add? (one sentence) -- **Impact**: What parts of the codebase are affected? (one sentence if significant) - -PR Title: ${context.title || 'No title provided'} -${context.language ? `Language: ${context.language}${context.framework ? ` (${context.framework})` : ''}` : ''} - -Stats: ${totalFiles} files, +${totalAdditions}/-${totalDeletions} lines${fixes.length > 0 ? `, ${fixes.filter((f) => f.severity === 'critical').length} critical fixes` : ''} - -Key files: -${fileList.split('\n').slice(0, 5).join('\n')} - -${semgrepSummaryContext && semgrepSummary ? `Static analysis found ${semgrepSummary.totalFindings} issues (${semgrepSummary.errorCount} critical). ` : ''} - + const summaryPrompt = `Analyze this pull request and provide a BRIEF, scannable summary (2-3 sentences max). + +Focus on: +- **What**: What does this PR do? (one sentence) +- **Why**: What problem does it solve or what feature does it add? (one sentence) +- **Impact**: What parts of the codebase are affected? (one sentence if significant) + +PR Title: ${context.title || 'No title provided'} +${context.language ? `Language: ${context.language}${context.framework ? ` (${context.framework})` : ''}` : ''} + +Stats: ${totalFiles} files, +${totalAdditions}/-${totalDeletions} lines${fixes.length > 0 ? `, ${fixes.filter((f) => f.severity === 'critical').length} critical fixes` : ''} + +Key files: +${fileList.split('\n').slice(0, 5).join('\n')} + +${semgrepSummaryContext && semgrepSummary ? `Static analysis found ${semgrepSummary.totalFindings} issues (${semgrepSummary.errorCount} critical). ` : ''} + Write a concise summary that helps reviewers quickly understand the PR's purpose and scope. Be direct and specific.`; try { const response = await this.model.invoke(summaryPrompt); @@ -94704,12 +95599,12 @@ Write a concise summary that helps reviewers quickly understand the PR's purpose catch (error) { console.error('Error generating summary:', error); // Fallback to basic summary - const fallbackSummary = `PR Analysis Summary: -- Files changed: ${totalFiles} -- Additions: ${totalAdditions} -- Deletions: ${totalDeletions} -- Fixes identified: ${fixes.length} - + const fallbackSummary = `PR Analysis Summary: +- Files changed: ${totalFiles} +- Additions: ${totalAdditions} +- Deletions: ${totalDeletions} +- Fixes identified: ${fixes.length} + ${context.title ? `Title: ${context.title}` : ''}`; return { ...state, @@ -94736,20 +95631,20 @@ ${context.title ? `Title: ${context.title}` : ''}`; } } // Generate recommendations - const refinementPrompt = `Based on this PR analysis, provide 3-5 specific, actionable recommendations. - ${archDocsRefinementContext} - - PR Summary: - ${currentSummary} - - Fixes Identified: ${fixes.length} - ${fixes.length > 0 ? `\nKey fixes:\n${fixes.slice(0, 5).map(f => `- ${f.file}${f.line ? `:${f.line}` : ''}: ${f.comment.substring(0, 100)}...`).join('\n')}` : ''} - - Files Changed: ${fileAnalyses.size} - - ${archDocsRefinementContext ? 'Use the repository guidelines above to ensure recommendations align with established practices.\n' : ''} - - Provide a JSON array of recommendations: + const refinementPrompt = `Based on this PR analysis, provide 3-5 specific, actionable recommendations. + ${archDocsRefinementContext} + + PR Summary: + ${currentSummary} + + Fixes Identified: ${fixes.length} + ${fixes.length > 0 ? `\nKey fixes:\n${fixes.slice(0, 5).map(f => `- ${f.file}${f.line ? `:${f.line}` : ''}: ${f.comment.substring(0, 100)}...`).join('\n')}` : ''} + + Files Changed: ${fileAnalyses.size} + + ${archDocsRefinementContext ? 'Use the repository guidelines above to ensure recommendations align with established practices.\n' : ''} + + Provide a JSON array of recommendations: ["recommendation 1", "recommendation 2", ...]`; try { const response = await this.model.invoke(refinementPrompt); @@ -94879,6 +95774,8 @@ function extractToolCalls(content) { //# sourceMappingURL=output_parsers.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/utils/tools.js + + //#region src/utils/tools.ts function handleToolChoice(toolChoice) { if (!toolChoice) return void 0; @@ -94891,6 +95788,29 @@ function handleToolChoice(toolChoice) { }; else return toolChoice; } +const AnthropicToolExtrasSchema = object({ + cache_control: schemas_custom().optional().nullable(), + defer_loading: schemas_boolean().optional(), + input_examples: array(unknown()).optional(), + allowed_callers: array(unknown()).optional() +}); +/** +* Mapping of Anthropic tool types to their required beta feature flags. +* +* This constant defines which beta header is needed for specific tool types +* when making requests to the Anthropic API. Beta features are experimental +* capabilities that may change or be removed. +*/ +const ANTHROPIC_TOOL_BETAS = { + tool_search_tool_regex_20251119: "advanced-tool-use-2025-11-20", + tool_search_tool_bm25_20251119: "advanced-tool-use-2025-11-20", + memory_20250818: "context-management-2025-06-27", + web_fetch_20250910: "web-fetch-2025-09-10", + code_execution_20250825: "code-execution-2025-08-25", + computer_20251124: "computer-use-2025-11-24", + computer_20250124: "computer-use-2025-01-24", + mcp_toolset: "mcp-client-2025-11-20" +}; //#endregion @@ -95583,10 +96503,11 @@ function _makeMessageChunkFromAnthropicEvent(data, fields) { const filteredAdditionalKwargs = {}; for (const [key, value] of Object.entries(additionalKwargs)) if (value !== void 0 && value !== null) filteredAdditionalKwargs[key] = value; const { input_tokens, output_tokens,...rest } = usage ?? {}; + const totalInputTokens = input_tokens + rest.cache_creation_input_tokens + rest.cache_read_input_tokens; const usageMetadata = { - input_tokens, + input_tokens: totalInputTokens, output_tokens, - total_tokens: input_tokens + output_tokens, + total_tokens: totalInputTokens + output_tokens, input_token_details: { cache_creation: rest.cache_creation_input_tokens, cache_read: rest.cache_read_input_tokens @@ -96389,7 +97310,7 @@ const pop = (obj, key) => { const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); //# sourceMappingURL=sleep.mjs.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/version.mjs -const VERSION = '0.71.0'; // x-release-please-version +const VERSION = '0.71.2'; // x-release-please-version //# sourceMappingURL=version.mjs.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/internal/detect-platform.mjs // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. @@ -98036,43 +98957,57 @@ const MODEL_NONSTREAMING_TOKENS = { //# sourceMappingURL=constants.mjs.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/lib/beta-parser.mjs -function maybeParseBetaMessage(message, params) { +function maybeParseBetaMessage(message, params, opts) { if (!params || !('parse' in (params.output_format ?? {}))) { return { ...message, content: message.content.map((block) => { if (block.type === 'text') { - return { - ...block, - parsed: null, - }; + const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', { + value: null, + enumerable: false, + }); + return Object.defineProperty(parsedBlock, 'parsed', { + get() { + opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.'); + return null; + }, + enumerable: false, + }); } return block; }), parsed_output: null, }; } - return parseBetaMessage(message, params); + return parseBetaMessage(message, params, opts); } -function parseBetaMessage(message, params) { - let firstParsed = null; +function parseBetaMessage(message, params, opts) { + let firstParsedOutput = null; const content = message.content.map((block) => { if (block.type === 'text') { - const parsed = parseBetaOutputFormat(params, block.text); - if (firstParsed === null) { - firstParsed = parsed; + const parsedOutput = parseBetaOutputFormat(params, block.text); + if (firstParsedOutput === null) { + firstParsedOutput = parsedOutput; } - return { - ...block, - parsed, - }; + const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', { + value: parsedOutput, + enumerable: false, + }); + return Object.defineProperty(parsedBlock, 'parsed', { + get() { + opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.'); + return parsedOutput; + }, + enumerable: false, + }); } return block; }); return { ...message, content, - parsed_output: firstParsed, + parsed_output: firstParsedOutput, }; } function parseBetaOutputFormat(params, content) { @@ -98321,7 +99256,7 @@ const tokenize = (input) => { //# sourceMappingURL=streaming.mjs.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/lib/BetaMessageStream.mjs -var _BetaMessageStream_instances, _BetaMessageStream_currentMessageSnapshot, _BetaMessageStream_params, _BetaMessageStream_connectedPromise, _BetaMessageStream_resolveConnectedPromise, _BetaMessageStream_rejectConnectedPromise, _BetaMessageStream_endPromise, _BetaMessageStream_resolveEndPromise, _BetaMessageStream_rejectEndPromise, _BetaMessageStream_listeners, _BetaMessageStream_ended, _BetaMessageStream_errored, _BetaMessageStream_aborted, _BetaMessageStream_catchingPromiseCreated, _BetaMessageStream_response, _BetaMessageStream_request_id, _BetaMessageStream_getFinalMessage, _BetaMessageStream_getFinalText, _BetaMessageStream_handleError, _BetaMessageStream_beginRequest, _BetaMessageStream_addStreamEvent, _BetaMessageStream_endRequest, _BetaMessageStream_accumulateMessage; +var _BetaMessageStream_instances, _BetaMessageStream_currentMessageSnapshot, _BetaMessageStream_params, _BetaMessageStream_connectedPromise, _BetaMessageStream_resolveConnectedPromise, _BetaMessageStream_rejectConnectedPromise, _BetaMessageStream_endPromise, _BetaMessageStream_resolveEndPromise, _BetaMessageStream_rejectEndPromise, _BetaMessageStream_listeners, _BetaMessageStream_ended, _BetaMessageStream_errored, _BetaMessageStream_aborted, _BetaMessageStream_catchingPromiseCreated, _BetaMessageStream_response, _BetaMessageStream_request_id, _BetaMessageStream_logger, _BetaMessageStream_getFinalMessage, _BetaMessageStream_getFinalText, _BetaMessageStream_handleError, _BetaMessageStream_beginRequest, _BetaMessageStream_addStreamEvent, _BetaMessageStream_endRequest, _BetaMessageStream_accumulateMessage; @@ -98333,7 +99268,7 @@ function tracksToolInput(content) { return content.type === 'tool_use' || content.type === 'server_tool_use' || content.type === 'mcp_tool_use'; } class BetaMessageStream { - constructor(params) { + constructor(params, opts) { _BetaMessageStream_instances.add(this); this.messages = []; this.receivedMessages = []; @@ -98353,6 +99288,7 @@ class BetaMessageStream { _BetaMessageStream_catchingPromiseCreated.set(this, false); _BetaMessageStream_response.set(this, void 0); _BetaMessageStream_request_id.set(this, void 0); + _BetaMessageStream_logger.set(this, void 0); _BetaMessageStream_handleError.set(this, (error) => { __classPrivateFieldSet(this, _BetaMessageStream_errored, true, "f"); if (isAbortError(error)) { @@ -98388,6 +99324,7 @@ class BetaMessageStream { __classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => { }); __classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f").catch(() => { }); __classPrivateFieldSet(this, _BetaMessageStream_params, params, "f"); + __classPrivateFieldSet(this, _BetaMessageStream_logger, opts?.logger ?? console, "f"); } get response() { return __classPrivateFieldGet(this, _BetaMessageStream_response, "f"); @@ -98406,6 +99343,7 @@ class BetaMessageStream { * as no `Response` is available. */ async withResponse() { + __classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f"); const response = await __classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f"); if (!response) { throw new Error('Could not resolve a `Response` object'); @@ -98428,8 +99366,8 @@ class BetaMessageStream { runner._run(() => runner._fromReadableStream(stream)); return runner; } - static createMessage(messages, params, options) { - const runner = new BetaMessageStream(params); + static createMessage(messages, params, options, { logger } = {}) { + const runner = new BetaMessageStream(params, { logger }); for (const message of params.messages) { runner._addMessageParam(message); } @@ -98656,7 +99594,7 @@ class BetaMessageStream { } } } - [(_BetaMessageStream_currentMessageSnapshot = new WeakMap(), _BetaMessageStream_params = new WeakMap(), _BetaMessageStream_connectedPromise = new WeakMap(), _BetaMessageStream_resolveConnectedPromise = new WeakMap(), _BetaMessageStream_rejectConnectedPromise = new WeakMap(), _BetaMessageStream_endPromise = new WeakMap(), _BetaMessageStream_resolveEndPromise = new WeakMap(), _BetaMessageStream_rejectEndPromise = new WeakMap(), _BetaMessageStream_listeners = new WeakMap(), _BetaMessageStream_ended = new WeakMap(), _BetaMessageStream_errored = new WeakMap(), _BetaMessageStream_aborted = new WeakMap(), _BetaMessageStream_catchingPromiseCreated = new WeakMap(), _BetaMessageStream_response = new WeakMap(), _BetaMessageStream_request_id = new WeakMap(), _BetaMessageStream_handleError = new WeakMap(), _BetaMessageStream_instances = new WeakSet(), _BetaMessageStream_getFinalMessage = function _BetaMessageStream_getFinalMessage() { + [(_BetaMessageStream_currentMessageSnapshot = new WeakMap(), _BetaMessageStream_params = new WeakMap(), _BetaMessageStream_connectedPromise = new WeakMap(), _BetaMessageStream_resolveConnectedPromise = new WeakMap(), _BetaMessageStream_rejectConnectedPromise = new WeakMap(), _BetaMessageStream_endPromise = new WeakMap(), _BetaMessageStream_resolveEndPromise = new WeakMap(), _BetaMessageStream_rejectEndPromise = new WeakMap(), _BetaMessageStream_listeners = new WeakMap(), _BetaMessageStream_ended = new WeakMap(), _BetaMessageStream_errored = new WeakMap(), _BetaMessageStream_aborted = new WeakMap(), _BetaMessageStream_catchingPromiseCreated = new WeakMap(), _BetaMessageStream_response = new WeakMap(), _BetaMessageStream_request_id = new WeakMap(), _BetaMessageStream_logger = new WeakMap(), _BetaMessageStream_handleError = new WeakMap(), _BetaMessageStream_instances = new WeakSet(), _BetaMessageStream_getFinalMessage = function _BetaMessageStream_getFinalMessage() { if (this.receivedMessages.length === 0) { throw new error_AnthropicError('stream ended without producing a Message with role=assistant'); } @@ -98723,7 +99661,7 @@ class BetaMessageStream { } case 'message_stop': { this._addMessageParam(messageSnapshot); - this._addMessage(maybeParseBetaMessage(messageSnapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f")), true); + this._addMessage(maybeParseBetaMessage(messageSnapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") }), true); break; } case 'content_block_stop': { @@ -98747,7 +99685,7 @@ class BetaMessageStream { throw new error_AnthropicError(`request ended without sending any chunks`); } __classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f"); - return maybeParseBetaMessage(snapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f")); + return maybeParseBetaMessage(snapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") }); }, _BetaMessageStream_accumulateMessage = function _BetaMessageStream_accumulateMessage(event) { let snapshot = __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f"); if (event.type === 'message_start') { @@ -99597,7 +100535,7 @@ class Messages extends APIResource { } /** * Send a structured list of input messages with text and/or image content, along with an expected `output_format` and - * the response will be automatically parsed and available in the `parsed` property of the message. + * the response will be automatically parsed and available in the `parsed_output` property of the message. * * @example * ```ts @@ -99608,7 +100546,7 @@ class Messages extends APIResource { * output_format: zodOutputFormat(z.object({ answer: z.number() }), 'math'), * }); * - * console.log(message.parsed?.answer); // 4 + * console.log(message.parsed_output?.answer); // 4 * ``` */ parse(params, options) { @@ -99619,7 +100557,7 @@ class Messages extends APIResource { options?.headers, ]), }; - return this.create(params, options).then((message) => parseBetaMessage(message, params)); + return this.create(params, options).then((message) => parseBetaMessage(message, params, { logger: this._client.logger ?? console })); } /** * Create a Message stream @@ -99983,6 +100921,7 @@ class MessageStream { * as no `Response` is available. */ async withResponse() { + __classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f"); const response = await __classPrivateFieldGet(this, _MessageStream_connectedPromise, "f"); if (!response) { throw new Error('Could not resolve a `Response` object'); @@ -101329,8 +102268,161 @@ Anthropic.Beta = Beta; //# sourceMappingURL=index.mjs.map -// EXTERNAL MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/lib/transform-json-schema.js -var transform_json_schema = __nccwpck_require__(1252); +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/internal/utils/base64.mjs +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + + +const toBase64 = (data) => { + if (!data) + return ''; + if (typeof globalThis.Buffer !== 'undefined') { + return globalThis.Buffer.from(data).toString('base64'); + } + if (typeof data === 'string') { + data = encodeUTF8(data); + } + if (typeof btoa !== 'undefined') { + return btoa(String.fromCharCode.apply(null, data)); + } + throw new AnthropicError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); +}; +const fromBase64 = (str) => { + if (typeof globalThis.Buffer !== 'undefined') { + const buf = globalThis.Buffer.from(str, 'base64'); + return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); + } + if (typeof atob !== 'undefined') { + const bstr = atob(str); + const buf = new Uint8Array(bstr.length); + for (let i = 0; i < bstr.length; i++) { + buf[i] = bstr.charCodeAt(i); + } + return buf; + } + throw new AnthropicError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined'); +}; +//# sourceMappingURL=base64.mjs.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/internal/utils.mjs +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + + + + + + +//# sourceMappingURL=utils.mjs.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk/lib/transform-json-schema.mjs + +// Supported string formats +const SUPPORTED_STRING_FORMATS = new Set([ + 'date-time', + 'time', + 'date', + 'duration', + 'email', + 'hostname', + 'uri', + 'ipv4', + 'ipv6', + 'uuid', +]); +function transform_json_schema_deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); +} +function transformJSONSchema(jsonSchema) { + const workingCopy = transform_json_schema_deepClone(jsonSchema); + return _transformJSONSchema(workingCopy); +} +function _transformJSONSchema(jsonSchema) { + const strictSchema = {}; + const ref = pop(jsonSchema, '$ref'); + if (ref !== undefined) { + strictSchema['$ref'] = ref; + return strictSchema; + } + const defs = pop(jsonSchema, '$defs'); + if (defs !== undefined) { + const strictDefs = {}; + strictSchema['$defs'] = strictDefs; + for (const [name, defSchema] of Object.entries(defs)) { + strictDefs[name] = _transformJSONSchema(defSchema); + } + } + const type = pop(jsonSchema, 'type'); + const anyOf = pop(jsonSchema, 'anyOf'); + const oneOf = pop(jsonSchema, 'oneOf'); + const allOf = pop(jsonSchema, 'allOf'); + if (Array.isArray(anyOf)) { + strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant)); + } + else if (Array.isArray(oneOf)) { + strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant)); + } + else if (Array.isArray(allOf)) { + strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry)); + } + else { + if (type === undefined) { + throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used'); + } + strictSchema['type'] = type; + } + const description = pop(jsonSchema, 'description'); + if (description !== undefined) { + strictSchema['description'] = description; + } + const title = pop(jsonSchema, 'title'); + if (title !== undefined) { + strictSchema['title'] = title; + } + if (type === 'object') { + const properties = pop(jsonSchema, 'properties') || {}; + strictSchema['properties'] = Object.fromEntries(Object.entries(properties).map(([key, propSchema]) => [ + key, + _transformJSONSchema(propSchema), + ])); + pop(jsonSchema, 'additionalProperties'); + strictSchema['additionalProperties'] = false; + const required = pop(jsonSchema, 'required'); + if (required !== undefined) { + strictSchema['required'] = required; + } + } + else if (type === 'string') { + const format = pop(jsonSchema, 'format'); + if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) { + strictSchema['format'] = format; + } + else if (format !== undefined) { + jsonSchema['format'] = format; + } + } + else if (type === 'array') { + const items = pop(jsonSchema, 'items'); + if (items !== undefined) { + strictSchema['items'] = _transformJSONSchema(items); + } + const minItems = pop(jsonSchema, 'minItems'); + if (minItems !== undefined && (minItems === 0 || minItems === 1)) { + strictSchema['minItems'] = minItems; + } + else if (minItems !== undefined) { + jsonSchema['minItems'] = minItems; + } + } + if (Object.keys(jsonSchema).length > 0) { + const existingDescription = strictSchema['description']; + strictSchema['description'] = + (existingDescription ? existingDescription + '\n\n' : '') + + '{' + + Object.entries(jsonSchema) + .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) + .join(', ') + + '}'; + } + return strictSchema; +} +//# sourceMappingURL=transform-json-schema.mjs.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/chat_models.js @@ -101393,12 +102485,18 @@ function isBuiltinTool(tool) { "str_replace_editor_", "str_replace_based_edit_tool_", "code_execution_", - "memory_" + "memory_", + "tool_search_", + "mcp_toolset" ]; - return typeof tool === "object" && tool !== null && "type" in tool && "name" in tool && typeof tool.type === "string" && builtInToolPrefixes.some((prefix) => typeof tool.type === "string" && tool.type.startsWith(prefix)); + return typeof tool === "object" && tool !== null && "type" in tool && ("name" in tool || "mcp_server_name" in tool) && typeof tool.type === "string" && builtInToolPrefixes.some((prefix) => typeof tool.type === "string" && tool.type.startsWith(prefix)); } -function _combineBetas(a, b) { - return Array.from(new Set([...a ?? [], ...b ?? []])); +function _combineBetas(a, b, ...rest) { + return Array.from(new Set([ + ...a ?? [], + ...b ?? [], + ...rest.flatMap((x) => Array.from(x)) + ])); } function extractToken(chunk) { if (typeof chunk.content === "string") return chunk.content; @@ -101662,6 +102760,92 @@ function extractToken(chunk) { *
* *
+* Tool Search +* +* Tool search enables Claude to dynamically discover and load tools on-demand +* instead of loading all tool definitions upfront. This is useful when you have +* many tools but want to avoid the overhead of sending all definitions with every request. +* +* ```typescript +* import { ChatAnthropic } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* const tools = [ +* // Tool search server tool +* { +* type: "tool_search_tool_regex_20251119", +* name: "tool_search_tool_regex", +* }, +* // Tools with defer_loading are loaded on-demand +* { +* name: "get_weather", +* description: "Get the current weather for a location", +* input_schema: { +* type: "object", +* properties: { +* location: { type: "string", description: "City name" }, +* unit: { +* type: "string", +* enum: ["celsius", "fahrenheit"], +* }, +* }, +* required: ["location"], +* }, +* defer_loading: true, // Tool is loaded on-demand +* }, +* { +* name: "search_files", +* description: "Search through files in the workspace", +* input_schema: { +* type: "object", +* properties: { +* query: { type: "string" }, +* }, +* required: ["query"], +* }, +* defer_loading: true, // Tool is loaded on-demand +* }, +* ]; +* +* const modelWithTools = model.bindTools(tools); +* const response = await modelWithTools.invoke("What's the weather in San Francisco?"); +* ``` +* +* You can also use the `tool()` helper with the `extras` field: +* +* ```typescript +* import { tool } from "@langchain/core/tools"; +* import { z } from "zod"; +* +* const getWeather = tool( +* async (input) => `Weather in ${input.location}`, +* { +* name: "get_weather", +* description: "Get weather for a location", +* schema: z.object({ location: z.string() }), +* extras: { defer_loading: true }, +* } +* ); +* ``` +* +* **Note:** The required `advanced-tool-use-2025-11-20` beta header is automatically +* appended to the request when using tool search tools. +* +* **Best practices:** +* - Tools with `defer_loading: true` are only loaded when Claude discovers them via search +* - Keep your 3-5 most frequently used tools as non-deferred for optimal performance +* - Both regex and bm25 variants search tool names, descriptions, and argument info +* +* See the {@link https://platform.claude.com/docs/en/agents-and-tools/tool-use/tool-search-tool | Claude docs} +* for more information. +*
+* +*
+* +*
* Structured Output * * ChatAnthropic supports structured output through two main approaches: @@ -101917,8 +103101,9 @@ var ChatAnthropicMessages = class extends BaseChatModel { * @returns {AnthropicTool[] | undefined} The formatted tools, or undefined if none are passed. */ formatStructuredToolToAnthropic(tools) { - if (!tools || !tools.length) return void 0; + if (!tools) return void 0; return tools.map((tool) => { + if (isLangChainTool(tool) && tool.extras?.providerToolDefinition) return tool.extras.providerToolDefinition; if (isBuiltinTool(tool)) return tool; if (isAnthropicTool(tool)) return tool; if (isOpenAITool(tool)) return { @@ -101929,7 +103114,8 @@ var ChatAnthropicMessages = class extends BaseChatModel { if (isLangChainTool(tool)) return { name: tool.name, description: tool.description, - input_schema: isInteropZodSchema(tool.schema) ? toJsonSchema(tool.schema) : tool.schema + input_schema: isInteropZodSchema(tool.schema) ? toJsonSchema(tool.schema) : tool.schema, + ...tool.extras ? AnthropicToolExtrasSchema.parse(tool.extras) : {} }; throw new Error(`Unknown tool type passed to ChatAnthropic: ${JSON.stringify(tool, null, 2)}`); }); @@ -101945,29 +103131,15 @@ var ChatAnthropicMessages = class extends BaseChatModel { */ invocationParams(options) { const tool_choice = handleToolChoice(options?.tool_choice); - if (this.thinking.type === "enabled") { - if (this.topP !== void 0 && this.topK !== -1) throw new Error("topK is not supported when thinking is enabled"); - if (this.temperature !== void 0 && this.temperature !== 1) throw new Error("temperature is not supported when thinking is enabled"); - return { - model: this.model, - stop_sequences: options?.stop ?? this.stopSequences, - stream: this.streaming, - max_tokens: this.maxTokens, - tools: this.formatStructuredToolToAnthropic(options?.tools), - tool_choice, - thinking: this.thinking, - context_management: this.contextManagement, - ...this.invocationKwargs, - container: options?.container, - betas: _combineBetas(this.betas, options?.betas), - output_format: options?.output_format - }; - } - return { + const toolBetas = options?.tools?.reduce((acc, tool) => { + if (typeof tool === "object" && "type" in tool && tool.type in ANTHROPIC_TOOL_BETAS) { + const beta = ANTHROPIC_TOOL_BETAS[tool.type]; + if (!acc.includes(beta)) return [...acc, beta]; + } + return acc; + }, []); + const output = { model: this.model, - temperature: this.temperature, - top_k: this.topK, - top_p: this.topP, stop_sequences: options?.stop ?? this.stopSequences, stream: this.streaming, max_tokens: this.maxTokens, @@ -101977,9 +103149,19 @@ var ChatAnthropicMessages = class extends BaseChatModel { context_management: this.contextManagement, ...this.invocationKwargs, container: options?.container, - betas: _combineBetas(this.betas, options?.betas), - output_format: options?.output_format + betas: _combineBetas(this.betas, options?.betas, toolBetas ?? []), + output_format: options?.output_format, + mcp_servers: options?.mcp_servers }; + if (this.thinking.type === "enabled") { + if (this.topP !== void 0 && this.topK !== -1) throw new Error("topK is not supported when thinking is enabled"); + if (this.temperature !== void 0 && this.temperature !== 1) throw new Error("temperature is not supported when thinking is enabled"); + } else { + output.temperature = this.temperature; + output.top_k = this.topK; + output.top_p = this.topP; + } + return output; } /** @ignore */ _identifyingParams() { @@ -102181,7 +103363,7 @@ var ChatAnthropicMessages = class extends BaseChatModel { } if (method === "jsonSchema") { outputParser = isInteropZodSchema(schema) ? StructuredOutputParser.fromZodSchema(schema) : new JsonOutputParser(); - const jsonSchema = (0,transform_json_schema/* transformJSONSchema */.W)(toJsonSchema(schema)); + const jsonSchema = transformJSONSchema(toJsonSchema(schema)); llm = this.withConfig({ outputVersion: "v0", output_format: { @@ -102316,11 +103498,1048 @@ function convertPromptToAnthropic(formattedPrompt) { //#endregion //# sourceMappingURL=prompts.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/types.js + + +//#region src/tools/types.ts +/** +* Memory tool command types as defined by Anthropic's memory tool API. +* @beta +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool +*/ +const Memory20250818ViewCommandSchema = object({ + command: literal("view"), + path: schemas_string() +}); +const Memory20250818CreateCommandSchema = object({ + command: literal("create"), + path: schemas_string(), + file_text: schemas_string() +}); +const Memory20250818StrReplaceCommandSchema = object({ + command: literal("str_replace"), + path: schemas_string(), + old_str: schemas_string(), + new_str: schemas_string() +}); +const Memory20250818InsertCommandSchema = object({ + command: literal("insert"), + path: schemas_string(), + insert_line: schemas_number(), + insert_text: schemas_string() +}); +const Memory20250818DeleteCommandSchema = object({ + command: literal("delete"), + path: schemas_string() +}); +const Memory20250818RenameCommandSchema = object({ + command: literal("rename"), + old_path: schemas_string(), + new_path: schemas_string() +}); +const Memory20250818CommandSchema = discriminatedUnion("command", [ + Memory20250818ViewCommandSchema, + Memory20250818CreateCommandSchema, + Memory20250818StrReplaceCommandSchema, + Memory20250818InsertCommandSchema, + Memory20250818DeleteCommandSchema, + Memory20250818RenameCommandSchema +]); +/** +* Text editor tool command types for Claude 4.x models. +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/text-editor-tool +*/ +const TextEditor20250728ViewCommandSchema = object({ + command: literal("view"), + path: schemas_string(), + view_range: tuple([schemas_number(), schemas_number()]).optional() +}); +const TextEditor20250728StrReplaceCommandSchema = object({ + command: literal("str_replace"), + path: schemas_string(), + old_str: schemas_string(), + new_str: schemas_string() +}); +const TextEditor20250728CreateCommandSchema = object({ + command: literal("create"), + path: schemas_string(), + file_text: schemas_string() +}); +const TextEditor20250728InsertCommandSchema = object({ + command: literal("insert"), + path: schemas_string(), + insert_line: schemas_number(), + new_str: schemas_string() +}); +const TextEditor20250728CommandSchema = discriminatedUnion("command", [ + TextEditor20250728ViewCommandSchema, + TextEditor20250728StrReplaceCommandSchema, + TextEditor20250728CreateCommandSchema, + TextEditor20250728InsertCommandSchema +]); +const coordinateSchema = tuple([schemas_number(), schemas_number()]); +const ComputerScreenshotActionSchema = object({ action: literal("screenshot") }); +const ComputerLeftClickActionSchema = object({ + action: literal("left_click"), + coordinate: coordinateSchema +}); +const ComputerRightClickActionSchema = object({ + action: literal("right_click"), + coordinate: coordinateSchema +}); +const ComputerMiddleClickActionSchema = object({ + action: literal("middle_click"), + coordinate: coordinateSchema +}); +const ComputerDoubleClickActionSchema = object({ + action: literal("double_click"), + coordinate: coordinateSchema +}); +const ComputerTripleClickActionSchema = object({ + action: literal("triple_click"), + coordinate: coordinateSchema +}); +const ComputerLeftClickDragActionSchema = object({ + action: literal("left_click_drag"), + start_coordinate: coordinateSchema, + end_coordinate: coordinateSchema +}); +const ComputerLeftMouseDownActionSchema = object({ + action: literal("left_mouse_down"), + coordinate: coordinateSchema +}); +const ComputerLeftMouseUpActionSchema = object({ + action: literal("left_mouse_up"), + coordinate: coordinateSchema +}); +const ComputerScrollActionSchema = object({ + action: literal("scroll"), + coordinate: coordinateSchema, + scroll_direction: schemas_enum([ + "up", + "down", + "left", + "right" + ]), + scroll_amount: schemas_number() +}); +const ComputerTypeActionSchema = object({ + action: literal("type"), + text: schemas_string() +}); +const ComputerKeyActionSchema = object({ + action: literal("key"), + key: schemas_string() +}); +const ComputerMouseMoveActionSchema = object({ + action: literal("mouse_move"), + coordinate: coordinateSchema +}); +const ComputerHoldKeyActionSchema = object({ + action: literal("hold_key"), + key: schemas_string() +}); +const ComputerWaitActionSchema = object({ + action: literal("wait"), + duration: schemas_number().optional() +}); +const ComputerZoomActionSchema = object({ + action: literal("zoom"), + region: tuple([ + schemas_number(), + schemas_number(), + schemas_number(), + schemas_number() + ]) +}); +const Computer20250124ActionSchema = discriminatedUnion("action", [ + ComputerScreenshotActionSchema, + ComputerLeftClickActionSchema, + ComputerRightClickActionSchema, + ComputerMiddleClickActionSchema, + ComputerDoubleClickActionSchema, + ComputerTripleClickActionSchema, + ComputerLeftClickDragActionSchema, + ComputerLeftMouseDownActionSchema, + ComputerLeftMouseUpActionSchema, + ComputerScrollActionSchema, + ComputerTypeActionSchema, + ComputerKeyActionSchema, + ComputerMouseMoveActionSchema, + ComputerHoldKeyActionSchema, + ComputerWaitActionSchema +]); +const Computer20251124ActionSchema = discriminatedUnion("action", [ + ComputerScreenshotActionSchema, + ComputerLeftClickActionSchema, + ComputerRightClickActionSchema, + ComputerMiddleClickActionSchema, + ComputerDoubleClickActionSchema, + ComputerTripleClickActionSchema, + ComputerLeftClickDragActionSchema, + ComputerLeftMouseDownActionSchema, + ComputerLeftMouseUpActionSchema, + ComputerScrollActionSchema, + ComputerTypeActionSchema, + ComputerKeyActionSchema, + ComputerMouseMoveActionSchema, + ComputerHoldKeyActionSchema, + ComputerWaitActionSchema, + ComputerZoomActionSchema +]); +/** +* Bash tool command types for Claude 4 models and Claude 3.7. +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/bash-tool +*/ +const Bash20250124ExecuteCommandSchema = object({ command: schemas_string().describe("The bash command to run") }); +const Bash20250124RestartCommandSchema = object({ restart: literal(true).describe("Set to true to restart the bash session") }); +const Bash20250124CommandSchema = union([Bash20250124ExecuteCommandSchema, Bash20250124RestartCommandSchema]); + +//#endregion + +//# sourceMappingURL=types.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/memory.js + + + +//#region src/tools/memory.ts +/** +* Creates an Anthropic memory tool that can be used with ChatAnthropic. +* +* The memory tool enables Claude to store and retrieve information across conversations +* through a memory file directory. Claude can create, read, update, and delete files that +* persist between sessions, allowing it to build knowledge over time without keeping +* everything in the context window. +* +* @example +* ```typescript +* import { ChatAnthropic, memory_20250818 } from "@langchain/anthropic"; +* +* const llm = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929" +* }); +* +* const memory = memory_20250818({ +* execute: async (args) => { +* // handle memory command execution +* // ... +* }, +* }); +* const llmWithMemory = llm.bindTools([memory]); +* +* const response = await llmWithMemory.invoke("Remember that I like Python"); +* ``` +* +* @param options - Optional configuration for the memory tool (currently unused) +* @param options.execute - Optional execute function that handles memory command execution. +* @returns The memory tool object that can be passed to `bindTools` +* +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/memory-tool +*/ +function memory_20250818(options) { + const memoryTool = tool(options?.execute, { + name: "memory", + schema: Memory20250818CommandSchema + }); + memoryTool.extras = { + ...memoryTool.extras ?? {}, + providerToolDefinition: { + type: "memory_20250818", + name: "memory" + } + }; + return memoryTool; +} + +//#endregion + +//# sourceMappingURL=memory.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/webSearch.js +//#region src/tools/webSearch.ts +/** +* Creates a web search tool that gives Claude direct access to real-time web content, +* allowing it to answer questions with up-to-date information beyond its knowledge cutoff. +* Claude automatically cites sources from search results as part of its answer. +* +* @see {@link https://docs.anthropic.com/en/docs/build-with-claude/tool-use/web-search-tool | Anthropic Web Search Documentation} +* @param options - Configuration options for the web search tool +* @returns A web search tool definition to be passed to the Anthropic API +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* // Basic usage +* const response = await model.invoke("What is the weather in NYC?", { +* tools: [tools.webSearch_20250305()], +* }); +* +* // With options +* const responseWithOptions = await model.invoke("Latest news about AI?", { +* tools: [tools.webSearch_20250305({ +* maxUses: 5, +* allowedDomains: ["reuters.com", "bbc.com"], +* userLocation: { +* type: "approximate", +* city: "San Francisco", +* region: "California", +* country: "US", +* timezone: "America/Los_Angeles", +* }, +* })], +* }); +* ``` +*/ +function webSearch_20250305(options) { + return { + type: "web_search_20250305", + name: "web_search", + max_uses: options?.maxUses, + allowed_domains: options?.allowedDomains, + blocked_domains: options?.blockedDomains, + cache_control: options?.cacheControl, + defer_loading: options?.deferLoading, + strict: options?.strict, + user_location: options?.userLocation + }; +} + +//#endregion + +//# sourceMappingURL=webSearch.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/webFetch.js +//#region src/tools/webFetch.ts +/** +* Creates a web fetch tool that allows Claude to retrieve full content from specified +* web pages and PDF documents. Claude can only fetch URLs that have been explicitly +* provided by the user or that come from previous web search or web fetch results. +* +* @warning Enabling the web fetch tool in environments where Claude processes untrusted +* input alongside sensitive data poses data exfiltration risks. We recommend only using +* this tool in trusted environments or when handling non-sensitive data. +* +* @see {@link https://docs.anthropic.com/en/docs/build-with-claude/tool-use/web-fetch-tool | Anthropic Web Fetch Documentation} +* @param options - Configuration options for the web fetch tool +* @returns A web fetch tool definition to be passed to the Anthropic API +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* // Basic usage - fetch content from a URL +* const response = await model.invoke( +* "Please analyze the content at https://example.com/article", +* { tools: [tools.webFetch_20250910()] } +* ); +* +* // With options +* const responseWithOptions = await model.invoke( +* "Summarize this research paper: https://arxiv.org/abs/2024.12345", +* { +* tools: [tools.webFetch_20250910({ +* maxUses: 5, +* allowedDomains: ["arxiv.org", "example.com"], +* citations: { enabled: true }, +* maxContentTokens: 50000, +* })], +* } +* ); +* +* // Combined with web search for comprehensive information gathering +* const combinedResponse = await model.invoke( +* "Find recent articles about quantum computing and analyze the most relevant one", +* { +* tools: [ +* tools.webSearch_20250305({ maxUses: 3 }), +* tools.webFetch_20250910({ maxUses: 5, citations: { enabled: true } }), +* ], +* } +* ); +* ``` +*/ +function webFetch_20250910(options) { + return { + type: "web_fetch_20250910", + name: "web_fetch", + max_uses: options?.maxUses, + allowed_domains: options?.allowedDomains, + blocked_domains: options?.blockedDomains, + cache_control: options?.cacheControl, + citations: options?.citations, + max_content_tokens: options?.maxContentTokens + }; +} + +//#endregion + +//# sourceMappingURL=webFetch.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/toolSearch.js +//#region src/tools/toolSearch.ts +/** +* Creates a regex-based tool search tool that enables Claude to work with hundreds +* or thousands of tools by dynamically discovering and loading them on-demand. +* Claude constructs regex patterns (using Python's `re.search()` syntax) to search +* for tools by name, description, argument names, and argument descriptions. +* +* @note This tool requires the beta header `advanced-tool-use-2025-11-20` in API requests. +* +* @see {@link https://docs.anthropic.com/en/docs/build-with-claude/tool-use/tool-search-tool | Anthropic Tool Search Documentation} +* @param options - Configuration options for the tool search tool +* @returns A tool search tool definition to be passed to the Anthropic API +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* const getWeather = tool( +* async (input: { location: string }) => { +* return `Weather in ${input.location}`; +* }, +* { +* name: "get_weather", +* description: "Get the weather at a specific location", +* schema: z.object({ +* location: z.string(), +* }), +* extras: { defer_loading: true }, +* }, +* ); +* +* // Use with deferred tools - Claude will search and discover tools as needed +* const response = await model.invoke("What is the weather in San Francisco?", { +* tools: [ +* tools.toolSearchRegex_20251119(), +* getWeather, +* ], +* }); +* ``` +*/ +function toolSearchRegex_20251119(options) { + return { + type: "tool_search_tool_regex_20251119", + name: "tool_search_tool_regex", + cache_control: options?.cacheControl + }; +} +/** +* Creates a BM25-based tool search tool that enables Claude to work with hundreds +* or thousands of tools by dynamically discovering and loading them on-demand. +* Claude uses natural language queries to search for tools by name, description, +* argument names, and argument descriptions. +* +* @note This tool requires the beta header `advanced-tool-use-2025-11-20` in API requests. +* +* @see {@link https://docs.anthropic.com/en/docs/build-with-claude/tool-use/tool-search-tool | Anthropic Tool Search Documentation} +* @param options - Configuration options for the tool search tool +* @returns A tool search tool definition to be passed to the Anthropic API +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* clientOptions: { +* defaultHeaders: { "anthropic-beta": "advanced-tool-use-2025-11-20" }, +* }, +* }); +* +* const getWeather = tool( +* async (input: { location: string }) => { +* return `Weather in ${input.location}`; +* }, +* { +* name: "get_weather", +* description: "Get the weather at a specific location", +* schema: z.object({ +* location: z.string(), +* }), +* extras: { defer_loading: true }, +* }, +* ); +* +* // Use with deferred tools - Claude will search using natural language +* const response = await model.invoke("What is the weather in San Francisco?", { +* tools: [ +* tools.toolSearchBM25_20251119(), +* getWeather, +* ], +* }); +* ``` +*/ +function toolSearchBM25_20251119(options) { + return { + type: "tool_search_tool_bm25_20251119", + name: "tool_search_tool_bm25", + cache_control: options?.cacheControl + }; +} + +//#endregion + +//# sourceMappingURL=toolSearch.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/textEditor.js + + + +//#region src/tools/textEditor.ts +/** +* Creates an Anthropic text editor tool for Claude 4.x models that can view and modify text files. +* +* The text editor tool enables Claude to view and modify text files, helping debug, fix, +* and improve code or other text documents. Claude can directly interact with files, +* providing hands-on assistance rather than just suggesting changes. +* +* Available commands: +* - `view`: Examine file contents or list directory contents +* - `str_replace`: Replace specific text in a file +* - `create`: Create a new file with specified content +* - `insert`: Insert text at a specific line number +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* import * as fs from "fs"; +* +* const llm = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* const textEditor = tools.textEditor_20250728({ +* execute: async (args) => { +* if (args.command === "view") { +* const content = fs.readFileSync(args.path, "utf-8"); +* return content.split("\n").map((line, i) => `${i + 1}: ${line}`).join("\n"); +* } +* if (args.command === "str_replace") { +* let content = fs.readFileSync(args.path, "utf-8"); +* content = content.replace(args.old_str!, args.new_str!); +* fs.writeFileSync(args.path, content); +* return "Successfully replaced text."; +* } +* // Handle other commands... +* return "Command executed"; +* }, +* maxCharacters: 10000, +* }); +* +* const llmWithEditor = llm.bindTools([textEditor]); +* const response = await llmWithEditor.invoke( +* "There's a syntax error in my primes.py file. Can you help me fix it?" +* ); +* ``` +* +* @param options - Configuration options for the text editor tool +* @param options.execute - Function that handles text editor command execution +* @param options.maxCharacters - Maximum characters to return when viewing files +* @returns The text editor tool object that can be passed to `bindTools` +* +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/text-editor-tool +*/ +function textEditor_20250728(options) { + const name = "str_replace_based_edit_tool"; + const textEditorTool = tool(options?.execute, { + name, + description: "A tool for editing text files", + schema: TextEditor20250728CommandSchema + }); + textEditorTool.extras = { + ...textEditorTool.extras ?? {}, + providerToolDefinition: { + type: "text_editor_20250728", + name, + ...options?.maxCharacters !== void 0 && { max_characters: options.maxCharacters } + } + }; + return textEditorTool; +} + +//#endregion + +//# sourceMappingURL=textEditor.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/computer.js + + + +//#region src/tools/computer.ts +const TOOL_NAME = "computer"; +/** +* Creates an Anthropic computer use tool for Claude Opus 4.5 that provides +* screenshot capabilities and mouse/keyboard control for autonomous desktop interaction. +* +* The computer use tool enables Claude to interact with desktop environments through: +* - **Screenshot capture**: See what's currently displayed on screen +* - **Mouse control**: Click, drag, and move the cursor +* - **Keyboard input**: Type text and use keyboard shortcuts +* - **Zoom**: View specific screen regions at full resolution (when enabled) +* +* @warning Computer use is a beta feature with unique risks. Use a dedicated virtual machine +* or container with minimal privileges. Avoid giving access to sensitive data. +* +* @see {@link https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool | Anthropic Computer Use Documentation} +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const llm = new ChatAnthropic({ +* model: "claude-opus-4-5-20251101", +* clientOptions: { +* defaultHeaders: { +* "anthropic-beta": "computer-use-2025-11-24", +* }, +* }, +* }); +* +* const computer = tools.computer_20251124({ +* displayWidthPx: 1024, +* displayHeightPx: 768, +* displayNumber: 1, +* enableZoom: true, +* execute: async (action) => { +* if (action.action === "screenshot") { +* // Capture and return base64-encoded screenshot +* return captureScreenshot(); +* } +* if (action.action === "left_click") { +* // Click at the specified coordinates +* await click(action.coordinate[0], action.coordinate[1]); +* return captureScreenshot(); +* } +* // Handle other actions... +* }, +* }); +* +* const llmWithComputer = llm.bindTools([computer]); +* const response = await llmWithComputer.invoke( +* "Save a picture of a cat to my desktop." +* ); +* ``` +* +* @param options - Configuration options for the computer use tool +* @returns The computer use tool object that can be passed to `bindTools` +*/ +function computer_20251124(options) { + const name = TOOL_NAME; + const computerTool = tool(options.execute, { + name, + schema: Computer20251124ActionSchema + }); + computerTool.extras = { + ...computerTool.extras ?? {}, + providerToolDefinition: { + type: "computer_20251124", + name, + display_width_px: options.displayWidthPx, + display_height_px: options.displayHeightPx, + ...options.displayNumber !== void 0 && { display_number: options.displayNumber }, + ...options.enableZoom !== void 0 && { enable_zoom: options.enableZoom } + } + }; + return computerTool; +} +/** +* Creates an Anthropic computer use tool that provides screenshot capabilities and mouse/keyboard control +* for autonomous desktop interaction. +* +* Supported models: Claude Sonnet 4.5, Haiku 4.5, Opus 4.1, Sonnet 4, Opus 4, and Sonnet 3.7 versions. +* +* The computer use tool enables Claude to interact with desktop environments through: +* - **Screenshot capture**: See what's currently displayed on screen +* - **Mouse control**: Click, drag, and move the cursor +* - **Keyboard input**: Type text and use keyboard shortcuts +* +* @warning Computer use is a beta feature with unique risks. Use a dedicated virtual machine +* or container with minimal privileges. Avoid giving access to sensitive data. +* +* @see {@link https://platform.claude.com/docs/en/agents-and-tools/tool-use/computer-use-tool | Anthropic Computer Use Documentation} +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const llm = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* clientOptions: { +* defaultHeaders: { +* "anthropic-beta": "computer-use-2025-01-24", +* }, +* }, +* }); +* +* const computer = tools.computer_20250124({ +* displayWidthPx: 1024, +* displayHeightPx: 768, +* displayNumber: 1, +* execute: async (action) => { +* if (action.action === "screenshot") { +* // Capture and return base64-encoded screenshot +* return captureScreenshot(); +* } +* if (action.action === "left_click") { +* // Click at the specified coordinates +* await click(action.coordinate[0], action.coordinate[1]); +* return captureScreenshot(); +* } +* // Handle other actions... +* }, +* }); +* +* const llmWithComputer = llm.bindTools([computer]); +* const response = await llmWithComputer.invoke( +* "Save a picture of a cat to my desktop." +* ); +* ``` +* +* @param options - Configuration options for the computer use tool +* @returns The computer use tool object that can be passed to `bindTools` +*/ +function computer_20250124(options) { + const name = TOOL_NAME; + const computerTool = tool(options.execute, { + name, + description: "A tool for interacting with the computer", + schema: Computer20250124ActionSchema + }); + computerTool.extras = { + ...computerTool.extras ?? {}, + providerToolDefinition: { + type: "computer_20250124", + name, + display_width_px: options.displayWidthPx, + display_height_px: options.displayHeightPx, + ...options.displayNumber !== void 0 && { display_number: options.displayNumber } + } + }; + return computerTool; +} + +//#endregion + +//# sourceMappingURL=computer.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/codeExecution.js +//#region src/tools/codeExecution.ts +/** +* Creates a code execution tool that allows Claude to run Bash commands and manipulate files +* in a secure, sandboxed environment. Claude can analyze data, create visualizations, +* perform calculations, and process files. +* +* When this tool is provided, Claude automatically gains access to: +* - **Bash commands**: Execute shell commands for system operations +* - **File operations**: Create, view, and edit files directly +* +* @note This tool requires the beta header `code-execution-2025-08-25` in API requests. +* +* @see {@link https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/code-execution-tool | Anthropic Code Execution Documentation} +* @param options - Configuration options for the code execution tool +* @returns A code execution tool definition to be passed to the Anthropic API +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* // Basic usage - calculations and data analysis +* const response = await model.invoke( +* "Calculate the mean and standard deviation of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", +* { tools: [tools.codeExecution_20250825()] } +* ); +* +* // File operations and visualization +* const response2 = await model.invoke( +* "Create a matplotlib visualization of sales data and save it as chart.png", +* { tools: [tools.codeExecution_20250825()] } +* ); +* ``` +* +* @example Container reuse +* ```typescript +* // First request - creates a container +* const response1 = await model.invoke( +* "Write a random number to /tmp/number.txt", +* { tools: [tools.codeExecution_20250825()] } +* ); +* +* // Extract container ID from response for reuse +* const containerId = response1.response_metadata?.container?.id; +* +* // Second request - reuse container to access the file +* const response2 = await model.invoke( +* "Read /tmp/number.txt and calculate its square", +* { +* tools: [tools.codeExecution_20250825()], +* // Pass container ID to reuse the same environment +* } +* ); +* ``` +*/ +function codeExecution_20250825(options) { + return { + type: "code_execution_20250825", + name: "code_execution", + cache_control: options?.cacheControl + }; +} + +//#endregion + +//# sourceMappingURL=codeExecution.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/bash.js + + + +//#region src/tools/bash.ts +/** +* Creates an Anthropic bash tool for Claude 4 models and Claude 3.7 that enables +* shell command execution in a persistent bash session. +* +* The bash tool provides Claude with: +* - **Persistent bash session**: Maintains state between commands +* - **Shell command execution**: Run any shell command +* - **Environment access**: Access to environment variables and working directory +* - **Command chaining**: Support for pipes, redirects, and scripting +* +* Available commands: +* - Execute a command: `{ command: "ls -la" }` +* - Restart the session: `{ restart: true }` +* +* @warning The bash tool provides direct system access. Implement safety measures +* such as running in isolated environments (Docker/VM), command filtering, +* and resource limits. +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* import { execSync } from "child_process"; +* +* const llm = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* const bash = tools.bash_20250124({ +* execute: async (args) => { +* if (args.restart) { +* // Reset session state +* return "Bash session restarted"; +* } +* try { +* const output = execSync(args.command!, { +* encoding: "utf-8", +* timeout: 30000, +* }); +* return output; +* } catch (error) { +* return `Error: ${error.message}`; +* } +* }, +* }); +* +* const llmWithBash = llm.bindTools([bash]); +* const response = await llmWithBash.invoke( +* "List all Python files in the current directory" +* ); +* +* // Outputs: "bash" +* console.log(response.tool_calls[0].name); +* // Outputs: "ls -la *.py 2>/dev/null || echo \"No Python files found in the current directory\" +* console.log(response.tool_calls[0].args.command); +* ``` +* +* @example Multi-step automation +* ```typescript +* // Claude can chain commands in a persistent session: +* // 1. cd /tmp +* // 2. echo "Hello" > test.txt +* // 3. cat test.txt // Works because we're still in /tmp +* ``` +* +* @param options - Configuration options for the bash tool +* @param options.execute - Function that handles bash command execution +* @returns The bash tool object that can be passed to `bindTools` +* +* @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/bash-tool +*/ +function bash_20250124(options) { + const name = "bash"; + const bashTool = tool(options?.execute, { + name, + description: "A tool for executing bash commands", + schema: Bash20250124CommandSchema + }); + bashTool.extras = { + ...bashTool.extras ?? {}, + providerToolDefinition: { + type: "bash_20250124", + name + } + }; + return bashTool; +} + +//#endregion + +//# sourceMappingURL=bash.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/mcpToolset.js +//#region src/tools/mcpToolset.ts +/** +* Creates an MCP toolset that connects to a remote MCP server to access its tools. +* This enables Claude to use tools from MCP servers without implementing a separate MCP client. +* +* @note This tool requires the beta header `mcp-client-2025-11-20` in API requests. +* The header is automatically added when using this tool. +* +* @see {@link https://docs.anthropic.com/en/docs/agents-and-tools/mcp-connector | Anthropic MCP Connector Documentation} +* @param options - Configuration options for the MCP toolset +* @returns An MCP toolset definition to be passed to the Anthropic API tools array +* +* @example +* ```typescript +* import { ChatAnthropic, tools } from "@langchain/anthropic"; +* +* const model = new ChatAnthropic({ +* model: "claude-sonnet-4-5-20250929", +* }); +* +* // Basic usage - enable all tools from an MCP server +* const response = await model.invoke("What tools do you have available?", { +* mcp_servers: [{ +* type: "url", +* url: "https://example-server.modelcontextprotocol.io/sse", +* name: "example-mcp", +* authorization_token: "YOUR_TOKEN", +* }], +* tools: [ +* tools.mcpToolset_20251120({ serverName: "example-mcp" }), +* ], +* }); +* +* // Allowlist pattern - enable only specific tools +* const responseAllowlist = await model.invoke("Search for events", { +* mcp_servers: [{ +* type: "url", +* url: "https://calendar.example.com/sse", +* name: "google-calendar-mcp", +* authorization_token: "YOUR_TOKEN", +* }], +* tools: [ +* tools.mcpToolset_20251120({ +* serverName: "google-calendar-mcp", +* defaultConfig: { enabled: false }, +* configs: { +* search_events: { enabled: true }, +* create_event: { enabled: true }, +* }, +* }), +* ], +* }); +* +* // Denylist pattern - disable specific tools +* const responseDenylist = await model.invoke("List my events", { +* mcp_servers: [{ +* type: "url", +* url: "https://calendar.example.com/sse", +* name: "google-calendar-mcp", +* authorization_token: "YOUR_TOKEN", +* }], +* tools: [ +* tools.mcpToolset_20251120({ +* serverName: "google-calendar-mcp", +* configs: { +* delete_all_events: { enabled: false }, +* share_calendar_publicly: { enabled: false }, +* }, +* }), +* ], +* }); +* +* // With deferred loading for use with Tool Search Tool +* const responseDeferred = await model.invoke("Search for tools", { +* mcp_servers: [{ +* type: "url", +* url: "https://example.com/sse", +* name: "example-mcp", +* }], +* tools: [ +* tools.toolSearchRegex_20251119(), +* tools.mcpToolset_20251120({ +* serverName: "example-mcp", +* defaultConfig: { deferLoading: true }, +* }), +* ], +* }); +* ``` +*/ +function mcpToolset_20251120(options) { + const defaultConfig = options.defaultConfig?.enabled !== void 0 || options.defaultConfig?.deferLoading !== void 0 ? { + enabled: options.defaultConfig?.enabled, + defer_loading: options.defaultConfig?.deferLoading + } : void 0; + const configs = options.configs ? Object.fromEntries(Object.entries(options.configs).map(([toolName, config]) => [toolName, { + enabled: config.enabled, + defer_loading: config.deferLoading + }])) : void 0; + return { + type: "mcp_toolset", + mcp_server_name: options.serverName, + default_config: defaultConfig, + configs, + cache_control: options.cacheControl + }; +} + +//#endregion + +//# sourceMappingURL=mcpToolset.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/tools/index.js + + + + + + + + + + +//#region src/tools/index.ts +const tools = { + memory_20250818: memory_20250818, + webSearch_20250305: webSearch_20250305, + webFetch_20250910: webFetch_20250910, + toolSearchRegex_20251119: toolSearchRegex_20251119, + toolSearchBM25_20251119: toolSearchBM25_20251119, + textEditor_20250728: textEditor_20250728, + computer_20251124: computer_20251124, + computer_20250124: computer_20250124, + codeExecution_20250825: codeExecution_20250825, + bash_20250124: bash_20250124, + mcpToolset_20251120: mcpToolset_20251120 +}; + +//#endregion + +//# sourceMappingURL=index.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/anthropic/dist/index.js + ;// CONCATENATED MODULE: ./src/providers/anthropic.provider.ts /** @@ -102652,7 +104871,7 @@ const values_safeJSON = (text) => { const sleep_sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); //# sourceMappingURL=sleep.mjs.map ;// CONCATENATED MODULE: ./node_modules/openai/version.mjs -const version_VERSION = '6.9.1'; // x-release-please-version +const version_VERSION = '6.15.0'; // x-release-please-version //# sourceMappingURL=version.mjs.map ;// CONCATENATED MODULE: ./node_modules/openai/internal/detect-platform.mjs // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. @@ -106712,7 +108931,7 @@ class Steps extends resource_APIResource { // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -const toBase64 = (data) => { +const base64_toBase64 = (data) => { if (!data) return ''; if (typeof globalThis.Buffer !== 'undefined') { @@ -106726,7 +108945,7 @@ const toBase64 = (data) => { } throw new OpenAIError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined'); }; -const fromBase64 = (str) => { +const base64_fromBase64 = (str) => { if (typeof globalThis.Buffer !== 'undefined') { const buf = globalThis.Buffer.from(str, 'base64'); return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength); @@ -109151,6 +111370,19 @@ class Responses extends resource_APIResource { cancel(responseID, options) { return this._client.post(path_path `/responses/${responseID}/cancel`, options); } + /** + * Compact conversation + * + * @example + * ```ts + * const compactedResponse = await client.responses.compact({ + * model: 'gpt-5.2', + * }); + * ``` + */ + compact(body, options) { + return this._client.post('/responses/compact', { body, ...options }); + } } Responses.InputItems = InputItems; Responses.InputTokens = InputTokens; @@ -110490,6 +112722,11 @@ function extractGenericMessageCustomRole(message) { if (message.role !== "system" && message.role !== "developer" && message.role !== "assistant" && message.role !== "user" && message.role !== "function" && message.role !== "tool") console.warn(`Unknown message role: ${message.role}`); return message.role; } +function getRequiredFilenameFromMetadata(block) { + const filename = block.metadata?.filename ?? block.metadata?.name ?? block.metadata?.title; + if (!filename) throw new Error("a filename or name or title is needed via meta-data for OpenAI when working with multimodal blocks"); + return filename; +} function messageToOpenAIRole(message) { const type = message._getType(); switch (type) { @@ -110504,6 +112741,9 @@ function messageToOpenAIRole(message) { default: throw new Error(`Unknown message type: ${type}`); } } +function _modelPrefersResponsesAPI(model) { + return model.includes("gpt-5.2-pro"); +} //#endregion @@ -110700,6 +112940,14 @@ function formatToOpenAIToolChoice(toolChoice) { function isBuiltInTool(tool) { return "type" in tool && tool.type !== "function"; } +/** +* Checks if a tool has a provider-specific tool definition in extras.providerToolDefinition. +* This is used for tools like localShell, shell, computerUse, and applyPatch +* that need to be sent as built-in tool types to the OpenAI API. +*/ +function hasProviderToolDefinition(tool) { + return typeof tool === "object" && tool !== null && "extras" in tool && typeof tool.extras === "object" && tool.extras !== null && "providerToolDefinition" in tool.extras && typeof tool.extras.providerToolDefinition === "object" && tool.extras.providerToolDefinition !== null; +} function isBuiltInToolChoice(tool_choice) { return tool_choice != null && typeof tool_choice === "object" && "type" in tool_choice && tool_choice.type !== "function"; } @@ -110721,8 +112969,35 @@ function parseCustomToolCall(rawToolCall) { args: { input: rawToolCall.input } }; } +/** +* Parses a computer_call output item from the OpenAI Responses API +* into a ToolCall format that can be processed by the ToolNode. +* +* @param rawToolCall - The raw computer_call output item from the API +* @returns A ComputerToolCall object if valid, undefined otherwise +*/ +function parseComputerCall(rawToolCall) { + if (rawToolCall.type !== "computer_call") return void 0; + return { + ...rawToolCall, + type: "tool_call", + call_id: rawToolCall.id, + id: rawToolCall.call_id, + name: "computer_use", + isComputerTool: true, + args: { action: rawToolCall.action } + }; +} +/** +* Checks if a tool call is a computer tool call. +* @param toolCall - The tool call to check. +* @returns True if the tool call is a computer tool call, false otherwise. +*/ +function isComputerToolCall(toolCall) { + return typeof toolCall === "object" && toolCall !== null && "type" in toolCall && toolCall.type === "tool_call" && "isComputerTool" in toolCall && toolCall.isComputerTool === true; +} function isCustomToolCall(toolCall) { - return toolCall.type === "tool_call" && "isCustomTool" in toolCall && toolCall.isCustomTool === true; + return typeof toolCall === "object" && toolCall !== null && "type" in toolCall && toolCall.type === "tool_call" && "isCustomTool" in toolCall && toolCall.isCustomTool === true; } function convertCompletionsCustomTool(tool) { const getFormat = () => { @@ -112278,7 +114553,7 @@ function ensureStrictJsonSchema(jsonSchema, path, root) { if (typeof ref !== 'string') { throw new TypeError(`Received non-string $ref - ${ref}; path=${path.join('/')}`); } - const resolved = resolveRef(root, ref); + const resolved = transform_resolveRef(root, ref); if (typeof resolved === 'boolean') { throw new Error(`Expected \`$ref: ${ref}\` to resolve to an object schema but got boolean`); } @@ -112294,7 +114569,7 @@ function ensureStrictJsonSchema(jsonSchema, path, root) { } return jsonSchema; } -function resolveRef(root, ref) { +function transform_resolveRef(root, ref) { if (!ref.startsWith('#/')) { throw new Error(`Unexpected $ref format ${JSON.stringify(ref)}; Does not start with #/`); } @@ -112448,6 +114723,7 @@ function zodResponsesFunction(options) { + //#region src/utils/output.ts const SUPPORTED_METHODS = [ "jsonSchema", @@ -112501,7 +114777,7 @@ function interopZodResponseFormat(zodSchema, name, props) { ...props, name, strict: true, - schema: toJSONSchema(zodSchema, { + schema: toJsonSchema(zodSchema, { cycles: "ref", reused: "ref", override(ctx) { @@ -113123,6 +115399,7 @@ var profiles_profiles_default = profiles_PROFILES; + //#region src/chat_models/base.ts /** @internal */ var BaseChatOpenAI = class extends BaseChatModel { @@ -113182,6 +115459,10 @@ var BaseChatOpenAI = class extends BaseChatModel { */ promptCacheKey; /** + * Used by OpenAI to set cache retention time + */ + promptCacheRetention; + /** * The verbosity of the model's response. */ verbosity; @@ -113257,6 +115538,7 @@ var BaseChatOpenAI = class extends BaseChatModel { "zdrEnabled", "reasoning", "promptCacheKey", + "promptCacheRetention", "verbosity" ]; } @@ -113310,6 +115592,7 @@ var BaseChatOpenAI = class extends BaseChatModel { this.reasoning = fields?.reasoning; this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens; this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey; + this.promptCacheRetention = fields?.promptCacheRetention ?? this.promptCacheRetention; this.verbosity = fields?.verbosity ?? this.verbosity; this.disableStreaming = fields?.disableStreaming === true; this.streaming = fields?.streaming === true; @@ -113398,7 +115681,11 @@ var BaseChatOpenAI = class extends BaseChatModel { if (kwargs?.strict !== void 0) strict = kwargs.strict; else if (this.supportsStrictToolCalling !== void 0) strict = this.supportsStrictToolCalling; return this.withConfig({ - tools: tools.map((tool) => isBuiltInTool(tool) || isCustomTool(tool) ? tool : this._convertChatOpenAIToolToCompletionsTool(tool, { strict })), + tools: tools.map((tool) => { + if (isBuiltInTool(tool) || isCustomTool(tool)) return tool; + if (hasProviderToolDefinition(tool)) return tool.extras.providerToolDefinition; + return this._convertChatOpenAIToolToCompletionsTool(tool, { strict }); + }), ...kwargs }); } @@ -113480,6 +115767,61 @@ var BaseChatOpenAI = class extends BaseChatModel { return tokens; } /** + * Moderate content using OpenAI's Moderation API. + * + * This method checks whether content violates OpenAI's content policy by + * analyzing text for categories such as hate, harassment, self-harm, + * sexual content, violence, and more. + * + * @param input - The text or array of texts to moderate + * @param params - Optional parameters for the moderation request + * @param params.model - The moderation model to use. Defaults to "omni-moderation-latest". + * @param params.options - Additional options to pass to the underlying request + * @returns A promise that resolves to the moderation response containing results for each input + * + * @example + * ```typescript + * const model = new ChatOpenAI({ model: "gpt-4o-mini" }); + * + * // Moderate a single text + * const result = await model.moderateContent("This is a test message"); + * console.log(result.results[0].flagged); // false + * console.log(result.results[0].categories); // { hate: false, harassment: false, ... } + * + * // Moderate multiple texts + * const results = await model.moderateContent([ + * "Hello, how are you?", + * "This is inappropriate content" + * ]); + * results.results.forEach((result, index) => { + * console.log(`Text ${index + 1} flagged:`, result.flagged); + * }); + * + * // Use a specific moderation model + * const stableResult = await model.moderateContent( + * "Test content", + * { model: "omni-moderation-latest" } + * ); + * ``` + */ + async moderateContent(input, params) { + const clientOptions = this._getClientOptions(params?.options); + const moderationModel = params?.model ?? "omni-moderation-latest"; + const moderationRequest = { + input, + model: moderationModel + }; + return this.caller.call(async () => { + try { + const response = await this.client.moderations.create(moderationRequest, clientOptions); + return response; + } catch (e) { + const error = wrapOpenAIClientError(e); + throw error; + } + }); + } + /** * Return profiling information for the model. * * Provides information about the model's capabilities and constraints, @@ -113741,22 +116083,26 @@ const completionsApiContentBlockConverter = { fromStandardFileBlock(block) { if (block.source_type === "url") { const data = parseBase64DataUrl({ dataUrl: block.url }); + const filename = getRequiredFilenameFromMetadata(block); if (!data) throw new Error(`URL file blocks with source_type ${block.source_type} must be formatted as a data URL for ChatOpenAI`); return { type: "file", file: { file_data: block.url, - ...block.metadata?.filename || block.metadata?.name ? { filename: block.metadata?.filename || block.metadata?.name } : {} + ...block.metadata?.filename || block.metadata?.name ? { filename } : {} + } + }; + } + if (block.source_type === "base64") { + const filename = getRequiredFilenameFromMetadata(block); + return { + type: "file", + file: { + file_data: `data:${block.mime_type ?? ""};base64,${block.data}`, + ...block.metadata?.filename || block.metadata?.name || block.metadata?.title ? { filename } : {} } }; } - if (block.source_type === "base64") return { - type: "file", - file: { - file_data: `data:${block.mime_type ?? ""};base64,${block.data}`, - ...block.metadata?.filename || block.metadata?.name || block.metadata?.title ? { filename: block.metadata?.filename || block.metadata?.name || block.metadata?.title } : {} - } - }; if (block.source_type === "id") return { type: "file", file: { file_id: block.id } @@ -114036,10 +116382,16 @@ const convertStandardContentBlockToCompletionsContentPart = (block) => { } } if (block.type === "file") { - if (block.data) return { - type: "file", - file: { file_data: block.data.toString() } - }; + if (block.data) { + const filename = getRequiredFilenameFromMetadata(block); + return { + type: "file", + file: { + file_data: `data:${block.mimeType};base64,${block.data}`, + filename + } + }; + } if (block.fileId) return { type: "file", file: { file_id: block.fileId } @@ -114237,14 +116589,9 @@ const completions_convertMessagesToCompletionsMessageParams = ({ messages, model content }; if (message.name != null) completionParam.name = message.name; - if (message.additional_kwargs.function_call != null) { - completionParam.function_call = message.additional_kwargs.function_call; - completionParam.content = ""; - } - if (AIMessage.isInstance(message) && !!message.tool_calls?.length) { - completionParam.tool_calls = message.tool_calls.map(convertLangChainToolCallToOpenAI); - completionParam.content = ""; - } else { + if (message.additional_kwargs.function_call != null) completionParam.function_call = message.additional_kwargs.function_call; + if (AIMessage.isInstance(message) && !!message.tool_calls?.length) completionParam.tool_calls = message.tool_calls.map(convertLangChainToolCallToOpenAI); + else { if (message.additional_kwargs.tool_calls != null) completionParam.tool_calls = message.additional_kwargs.tool_calls; if (ToolMessage.isInstance(message) && message.tool_call_id != null) completionParam.tool_call_id = message.tool_call_id; } @@ -114310,6 +116657,7 @@ var ChatOpenAICompletions = class extends BaseChatOpenAI { ...this.modalities || options?.modalities ? { modalities: this.modalities || options?.modalities } : {}, ...this.modelKwargs, prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey, + prompt_cache_retention: options?.promptCacheRetention ?? this.promptCacheRetention, verbosity: options?.verbosity ?? this.verbosity }; if (options?.prediction !== void 0) params.prediction = options.prediction; @@ -114874,6 +117222,10 @@ const convertResponsesMessageToAIMessage = (response) => { const parsed = parseCustomToolCall(item); if (parsed) tool_calls.push(parsed); else invalid_tool_calls.push(makeInvalidToolCall(item, "Malformed custom tool call")); + } else if (item.type === "computer_call") { + const parsed = parseComputerCall(item); + if (parsed) tool_calls.push(parsed); + else invalid_tool_calls.push(makeInvalidToolCall(item, "Malformed computer call")); } else { additional_kwargs.tool_outputs ??= []; additional_kwargs.tool_outputs.push(item); @@ -115043,10 +117395,18 @@ const convertResponsesDeltaToChatGenerationChunk = (event) => { index: event.output_index }); additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY] = { [event.item.call_id]: event.item.id }; + } else if (event.type === "response.output_item.done" && event.item.type === "computer_call") { + tool_call_chunks.push({ + type: "tool_call_chunk", + name: "computer_use", + args: JSON.stringify({ action: event.item.action }), + id: event.item.call_id, + index: event.output_index + }); + additional_kwargs.tool_outputs = [event.item]; } else if (event.type === "response.output_item.done" && [ "web_search_call", "file_search_call", - "computer_call", "code_interpreter_call", "mcp_call", "mcp_list_tools", @@ -115224,7 +117584,7 @@ const convertStandardContentMessageToResponsesInput = (message) => { return void 0; }; const resolveFileItem = (block) => { - const filename = block.metadata?.filename ?? block.metadata?.name ?? block.metadata?.title; + const filename = getRequiredFilenameFromMetadata(block); if (block.fileId && typeof filename === "string") return { type: "input_file", file_id: block.fileId, @@ -115422,20 +117782,35 @@ const convertMessagesToResponsesInput = ({ messages, zdrEnabled, model }) => { if (additional_kwargs?.type === "computer_call_output") { const output = (() => { if (typeof toolMessage.content === "string") return { - type: "computer_screenshot", + type: "input_image", image_url: toolMessage.content }; if (Array.isArray(toolMessage.content)) { + /** + * Check for input_image type first (computer-use-preview format) + */ + const inputImage = toolMessage.content.find((i) => i.type === "input_image"); + if (inputImage) return inputImage; + /** + * Check for computer_screenshot type (legacy format) + */ const oaiScreenshot = toolMessage.content.find((i) => i.type === "computer_screenshot"); if (oaiScreenshot) return oaiScreenshot; + /** + * Convert image_url content block to input_image format + */ const lcImage = toolMessage.content.find((i) => i.type === "image_url"); if (lcImage) return { - type: "computer_screenshot", + type: "input_image", image_url: typeof lcImage.image_url === "string" ? lcImage.image_url : lcImage.image_url.url }; } throw new Error("Invalid computer call output"); })(); + /** + * Cast needed because OpenAI SDK types don't yet include input_image + * for computer-use-preview model output format + */ return { type: "computer_call_output", output, @@ -115499,6 +117874,12 @@ const convertMessagesToResponsesInput = ({ messages, zdrEnabled, model }) => { input: toolCall.args.input, name: toolCall.name }; + if (isComputerToolCall(toolCall)) return { + type: "computer_call", + id: toolCall.call_id, + call_id: toolCall.id ?? "", + action: toolCall.args.action + }; return { type: "function_call", name: toolCall.name, @@ -115600,7 +117981,7 @@ var ChatOpenAIResponses = class extends BaseChatOpenAI { invocationParams(options) { let strict; if (options?.strict !== void 0) strict = options.strict; - else if (this.supportsStrictToolCalling !== void 0) strict = this.supportsStrictToolCalling; + if (strict === void 0 && this.supportsStrictToolCalling !== void 0) strict = this.supportsStrictToolCalling; const params = { model: this.model, temperature: this.temperature, @@ -115657,6 +118038,7 @@ var ChatOpenAIResponses = class extends BaseChatOpenAI { parallel_tool_calls: options?.parallel_tool_calls, max_output_tokens: this.maxTokens === -1 ? void 0 : this.maxTokens, prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey, + prompt_cache_retention: options?.promptCacheRetention ?? this.promptCacheRetention, ...this.zdrEnabled ? { store: false } : {}, ...this.modelKwargs }; @@ -115827,6 +118209,7 @@ var AzureChatOpenAIResponses = class extends ChatOpenAIResponses { + //#region src/chat_models/index.ts /** * OpenAI chat model integration. @@ -116393,7 +118776,7 @@ var ChatOpenAI = class ChatOpenAI extends BaseChatOpenAI { const usesBuiltInTools = options?.tools?.some(isBuiltInTool); const hasResponsesOnlyKwargs = options?.previous_response_id != null || options?.text != null || options?.truncation != null || options?.include != null || options?.reasoning?.summary != null || this.reasoning?.summary != null; const hasCustomTools = options?.tools?.some(isOpenAICustomTool) || options?.tools?.some(isCustomTool); - return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs || hasCustomTools; + return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs || hasCustomTools || _modelPrefersResponsesAPI(this.model); } getLsParams(options) { const optionsWithDefaults = this._combineCallOptions(options); @@ -117655,9 +120038,1184 @@ var DallEAPIWrapper = class extends Tool { //#endregion //# sourceMappingURL=dalle.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/webSearch.js +//#region src/tools/webSearch.ts +/** +* Creates a web search tool that allows OpenAI models to search the web +* for up-to-date information before generating a response. +* +* Web search supports three main types: +* 1. **Non-reasoning web search**: Quick lookups where the model passes queries +* directly to the search tool. +* 2. **Agentic search with reasoning models**: The model actively manages the +* search process, analyzing results and deciding whether to keep searching. +* 3. **Deep research**: Extended investigations using models like `o3-deep-research` +* or `gpt-5` with high reasoning effort. +* +* @see {@link https://platform.openai.com/docs/guides/tools-web-search | OpenAI Web Search Documentation} +* @param options - Configuration options for the web search tool +* @returns A web search tool definition to be passed to the OpenAI Responses API +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* +* const model = new ChatOpenAI({ +* model: "gpt-4o", +* }); +* +* // Basic usage +* const response = await model.invoke("What was a positive news story from today?", { +* tools: [tools.webSearch()], +* }); +* +* // With domain filtering +* const filteredResponse = await model.invoke("Latest AI research news", { +* tools: [tools.webSearch({ +* filters: { +* allowedDomains: ["arxiv.org", "nature.com", "science.org"], +* }, +* })], +* }); +* +* // With user location for geographic relevance +* const localResponse = await model.invoke("What are the best restaurants near me?", { +* tools: [tools.webSearch({ +* userLocation: { +* type: "approximate", +* country: "US", +* city: "San Francisco", +* region: "California", +* timezone: "America/Los_Angeles", +* }, +* })], +* }); +* +* // Cache-only mode (no live internet access) +* const cachedResponse = await model.invoke("Find information about OpenAI", { +* tools: [tools.webSearch({ +* externalWebAccess: false, +* })], +* }); +* ``` +*/ +function webSearch(options) { + return { + type: "web_search", + filters: options?.filters?.allowedDomains ? { allowed_domains: options.filters.allowedDomains } : void 0, + user_location: options?.userLocation, + search_context_size: options?.search_context_size + }; +} + +//#endregion + +//# sourceMappingURL=webSearch.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/mcp.js +//#region src/tools/mcp.ts +/** +* Converts a McpToolFilter to the API format. +*/ +function convertToolFilter(filter) { + return { + tool_names: filter.toolNames, + read_only: filter.readOnly + }; +} +/** +* Converts allowed_tools option to API format. +*/ +function convertAllowedTools(allowedTools) { + if (!allowedTools) return void 0; + if (Array.isArray(allowedTools)) return allowedTools; + return convertToolFilter(allowedTools); +} +/** +* Converts require_approval option to API format. +*/ +function convertRequireApproval(requireApproval) { + if (!requireApproval) return void 0; + if (typeof requireApproval === "string") return requireApproval; + return { + always: requireApproval.always ? convertToolFilter(requireApproval.always) : void 0, + never: requireApproval.never ? convertToolFilter(requireApproval.never) : void 0 + }; +} +function mcp(options) { + const baseConfig = { + type: "mcp", + server_label: options.serverLabel, + allowed_tools: convertAllowedTools(options.allowedTools), + authorization: options.authorization, + headers: options.headers, + require_approval: convertRequireApproval(options.requireApproval), + server_description: options.serverDescription + }; + if ("serverUrl" in options) return { + ...baseConfig, + server_url: options.serverUrl + }; + return { + ...baseConfig, + connector_id: options.connectorId + }; +} + +//#endregion + +//# sourceMappingURL=mcp.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/codeInterpreter.js +//#region src/tools/codeInterpreter.ts +/** +* Converts container options to the API format. +*/ +function convertContainer(container) { + if (typeof container === "string") return container; + return { + type: "auto", + file_ids: container?.fileIds, + memory_limit: container?.memoryLimit + }; +} +/** +* Creates a Code Interpreter tool that allows models to write and run Python code +* in a sandboxed environment to solve complex problems. +* +* Use Code Interpreter for: +* - **Data analysis**: Processing files with diverse data and formatting +* - **File generation**: Creating files with data and images of graphs +* - **Iterative coding**: Writing and running code iteratively to solve problems +* - **Visual intelligence**: Cropping, zooming, rotating, and transforming images +* +* The tool runs in a container, which is a fully sandboxed virtual machine. +* Containers can be created automatically (auto mode) or explicitly via the +* `/v1/containers` endpoint. +* +* @see {@link https://platform.openai.com/docs/guides/tools-code-interpreter | OpenAI Code Interpreter Documentation} +* +* @param options - Configuration options for the Code Interpreter tool +* @returns A Code Interpreter tool definition to be passed to the OpenAI Responses API +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* +* const model = new ChatOpenAI({ model: "gpt-4.1" }); +* +* // Basic usage with auto container (default 1GB memory) +* const response = await model.invoke( +* "Solve the equation 3x + 11 = 14", +* { tools: [tools.codeInterpreter()] } +* ); +* +* // With increased memory limit for larger computations +* const response = await model.invoke( +* "Analyze this large dataset and create visualizations", +* { +* tools: [tools.codeInterpreter({ +* container: { memoryLimit: "4g" } +* })] +* } +* ); +* +* // With specific files available to the code +* const response = await model.invoke( +* "Process the uploaded CSV file", +* { +* tools: [tools.codeInterpreter({ +* container: { +* memoryLimit: "4g", +* fileIds: ["file-abc123", "file-def456"] +* } +* })] +* } +* ); +* +* // Using an explicit container ID (created via /v1/containers) +* const response = await model.invoke( +* "Continue working with the data", +* { +* tools: [tools.codeInterpreter({ +* container: "cntr_abc123" +* })] +* } +* ); +* ``` +* +* @remarks +* - Containers expire after 20 minutes of inactivity +* - While called "Code Interpreter", the model knows it as the "python tool" +* - For explicit prompting, ask for "the python tool" in your prompts +* - Files in model input are automatically uploaded to the container +* - Generated files are returned as `container_file_citation` annotations +*/ +function codeInterpreter(options) { + return { + type: "code_interpreter", + container: convertContainer(options?.container) + }; +} + +//#endregion + +//# sourceMappingURL=codeInterpreter.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/fileSearch.js +//#region src/tools/fileSearch.ts +/** +* Converts ranking options to the API format. +*/ +function convertRankingOptions(options) { + if (!options) return void 0; + return { + ranker: options.ranker, + score_threshold: options.scoreThreshold, + hybrid_search: options.hybridSearch ? { + embedding_weight: options.hybridSearch.embeddingWeight, + text_weight: options.hybridSearch.textWeight + } : void 0 + }; +} +/** +* Creates a File Search tool that allows models to search your files +* for relevant information using semantic and keyword search. +* +* File Search enables models to retrieve information from a knowledge base +* of previously uploaded files stored in vector stores. This is a hosted tool +* managed by OpenAI - you don't need to implement the search execution yourself. +* +* **Prerequisites**: Before using File Search, you must: +* 1. Upload files to the File API with `purpose: "assistants"` +* 2. Create a vector store +* 3. Add files to the vector store +* +* @see {@link https://platform.openai.com/docs/guides/tools-file-search | OpenAI File Search Documentation} +* +* @param options - Configuration options for the File Search tool +* @returns A File Search tool definition to be passed to the OpenAI Responses API +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* +* const model = new ChatOpenAI({ model: "gpt-4.1" }); +* +* // Basic usage with a vector store +* const response = await model.invoke( +* "What is deep research by OpenAI?", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123"] +* })] +* } +* ); +* +* // Limit the number of results for lower latency +* const response = await model.invoke( +* "Find information about pricing", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123"], +* maxNumResults: 5 +* })] +* } +* ); +* +* // With metadata filtering +* const response = await model.invoke( +* "Find recent blog posts about AI", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123"], +* filters: { +* type: "eq", +* key: "category", +* value: "blog" +* } +* })] +* } +* ); +* +* // With compound filters (AND/OR) +* const response = await model.invoke( +* "Find technical docs from 2024", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123"], +* filters: { +* type: "and", +* filters: [ +* { type: "eq", key: "category", value: "technical" }, +* { type: "gte", key: "year", value: 2024 } +* ] +* } +* })] +* } +* ); +* +* // With ranking options for more relevant results +* const response = await model.invoke( +* "Find the most relevant information", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123"], +* rankingOptions: { +* scoreThreshold: 0.8, +* ranker: "auto" +* } +* })] +* } +* ); +* +* // Search multiple vector stores +* const response = await model.invoke( +* "Search across all knowledge bases", +* { +* tools: [tools.fileSearch({ +* vectorStoreIds: ["vs_abc123", "vs_def456"] +* })] +* } +* ); +* ``` +* +* @remarks +* - Vector stores must be created and populated before using this tool +* - The tool returns file citations in the response annotations +* - Use `include: ["file_search_call.results"]` in the API call to get search results +* - Supported file types include PDF, DOCX, TXT, MD, and many code file formats +*/ +function fileSearch(options) { + return { + type: "file_search", + vector_store_ids: options.vectorStoreIds, + max_num_results: options.maxNumResults, + filters: options.filters, + ranking_options: convertRankingOptions(options.rankingOptions) + }; +} + +//#endregion + +//# sourceMappingURL=fileSearch.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/imageGeneration.js +//#region src/tools/imageGeneration.ts +/** +* Converts input mask options to the API format. +*/ +function convertInputImageMask(mask) { + if (!mask) return void 0; + return { + image_url: mask.imageUrl, + file_id: mask.fileId + }; +} +/** +* Creates an Image Generation tool that allows models to generate or edit images +* using text prompts and optional image inputs. +* +* The image generation tool leverages the GPT Image model and automatically +* optimizes text inputs for improved performance. When included in a request, +* the model can decide when and how to generate images as part of the conversation. +* +* **Key Features**: +* - Generate images from text descriptions +* - Edit existing images with text instructions +* - Multi-turn image editing by referencing previous responses +* - Configurable output options (size, quality, format) +* - Streaming support for partial image generation +* +* **Prompting Tips**: +* - Use terms like "draw" or "edit" in your prompt for best results +* - For combining images, say "edit the first image by adding this element" instead of "combine" +* +* @see {@link https://platform.openai.com/docs/guides/tools-image-generation | OpenAI Image Generation Documentation} +* +* @param options - Configuration options for the Image Generation tool +* @returns An Image Generation tool definition to be passed to the OpenAI Responses API +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* +* const model = new ChatOpenAI({ model: "gpt-4o" }); +* +* // Basic usage - generate an image +* const response = await model.invoke( +* "Generate an image of a gray tabby cat hugging an otter with an orange scarf", +* { tools: [tools.imageGeneration()] } +* ); +* +* // Access the generated image +* const imageData = response.additional_kwargs.tool_outputs?.find( +* (output) => output.type === "image_generation_call" +* ); +* if (imageData?.result) { +* // imageData.result contains the base64-encoded image +* const fs = await import("fs"); +* fs.writeFileSync("output.png", Buffer.from(imageData.result, "base64")); +* } +* +* // With custom options +* const response = await model.invoke( +* "Draw a beautiful sunset over mountains", +* { +* tools: [tools.imageGeneration({ +* size: "1536x1024", // Landscape format +* quality: "high", // Higher quality output +* outputFormat: "jpeg", // JPEG format +* outputCompression: 90, // 90% compression +* })] +* } +* ); +* +* // With transparent background +* const response = await model.invoke( +* "Create a logo with a transparent background", +* { +* tools: [tools.imageGeneration({ +* background: "transparent", +* outputFormat: "png", +* })] +* } +* ); +* +* // Force the model to use image generation +* const response = await model.invoke( +* "A serene lake at dawn", +* { +* tools: [tools.imageGeneration()], +* tool_choice: { type: "image_generation" }, +* } +* ); +* +* // Enable streaming with partial images +* const response = await model.invoke( +* "Draw a detailed fantasy castle", +* { +* tools: [tools.imageGeneration({ +* partialImages: 2, // Get 2 partial images during generation +* })] +* } +* ); +* ``` +* +* @remarks +* - Supported models: gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, o3 +* - The image generation process always uses `gpt-image-1` model internally +* - The model will automatically revise prompts for improved performance +* - Access the revised prompt via `revised_prompt` field in the output +* - Multi-turn editing is supported by passing previous response messages +*/ +function imageGeneration(options) { + return { + type: "image_generation", + background: options?.background, + input_fidelity: options?.inputFidelity, + input_image_mask: convertInputImageMask(options?.inputImageMask), + model: options?.model, + moderation: options?.moderation, + output_compression: options?.outputCompression, + output_format: options?.outputFormat, + partial_images: options?.partialImages, + quality: options?.quality, + size: options?.size + }; +} + +//#endregion + +//# sourceMappingURL=imageGeneration.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/computerUse.js + + + + +//#region src/tools/computerUse.ts +const ComputerUseScreenshotActionSchema = object({ type: literal("screenshot") }); +const ComputerUseClickActionSchema = object({ + type: literal("click"), + x: schemas_number(), + y: schemas_number(), + button: schemas_enum([ + "left", + "right", + "wheel", + "back", + "forward" + ]).default("left") +}); +const ComputerUseDoubleClickActionSchema = object({ + type: literal("double_click"), + x: schemas_number(), + y: schemas_number(), + button: schemas_enum([ + "left", + "right", + "wheel", + "back", + "forward" + ]).default("left") +}); +const ComputerUseDragActionSchema = object({ + type: literal("drag"), + path: array(object({ + x: schemas_number(), + y: schemas_number() + })) +}); +const ComputerUseKeypressActionSchema = object({ + type: literal("keypress"), + keys: array(schemas_string()) +}); +const ComputerUseMoveActionSchema = object({ + type: literal("move"), + x: schemas_number(), + y: schemas_number() +}); +const ComputerUseScrollActionSchema = object({ + type: literal("scroll"), + x: schemas_number(), + y: schemas_number(), + scroll_x: schemas_number(), + scroll_y: schemas_number() +}); +const ComputerUseTypeActionSchema = object({ + type: literal("type"), + text: schemas_string() +}); +const ComputerUseWaitActionSchema = object({ + type: literal("wait"), + duration: schemas_number().optional() +}); +const ComputerUseActionUnionSchema = discriminatedUnion("type", [ + ComputerUseScreenshotActionSchema, + ComputerUseClickActionSchema, + ComputerUseDoubleClickActionSchema, + ComputerUseDragActionSchema, + ComputerUseKeypressActionSchema, + ComputerUseMoveActionSchema, + ComputerUseScrollActionSchema, + ComputerUseTypeActionSchema, + ComputerUseWaitActionSchema +]); +const ComputerUseActionSchema = object({ action: ComputerUseActionUnionSchema }); +const computerUse_TOOL_NAME = "computer_use"; +/** +* Creates a Computer Use tool that allows models to control computer interfaces +* and perform tasks by simulating mouse clicks, keyboard input, scrolling, and more. +* +* **Computer Use** is a practical application of OpenAI's Computer-Using Agent (CUA) +* model (`computer-use-preview`), which combines vision capabilities with advanced +* reasoning to simulate controlling computer interfaces. +* +* **How it works**: +* The tool operates in a continuous loop: +* 1. Model sends computer actions (click, type, scroll, etc.) +* 2. Your code executes these actions in a controlled environment +* 3. You capture a screenshot of the result +* 4. Send the screenshot back to the model +* 5. Repeat until the task is complete +* +* **Important**: Computer use is in beta and requires careful consideration: +* - Use in sandboxed environments only +* - Do not use for high-stakes or authenticated tasks +* - Always implement human-in-the-loop for important decisions +* - Handle safety checks appropriately +* +* @see {@link https://platform.openai.com/docs/guides/tools-computer-use | OpenAI Computer Use Documentation} +* +* @param options - Configuration options for the Computer Use tool +* @returns A Computer Use tool that can be passed to `bindTools` +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* +* const model = new ChatOpenAI({ model: "computer-use-preview" }); +* +* // With execute callback for automatic action handling +* const computer = tools.computerUse({ +* displayWidth: 1024, +* displayHeight: 768, +* environment: "browser", +* execute: async (action) => { +* if (action.type === "screenshot") { +* return captureScreenshot(); +* } +* if (action.type === "click") { +* await page.mouse.click(action.x, action.y, { button: action.button }); +* return captureScreenshot(); +* } +* if (action.type === "type") { +* await page.keyboard.type(action.text); +* return captureScreenshot(); +* } +* // Handle other actions... +* return captureScreenshot(); +* }, +* }); +* +* const llmWithComputer = model.bindTools([computer]); +* const response = await llmWithComputer.invoke( +* "Check the latest news on bing.com" +* ); +* ``` +* +* @example +* ```typescript +* // Without execute callback (manual action handling) +* const computer = tools.computerUse({ +* displayWidth: 1024, +* displayHeight: 768, +* environment: "browser", +* }); +* +* const response = await model.invoke("Check the news", { +* tools: [computer], +* }); +* +* // Access the computer call from the response +* const computerCall = response.additional_kwargs.tool_outputs?.find( +* (output) => output.type === "computer_call" +* ); +* if (computerCall) { +* console.log("Action to execute:", computerCall.action); +* // Execute the action manually, then send back a screenshot +* } +* ``` +* +* @example +* ```typescript +* // For macOS desktop automation with Docker +* const computer = tools.computerUse({ +* displayWidth: 1920, +* displayHeight: 1080, +* environment: "mac", +* execute: async (action) => { +* if (action.type === "click") { +* await dockerExec( +* `DISPLAY=:99 xdotool mousemove ${action.x} ${action.y} click 1`, +* containerName +* ); +* } +* // Capture screenshot from container +* return await getDockerScreenshot(containerName); +* }, +* }); +* ``` +* +* @remarks +* - Only available through the Responses API (not Chat Completions) +* - Requires `computer-use-preview` model +* - Actions include: click, double_click, drag, keypress, move, screenshot, scroll, type, wait +* - Safety checks may be returned that require acknowledgment before proceeding +* - Use `truncation: "auto"` parameter when making requests +* - Recommended to use with `reasoning.summary` for debugging +*/ +function computerUse(options) { + const computerTool = tool(async (input, runtime) => { + /** + * get computer_use call id from runtime + */ + const aiMessage = runtime.state?.messages.at(-1); + const computerToolCall = aiMessage?.tool_calls?.find((tc) => tc.name === "computer_use"); + const computerToolCallId = computerToolCall?.id; + if (!computerToolCallId) throw new Error("Computer use call id not found"); + const result = await options.execute(input.action, runtime); + /** + * make sure {@link ToolMessage} is returned with the correct additional kwargs + */ + if (typeof result === "string") return new ToolMessage({ + content: result, + tool_call_id: computerToolCallId, + additional_kwargs: { type: "computer_call_output" } + }); + /** + * make sure {@link ToolMessage} is returned with the correct additional kwargs + */ + return new ToolMessage({ + ...result, + tool_call_id: computerToolCallId, + additional_kwargs: { + type: "computer_call_output", + ...result.additional_kwargs + } + }); + }, { + name: computerUse_TOOL_NAME, + description: "Control a computer interface by executing mouse clicks, keyboard input, scrolling, and other actions.", + schema: ComputerUseActionSchema + }); + computerTool.extras = { + ...computerTool.extras ?? {}, + providerToolDefinition: { + type: "computer_use_preview", + display_width: options.displayWidth, + display_height: options.displayHeight, + environment: options.environment + } + }; + /** + * return as typed {@link DynamicStructuredTool} so we don't get any type + * errors like "can't export tool without reference" + */ + return computerTool; +} + +//#endregion + +//# sourceMappingURL=computerUse.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/localShell.js + + + +//#region src/tools/localShell.ts +const LocalShellExecActionSchema = object({ + type: literal("exec"), + command: array(schemas_string()), + env: record(schemas_string(), schemas_string()).optional(), + working_directory: schemas_string().optional(), + timeout_ms: schemas_number().optional(), + user: schemas_string().optional() +}); +const LocalShellActionSchema = discriminatedUnion("type", [LocalShellExecActionSchema]); +const localShell_TOOL_NAME = "local_shell"; +/** +* Creates a Local Shell tool that allows models to run shell commands locally +* on a machine you provide. Commands are executed inside your own runtime— +* the API only returns the instructions, but does not execute them on OpenAI infrastructure. +* +* **Important**: The local shell tool is designed to work with +* [Codex CLI](https://github.com/openai/codex) and the `codex-mini-latest` model. +* +* **How it works**: +* The tool operates in a continuous loop: +* 1. Model sends shell commands (`local_shell_call` with `exec` action) +* 2. Your code executes the command locally +* 3. You return the output back to the model +* 4. Repeat until the task is complete +* +* **Security Warning**: Running arbitrary shell commands can be dangerous. +* Always sandbox execution or add strict allow/deny-lists before forwarding +* a command to the system shell. +* +* @see {@link https://platform.openai.com/docs/guides/tools-local-shell | OpenAI Local Shell Documentation} +* +* @param options - Optional configuration for the Local Shell tool +* @returns A Local Shell tool that can be passed to `bindTools` +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* import { exec } from "child_process"; +* import { promisify } from "util"; +* +* const execAsync = promisify(exec); +* const model = new ChatOpenAI({ model: "codex-mini-latest" }); +* +* // With execute callback for automatic command handling +* const shell = tools.localShell({ +* execute: async (action) => { +* const { command, env, working_directory, timeout_ms } = action; +* const result = await execAsync(command.join(' '), { +* cwd: working_directory ?? process.cwd(), +* env: { ...process.env, ...env }, +* timeout: timeout_ms ?? undefined, +* }); +* return result.stdout + result.stderr; +* }, +* }); +* +* const llmWithShell = model.bindTools([shell]); +* const response = await llmWithShell.invoke( +* "List files in the current directory" +* ); +* ``` +* +* @example +* ```typescript +* // Without execute callback (manual handling) +* const shell = tools.localShell(); +* +* const response = await model.invoke("List files", { +* tools: [shell], +* }); +* +* // Access the shell call from the response +* const shellCall = response.additional_kwargs.tool_outputs?.find( +* (output) => output.type === "local_shell_call" +* ); +* if (shellCall) { +* console.log("Command to execute:", shellCall.action.command); +* // Execute the command manually, then send back the output +* } +* ``` +* +* @example +* ```typescript +* // Full shell loop example +* async function shellLoop(model, task) { +* let response = await model.invoke(task, { +* tools: [tools.localShell()], +* }); +* +* while (true) { +* const shellCall = response.additional_kwargs.tool_outputs?.find( +* (output) => output.type === "local_shell_call" +* ); +* +* if (!shellCall) break; +* +* // Execute command (with proper sandboxing!) +* const output = await executeCommand(shellCall.action); +* +* // Send output back to model +* response = await model.invoke([ +* response, +* { +* type: "local_shell_call_output", +* id: shellCall.call_id, +* output: output, +* }, +* ], { +* tools: [tools.localShell()], +* }); +* } +* +* return response; +* } +* ``` +* +* @remarks +* - Only available through the Responses API (not Chat Completions) +* - Designed for use with `codex-mini-latest` model +* - Commands are provided as argv tokens in `action.command` +* - Action includes: `command`, `env`, `working_directory`, `timeout_ms`, `user` +* - Always sandbox or validate commands before execution +* - The `timeout_ms` from the model is only a hint—enforce your own limits +*/ +function localShell(options) { + const shellTool = tool(options.execute, { + name: localShell_TOOL_NAME, + description: "Execute shell commands locally on the machine. Commands are provided as argv tokens.", + schema: LocalShellActionSchema + }); + shellTool.extras = { + ...shellTool.extras ?? {}, + providerToolDefinition: { type: "local_shell" } + }; + return shellTool; +} + +//#endregion + +//# sourceMappingURL=localShell.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/shell.js + + + +//#region src/tools/shell.ts +const ShellActionSchema = object({ + commands: array(schemas_string()).describe("Array of shell commands to execute"), + timeout_ms: schemas_number().optional().describe("Optional timeout in milliseconds for the commands"), + max_output_length: schemas_number().optional().describe("Optional maximum number of characters to return from each command") +}); +const shell_TOOL_NAME = "shell"; +/** +* Creates a Shell tool that allows models to run shell commands through your integration. +* +* The shell tool allows the model to interact with your local computer through a controlled +* command-line interface. The model proposes shell commands; your integration executes them +* and returns the outputs. This creates a simple plan-execute loop that lets models inspect +* the system, run utilities, and gather data until they can finish the task. +* +* **Important**: The shell tool is available through the Responses API for use with `GPT-5.1`. +* It is not available on other models, or via the Chat Completions API. +* +* **When to use**: +* - **Automating filesystem or process diagnostics** – For example, "find the largest PDF +* under ~/Documents" or "show running gunicorn processes." +* - **Extending the model's capabilities** – Using built-in UNIX utilities, python runtime +* and other CLIs in your environment. +* - **Running multi-step build and test flows** – Chaining commands like `pip install` and `pytest`. +* - **Complex agentic coding workflows** – Using other tools like `apply_patch` to complete +* workflows that involve complex file operations. +* +* **How it works**: +* The tool operates in a continuous loop: +* 1. Model sends shell commands (`shell_call` with `commands` array) +* 2. Your code executes the commands (can be concurrent) +* 3. You return stdout, stderr, and outcome for each command +* 4. Repeat until the task is complete +* +* **Security Warning**: Running arbitrary shell commands can be dangerous. +* Always sandbox execution or add strict allow/deny-lists before forwarding +* a command to the system shell. +* +* @see {@link https://platform.openai.com/docs/guides/tools-shell | OpenAI Shell Documentation} +* @see {@link https://github.com/openai/codex | Codex CLI} for reference implementation. +* +* @param options - Configuration for the Shell tool +* @returns A Shell tool that can be passed to `bindTools` +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* import { exec } from "child_process/promises"; +* +* const model = new ChatOpenAI({ model: "gpt-5.1" }); +* +* // With execute callback for automatic command handling +* const shellTool = tools.shell({ +* execute: async (action) => { +* const outputs = await Promise.all( +* action.commands.map(async (cmd) => { +* try { +* const { stdout, stderr } = await exec(cmd, { +* timeout: action.timeout_ms ?? undefined, +* }); +* return { +* stdout, +* stderr, +* outcome: { type: "exit" as const, exit_code: 0 }, +* }; +* } catch (error) { +* const timedOut = error.killed && error.signal === "SIGTERM"; +* return { +* stdout: error.stdout ?? "", +* stderr: error.stderr ?? String(error), +* outcome: timedOut +* ? { type: "timeout" as const } +* : { type: "exit" as const, exit_code: error.code ?? 1 }, +* }; +* } +* }) +* ); +* return { +* output: outputs, +* maxOutputLength: action.max_output_length, +* }; +* }, +* }); +* +* const llmWithShell = model.bindTools([shellTool]); +* const response = await llmWithShell.invoke( +* "Find the largest PDF file in ~/Documents" +* ); +* ``` +* +* @example +* ```typescript +* // Full shell loop example +* async function shellLoop(model, task) { +* let response = await model.invoke(task, { +* tools: [tools.shell({ execute: myExecutor })], +* }); +* +* while (true) { +* const shellCall = response.additional_kwargs.tool_outputs?.find( +* (output) => output.type === "shell_call" +* ); +* +* if (!shellCall) break; +* +* // Execute commands (with proper sandboxing!) +* const result = await executeCommands(shellCall.action); +* +* // Send output back to model +* response = await model.invoke([ +* response, +* { +* type: "shell_call_output", +* call_id: shellCall.call_id, +* output: result.output, +* max_output_length: result.maxOutputLength, +* }, +* ], { +* tools: [tools.shell({ execute: myExecutor })], +* }); +* } +* +* return response; +* } +* ``` +* +* @remarks +* - Only available through the Responses API (not Chat Completions) +* - Designed for use with `gpt-5.1` model +* - Commands are provided as an array of strings that can be executed concurrently +* - Action includes: `commands`, `timeout_ms`, `max_output_length` +* - Always sandbox or validate commands before execution +* - The `timeout_ms` from the model is only a hint—enforce your own limits +* - If `max_output_length` exists in the action, always pass it back in the output +* - Many CLI tools return non-zero exit codes for warnings; still capture stdout/stderr +*/ +function shell(options) { + const executeWrapper = async (action) => { + const result = await options.execute(action); + return JSON.stringify({ + output: result.output, + max_output_length: result.maxOutputLength + }); + }; + const shellTool = tool(executeWrapper, { + name: shell_TOOL_NAME, + description: "Execute shell commands in a managed environment. Commands can be run concurrently.", + schema: ShellActionSchema + }); + shellTool.extras = { + ...shellTool.extras ?? {}, + providerToolDefinition: { type: "shell" } + }; + return shellTool; +} + +//#endregion + +//# sourceMappingURL=shell.js.map +;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/applyPatch.js + + + +//#region src/tools/applyPatch.ts +const ApplyPatchCreateFileOperationSchema = object({ + type: literal("create_file"), + path: schemas_string(), + diff: schemas_string() +}); +const ApplyPatchUpdateFileOperationSchema = object({ + type: literal("update_file"), + path: schemas_string(), + diff: schemas_string() +}); +const ApplyPatchDeleteFileOperationSchema = object({ + type: literal("delete_file"), + path: schemas_string() +}); +const ApplyPatchOperationSchema = discriminatedUnion("type", [ + ApplyPatchCreateFileOperationSchema, + ApplyPatchUpdateFileOperationSchema, + ApplyPatchDeleteFileOperationSchema +]); +const applyPatch_TOOL_NAME = "apply_patch"; +/** +* Creates an Apply Patch tool that allows models to propose structured diffs +* that your integration applies. This enables iterative, multi-step code +* editing workflows. +* +* **Apply Patch** lets GPT-5.1 create, update, and delete files in your codebase +* using structured diffs. Instead of just suggesting edits, the model emits +* patch operations that your application applies and then reports back on. +* +* **When to use**: +* - **Multi-file refactors** – Rename symbols, extract helpers, or reorganize modules +* - **Bug fixes** – Have the model both diagnose issues and emit precise patches +* - **Tests & docs generation** – Create new test files, fixtures, and documentation +* - **Migrations & mechanical edits** – Apply repetitive, structured updates +* +* **How it works**: +* The tool operates in a continuous loop: +* 1. Model sends patch operations (`apply_patch_call` with operation type) +* 2. Your code applies the patch to your working directory or repo +* 3. You return success/failure status and optional output +* 4. Repeat until the task is complete +* +* **Security Warning**: Applying patches can modify files in your codebase. +* Always validate paths, implement backups, and consider sandboxing. +* +* @see {@link https://platform.openai.com/docs/guides/tools-apply-patch | OpenAI Apply Patch Documentation} +* +* @param options - Configuration options for the Apply Patch tool +* @returns An Apply Patch tool that can be passed to `bindTools` +* +* @example +* ```typescript +* import { ChatOpenAI, tools } from "@langchain/openai"; +* import { applyDiff } from "@openai/agents"; +* import * as fs from "fs/promises"; +* +* const model = new ChatOpenAI({ model: "gpt-5.1" }); +* +* // With execute callback for automatic patch handling +* const patchTool = tools.applyPatch({ +* execute: async (operation) => { +* if (operation.type === "create_file") { +* const content = applyDiff("", operation.diff, "create"); +* await fs.writeFile(operation.path, content); +* return `Created ${operation.path}`; +* } +* if (operation.type === "update_file") { +* const current = await fs.readFile(operation.path, "utf-8"); +* const newContent = applyDiff(current, operation.diff); +* await fs.writeFile(operation.path, newContent); +* return `Updated ${operation.path}`; +* } +* if (operation.type === "delete_file") { +* await fs.unlink(operation.path); +* return `Deleted ${operation.path}`; +* } +* return "Unknown operation type"; +* }, +* }); +* +* const llmWithPatch = model.bindTools([patchTool]); +* const response = await llmWithPatch.invoke( +* "Rename the fib() function to fibonacci() in lib/fib.py" +* ); +* ``` +* +* @remarks +* - Only available through the Responses API (not Chat Completions) +* - Designed for use with `gpt-5.1` model +* - Operations include: `create_file`, `update_file`, `delete_file` +* - Patches use V4A diff format for updates +* - Always validate paths to prevent directory traversal attacks +* - Consider backing up files before applying patches +* - Implement "all-or-nothing" semantics if atomicity is required +*/ +function applyPatch_applyPatch(options) { + const patchTool = tool(options.execute, { + name: applyPatch_TOOL_NAME, + description: "Apply structured diffs to create, update, or delete files in the codebase.", + schema: ApplyPatchOperationSchema + }); + patchTool.extras = { + ...patchTool.extras ?? {}, + providerToolDefinition: { type: "apply_patch" } + }; + return patchTool; +} + +//#endregion + +//# sourceMappingURL=applyPatch.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/index.js + + + + + + + + + +//#region src/tools/index.ts +const tools_tools = { + webSearch: webSearch, + mcp: mcp, + codeInterpreter: codeInterpreter, + fileSearch: fileSearch, + imageGeneration: imageGeneration, + computerUse: computerUse, + localShell: localShell, + shell: shell, + applyPatch: applyPatch_applyPatch +}; + +//#endregion + +//# sourceMappingURL=index.js.map ;// CONCATENATED MODULE: ./node_modules/@langchain/openai/dist/tools/custom.js @@ -117917,10 +121475,8 @@ const _FUNCTION_CALL_THOUGHT_SIGNATURES_MAP_KEY = "__gemini_function_call_though const DUMMY_SIGNATURE = "ErYCCrMCAdHtim9kOoOkrPiCNVsmlpMIKd7ZMxgiFbVQOkgp7nlLcDMzVsZwIzvuT7nQROivoXA72ccC2lSDvR0Gh7dkWaGuj7ctv6t7ZceHnecx0QYa+ix8tYpRfjhyWozQ49lWiws6+YGjCt10KRTyWsZ2h6O7iHTYJwKIRwGUHRKy/qK/6kFxJm5ML00gLq4D8s5Z6DBpp2ZlR+uF4G8jJgeWQgyHWVdx2wGYElaceVAc66tZdPQRdOHpWtgYSI1YdaXgVI8KHY3/EfNc2YqqMIulvkDBAnuMhkAjV9xmBa54Tq+ih3Im4+r3DzqhGqYdsSkhS0kZMwte4Hjs65dZzCw9lANxIqYi1DJ639WNPYihp/DCJCos7o+/EeSPJaio5sgWDyUnMGkY1atsJZ+m7pj7DD5tvQ=="; const common_iife = (fn) => fn(); function getMessageAuthor(message) { - const type = message._getType(); if (ChatMessage.isInstance(message)) return message.role; - if (type === "tool") return type; - return message.name ?? type; + return message.type; } /** * Maps a message type to a Google Generative AI chat author. @@ -118136,7 +121692,7 @@ function mapGenerateContentResultToChatResult(response, extra) { }; const [candidate] = response.candidates; const { content: candidateContent,...generationInfo } = candidate; - const functionCalls = candidateContent.parts.reduce((acc, p) => { + const functionCalls = candidateContent.parts?.reduce((acc, p) => { if ("functionCall" in p && p.functionCall) acc.push({ ...p, id: "id" in p.functionCall && typeof p.functionCall.id === "string" ? p.functionCall.id : esm_v4() @@ -118218,7 +121774,7 @@ function convertResponseContentToChatGenerationChunk(response, extra) { if (!response.candidates || response.candidates.length === 0) return null; const [candidate] = response.candidates; const { content: candidateContent,...generationInfo } = candidate; - const functionCalls = candidateContent.parts.reduce((acc, p) => { + const functionCalls = candidateContent.parts?.reduce((acc, p) => { if ("functionCall" in p && p.functionCall) acc.push({ ...p, id: "id" in p.functionCall && typeof p.functionCall.id === "string" ? p.functionCall.id : esm_v4() @@ -120787,7 +124343,8 @@ var ChatGoogleGenerativeAI = class extends BaseChatModel { } }, { apiVersion: fields.apiVersion, - baseUrl: fields.baseUrl + baseUrl: fields.baseUrl, + customHeaders: fields.customHeaders }); this.streamUsage = fields.streamUsage ?? this.streamUsage; } @@ -121144,10 +124701,46 @@ class GoogleProvider { } } +;// CONCATENATED MODULE: ./src/providers/zhipu.provider.ts + +/** + * Zhipu AI (智谱AI) provider implementation + * Uses Anthropic-compatible API endpoint + * Docs: https://docs.z.ai/ + */ +class ZhipuProvider { + name = 'zhipu'; + apiKey; + baseUrl = 'https://api.z.ai/api/anthropic'; + constructor(apiKey) { + this.apiKey = apiKey || process.env.ZHIPU_API_KEY || ''; + } + isConfigured() { + return !!this.apiKey; + } + getDefaultModel() { + // GLM-4.7 is mapped to claude-sonnet-4-20250514 in Zhipu's Anthropic-compatible API + return 'claude-sonnet-4-20250514'; + } + getChatModel(config = {}) { + if (!this.isConfigured()) { + throw new Error('Zhipu API key is not configured. Set ZHIPU_API_KEY environment variable.'); + } + return new ChatAnthropic({ + anthropicApiKey: this.apiKey, + anthropicApiUrl: this.baseUrl, + modelName: config.model || this.getDefaultModel(), + temperature: config.temperature ?? 0.2, + maxTokens: config.maxTokens ?? 4000, + }); + } +} + ;// CONCATENATED MODULE: ./src/providers/provider.factory.ts + /** * Factory for creating LLM providers */ @@ -121175,8 +124768,11 @@ class ProviderFactory { case 'google': provider = new GoogleProvider(apiKey); break; + case 'zhipu': + provider = new ZhipuProvider(apiKey); + break; default: - throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google`); + throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google, zhipu`); } // Cache the provider if no specific API key was provided if (!apiKey) { @@ -121228,13 +124824,15 @@ class ProviderFactory { return 'anthropic'; if (normalized === 'gemini') return 'google'; + if (normalized === 'glm' || normalized === 'zhipuai') + return 'zhipu'; return normalized; } /** * Get list of available providers */ static getAvailableProviders() { - return ['anthropic', 'openai', 'google']; + return ['anthropic', 'openai', 'google', 'zhipu']; } } @@ -121245,6 +124843,7 @@ class ProviderFactory { + ;// CONCATENATED MODULE: ./src/agents/pr-analyzer-agent.ts /** * PR Analyzer Agent @@ -121559,9 +125158,9 @@ async function getPRDiffs(context, ghToken) { const status = f.status === 'added' ? 'new file mode 100644' : f.status === 'removed' ? 'deleted file mode 100644' : ''; const patch = f.patch || ''; - return `diff --git a/${f.filename} b/${f.filename} -${status ? status + '\n' : ''}--- ${f.status === 'added' ? '/dev/null' : 'a/' + f.filename} -+++ ${f.status === 'removed' ? '/dev/null' : 'b/' + f.filename} + return `diff --git a/${f.filename} b/${f.filename} +${status ? status + '\n' : ''}--- ${f.status === 'added' ? '/dev/null' : 'a/' + f.filename} ++++ ${f.status === 'removed' ? '/dev/null' : 'b/' + f.filename} ${patch}`; }).join('\n'); } diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..8f9586e --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/licenses.txt b/dist/licenses.txt index 7febf81..f2cb43d 100644 --- a/dist/licenses.txt +++ b/dist/licenses.txt @@ -108,6 +108,212 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@google/generative-ai +Apache-2.0 + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + @langchain/anthropic MIT MIT License @@ -158,6 +364,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@langchain/google-genai +MIT +MIT License + +Copyright (c) LangChain, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + @langchain/langgraph MIT The MIT License @@ -206,6 +437,31 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +@langchain/openai +MIT +MIT License + +Copyright (c) LangChain, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + @octokit/auth-token MIT The MIT License @@ -743,6 +999,211 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +openai +Apache-2.0 + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2025 OpenAI + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + p-finally MIT The MIT License (MIT) @@ -781,19 +1242,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -p-retry -MIT -MIT License - -Copyright (c) Sindre Sorhus (sindresorhus.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - p-timeout MIT MIT License @@ -807,31 +1255,6 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -retry -MIT -Copyright (c) 2011: -Tim Koschützki (tim@debuggable.com) -Felix Geisendörfer (felix@debuggable.com) - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - semver ISC The ISC License diff --git a/dist/providers/index.d.ts b/dist/providers/index.d.ts index 197c43e..abcb958 100644 --- a/dist/providers/index.d.ts +++ b/dist/providers/index.d.ts @@ -3,3 +3,4 @@ export * from './provider.factory.js'; export * from './anthropic.provider.js'; export * from './openai.provider.js'; export * from './google.provider.js'; +export * from './zhipu.provider.js'; diff --git a/dist/providers/index.js b/dist/providers/index.js index 11dbd8e..3d54524 100644 --- a/dist/providers/index.js +++ b/dist/providers/index.js @@ -3,4 +3,5 @@ export * from './provider.factory.js'; export * from './anthropic.provider.js'; export * from './openai.provider.js'; export * from './google.provider.js'; +export * from './zhipu.provider.js'; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/providers/index.js.map b/dist/providers/index.js.map index 7e81376..8a72121 100644 --- a/dist/providers/index.js.map +++ b/dist/providers/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC"} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"} \ No newline at end of file diff --git a/dist/providers/provider.factory.d.ts b/dist/providers/provider.factory.d.ts index ca4916a..e38f90e 100644 --- a/dist/providers/provider.factory.d.ts +++ b/dist/providers/provider.factory.d.ts @@ -1,6 +1,6 @@ import { ILLMProvider } from './provider.interface.js'; import { BaseChatModel } from '@langchain/core/language_models/chat_models'; -export type SupportedProvider = 'anthropic' | 'openai' | 'google'; +export type SupportedProvider = 'anthropic' | 'openai' | 'google' | 'zhipu'; export interface ProviderOptions { provider?: SupportedProvider; apiKey?: string; diff --git a/dist/providers/provider.factory.js b/dist/providers/provider.factory.js index dd2fde9..4d1a3da 100644 --- a/dist/providers/provider.factory.js +++ b/dist/providers/provider.factory.js @@ -1,6 +1,7 @@ import { AnthropicProvider } from './anthropic.provider.js'; import { OpenAIProvider } from './openai.provider.js'; import { GoogleProvider } from './google.provider.js'; +import { ZhipuProvider } from './zhipu.provider.js'; /** * Factory for creating LLM providers */ @@ -28,8 +29,11 @@ export class ProviderFactory { case 'google': provider = new GoogleProvider(apiKey); break; + case 'zhipu': + provider = new ZhipuProvider(apiKey); + break; default: - throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google`); + throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google, zhipu`); } // Cache the provider if no specific API key was provided if (!apiKey) { @@ -81,13 +85,15 @@ export class ProviderFactory { return 'anthropic'; if (normalized === 'gemini') return 'google'; + if (normalized === 'glm' || normalized === 'zhipuai') + return 'zhipu'; return normalized; } /** * Get list of available providers */ static getAvailableProviders() { - return ['anthropic', 'openai', 'google']; + return ['anthropic', 'openai', 'google', 'zhipu']; } } //# sourceMappingURL=provider.factory.js.map \ No newline at end of file diff --git a/dist/providers/provider.factory.js.map b/dist/providers/provider.factory.js.map index 2926111..5bc47b1 100644 --- a/dist/providers/provider.factory.js.map +++ b/dist/providers/provider.factory.js.map @@ -1 +1 @@ -{"version":3,"file":"provider.factory.js","sourceRoot":"","sources":["../../src/providers/provider.factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"provider.factory.js","sourceRoot":"","sources":["../../src/providers/provider.factory.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/providers/zhipu.provider.d.ts b/dist/providers/zhipu.provider.d.ts new file mode 100644 index 0000000..d46c5af --- /dev/null +++ b/dist/providers/zhipu.provider.d.ts @@ -0,0 +1,16 @@ +import { BaseChatModel } from '@langchain/core/language_models/chat_models'; +import { ILLMProvider, ProviderConfig } from './provider.interface.js'; +/** + * Zhipu AI (智谱AI) provider implementation + * Uses Anthropic-compatible API endpoint + * Docs: https://docs.z.ai/ + */ +export declare class ZhipuProvider implements ILLMProvider { + readonly name = "zhipu"; + private readonly apiKey; + private readonly baseUrl; + constructor(apiKey?: string); + isConfigured(): boolean; + getDefaultModel(): string; + getChatModel(config?: ProviderConfig): BaseChatModel; +} diff --git a/dist/providers/zhipu.provider.js b/dist/providers/zhipu.provider.js new file mode 100644 index 0000000..2d9351b --- /dev/null +++ b/dist/providers/zhipu.provider.js @@ -0,0 +1,34 @@ +import { ChatAnthropic } from '@langchain/anthropic'; +/** + * Zhipu AI (智谱AI) provider implementation + * Uses Anthropic-compatible API endpoint + * Docs: https://docs.z.ai/ + */ +export class ZhipuProvider { + name = 'zhipu'; + apiKey; + baseUrl = 'https://api.z.ai/api/anthropic'; + constructor(apiKey) { + this.apiKey = apiKey || process.env.ZHIPU_API_KEY || ''; + } + isConfigured() { + return !!this.apiKey; + } + getDefaultModel() { + // GLM-4.7 is mapped to claude-sonnet-4-20250514 in Zhipu's Anthropic-compatible API + return 'claude-sonnet-4-20250514'; + } + getChatModel(config = {}) { + if (!this.isConfigured()) { + throw new Error('Zhipu API key is not configured. Set ZHIPU_API_KEY environment variable.'); + } + return new ChatAnthropic({ + anthropicApiKey: this.apiKey, + anthropicApiUrl: this.baseUrl, + modelName: config.model || this.getDefaultModel(), + temperature: config.temperature ?? 0.2, + maxTokens: config.maxTokens ?? 4000, + }); + } +} +//# sourceMappingURL=zhipu.provider.js.map \ No newline at end of file diff --git a/dist/providers/zhipu.provider.js.map b/dist/providers/zhipu.provider.js.map new file mode 100644 index 0000000..3adf977 --- /dev/null +++ b/dist/providers/zhipu.provider.js.map @@ -0,0 +1 @@ +{"version":3,"file":"zhipu.provider.js","sourceRoot":"","sources":["../../src/providers/zhipu.provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACR,IAAI,GAAG,OAAO,CAAC;IACd,MAAM,CAAS;IACf,OAAO,GAAG,gCAAgC,CAAC;IAE5D,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC;IAC1D,CAAC;IAEM,YAAY;QACjB,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC;IAEM,eAAe;QACpB,oFAAoF;QACpF,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAEM,YAAY,CAAC,SAAyB,EAAE;QAC7C,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QAED,OAAO,IAAI,aAAa,CAAC;YACvB,eAAe,EAAE,IAAI,CAAC,MAAM;YAC5B,eAAe,EAAE,IAAI,CAAC,OAAO;YAC7B,SAAS,EAAE,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,eAAe,EAAE;YACjD,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,GAAG;YACtC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;SACpC,CAAC,CAAC;IACL,CAAC;CACF"} \ No newline at end of file diff --git a/dist/types.d.ts b/dist/types.d.ts index a0c746d..50ee2ce 100644 --- a/dist/types.d.ts +++ b/dist/types.d.ts @@ -1,4 +1,4 @@ -export type AIProviderType = 'anthropic' | 'openai' | 'google'; +export type AIProviderType = 'anthropic' | 'openai' | 'google' | 'zhipu'; export interface PRInfo { number: number; title: string; diff --git a/dist/types/issue-tracker.types.d.ts b/dist/types/issue-tracker.types.d.ts new file mode 100644 index 0000000..6f87aeb --- /dev/null +++ b/dist/types/issue-tracker.types.d.ts @@ -0,0 +1,138 @@ +/** + * Generic Issue Tracker Provider Interface + * + * This abstraction allows PR Agent to work with different issue tracking systems + * (Jira, Linear, Azure DevOps, GitHub Issues, etc.) through a unified interface. + * + * MVP: Jira implementation via Atlassian MCP + * Future: Linear, Azure DevOps, GitHub Issues, etc. + */ +/** + * Normalized ticket/issue representation across all providers + */ +export interface IssueTicket { + id: string; + key: string; + url: string; + title: string; + description: string; + type: IssueType; + status: string; + priority: IssuePriority; + assignee?: string; + reporter?: string; + labels: string[]; + components: string[]; + project?: string; + storyPoints?: number; + estimate?: string; + acceptanceCriteria?: string; + acceptanceCriteriaList?: string[]; + testScenarios?: string[]; + linkedTestCases?: string[]; + hasScreenshots: boolean; + hasDiagrams: boolean; + attachmentCount: number; + parentKey?: string; + epicKey?: string; + linkedIssues: LinkedIssue[]; + subtasks: SubtaskInfo[]; + createdAt: string; + updatedAt: string; + rawData?: Record; +} +export type IssueType = 'bug' | 'feature' | 'story' | 'task' | 'epic' | 'subtask' | 'improvement' | 'spike' | 'other'; +export type IssuePriority = 'critical' | 'high' | 'medium' | 'low' | 'none'; +export interface LinkedIssue { + key: string; + type: string; + title: string; + status: string; +} +export interface SubtaskInfo { + key: string; + title: string; + status: string; +} +/** + * Reference to a ticket found in PR metadata + */ +export interface TicketReference { + key: string; + source: 'title' | 'description' | 'branch' | 'commit' | 'manual'; + rawMatch: string; + confidence: number; +} +/** + * Issue tracker provider interface - implement this for each provider + */ +export interface IssueTrackerProvider { + /** + * Provider name for display and configuration + */ + readonly name: string; + /** + * Provider type identifier + */ + readonly type: IssueTrackerType; + /** + * Check if the provider is properly configured and accessible + */ + isConfigured(): boolean; + /** + * Test connection to the provider + */ + testConnection(): Promise; + /** + * Fetch a single ticket by key + */ + getTicket(key: string): Promise; + /** + * Fetch multiple tickets by keys + */ + getTickets(keys: string[]): Promise; + /** + * Extract ticket references from PR metadata + */ + extractTicketReferences(context: TicketExtractionContext): TicketReference[]; + /** + * Search for tickets matching a query + */ + searchTickets?(query: string, limit?: number): Promise; + /** + * Get ticket comments (if supported) + */ + getComments?(ticketKey: string): Promise; +} +export type IssueTrackerType = 'jira' | 'linear' | 'azure-devops' | 'github-issues' | 'gitlab-issues' | 'shortcut' | 'asana' | 'other'; +export interface TicketExtractionContext { + prTitle: string; + prDescription?: string; + branchName?: string; + commitMessages?: string[]; +} +export interface IssueComment { + id: string; + author: string; + body: string; + createdAt: string; +} +/** + * Configuration for issue tracker integration + */ +export interface IssueTrackerConfig { + enabled: boolean; + provider: IssueTrackerType; + providerConfig: Record; + analyzeAcceptanceCriteria: boolean; + rateTicketQuality: boolean; + generateTestSuggestions: boolean; + checkScopeCreep: boolean; + ticketPatterns?: string[]; + includeTicketDetails: boolean; + verbose: boolean; +} +/** + * Factory function type for creating providers + */ +export type IssueTrackerProviderFactory = (config: IssueTrackerConfig) => IssueTrackerProvider | null; diff --git a/dist/types/issue-tracker.types.js b/dist/types/issue-tracker.types.js new file mode 100644 index 0000000..5e61f2a --- /dev/null +++ b/dist/types/issue-tracker.types.js @@ -0,0 +1,11 @@ +/** + * Generic Issue Tracker Provider Interface + * + * This abstraction allows PR Agent to work with different issue tracking systems + * (Jira, Linear, Azure DevOps, GitHub Issues, etc.) through a unified interface. + * + * MVP: Jira implementation via Atlassian MCP + * Future: Linear, Azure DevOps, GitHub Issues, etc. + */ +export {}; +//# sourceMappingURL=issue-tracker.types.js.map \ No newline at end of file diff --git a/dist/types/issue-tracker.types.js.map b/dist/types/issue-tracker.types.js.map new file mode 100644 index 0000000..51d6878 --- /dev/null +++ b/dist/types/issue-tracker.types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"issue-tracker.types.js","sourceRoot":"","sources":["../../src/types/issue-tracker.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"} \ No newline at end of file diff --git a/dist/types/jira.types.d.ts b/dist/types/jira.types.d.ts new file mode 100644 index 0000000..356236e --- /dev/null +++ b/dist/types/jira.types.d.ts @@ -0,0 +1,211 @@ +/** + * Jira types and interfaces for Peer Review Agent + * Provides structures for Jira ticket analysis and acceptance criteria validation + */ +/** + * Jira ticket from the Atlassian API/MCP + */ +export interface JiraTicket { + key: string; + id: string; + summary: string; + description: string; + status: string; + type: JiraTicketType; + priority: string; + assignee?: string; + reporter?: string; + labels: string[]; + components: string[]; + fixVersions: string[]; + storyPoints?: number; + createdAt: string; + updatedAt: string; + acceptanceCriteria?: string; + acceptanceCriteriaItems?: AcceptanceCriteriaItem[]; + testScenarios?: string[]; + testCases?: string[]; + attachments?: JiraAttachment[]; + linkedIssues?: JiraLinkedIssue[]; + comments?: JiraComment[]; + subtasks?: JiraSubtask[]; + parentKey?: string; + epicKey?: string; + customFields?: Record; +} +export type JiraTicketType = 'bug' | 'feature' | 'task' | 'story' | 'epic' | 'subtask' | 'improvement' | 'other'; +export interface AcceptanceCriteriaItem { + id: string; + text: string; + isMet?: boolean; + coverageDetails?: string; + relatedFiles?: string[]; + confidence: number; +} +export interface JiraAttachment { + id: string; + filename: string; + mimeType: string; + url: string; + createdAt: string; + isScreenshot: boolean; +} +export interface JiraLinkedIssue { + key: string; + type: string; + summary: string; + status: string; +} +export interface JiraComment { + id: string; + author: string; + body: string; + createdAt: string; +} +export interface JiraSubtask { + key: string; + summary: string; + status: string; +} +/** + * Ticket quality rating based on best practices + */ +export interface TicketQualityRating { + overallScore: number; + dimensions: { + descriptionClarity: number; + acceptanceCriteriaQuality: number; + testabilityScore: number; + scopeDefinition: number; + technicalContext: number; + visualDocumentation: number; + estimationQuality: number; + completeness: number; + }; + feedback: { + strengths: string[]; + weaknesses: string[]; + suggestions: string[]; + }; + tier: 'excellent' | 'good' | 'adequate' | 'poor' | 'insufficient'; + reviewable: boolean; + reviewabilityReason: string; +} +/** + * Result of acceptance criteria validation against PR changes + */ +export interface AcceptanceCriteriaValidation { + ticketKey: string; + totalCriteria: number; + metCriteria: number; + unmetCriteria: number; + partialCriteria: number; + criteriaAnalysis: CriteriaAnalysisItem[]; + compliancePercentage: number; + gaps: AcceptanceCriteriaGap[]; + suggestedTestScenarios: TestScenarioSuggestion[]; +} +export interface CriteriaAnalysisItem { + criteriaId: string; + criteriaText: string; + status: 'met' | 'unmet' | 'partial' | 'unclear'; + confidence: number; + evidence: string[]; + explanation: string; + relatedFiles: string[]; +} +export interface AcceptanceCriteriaGap { + criteriaText: string; + gapDescription: string; + severity: 'critical' | 'major' | 'minor'; + suggestedAction: string; +} +export interface TestScenarioSuggestion { + scenario: string; + type: 'unit' | 'integration' | 'e2e' | 'manual'; + priority: 'high' | 'medium' | 'low'; + relatedCriteria: string[]; + suggestedApproach: string; +} +/** + * Complete Jira analysis result for a PR + */ +export interface JiraAnalysisResult { + linkedTickets: JiraTicket[]; + primaryTicket?: JiraTicket; + ticketQuality?: TicketQualityRating; + acValidation?: AcceptanceCriteriaValidation; + scopeAnalysis: { + inScope: string[]; + outOfScope: string[]; + scopeCreepRisk: boolean; + scopeCreepDetails?: string; + }; + edgeCaseAnalysis: { + identifiedEdgeCases: string[]; + coveredEdgeCases: string[]; + uncoveredEdgeCases: string[]; + testSuggestions: TestScenarioSuggestion[]; + }; + overallAssessment: { + implementationCompleteness: number; + qualityScore: number; + readyForReview: boolean; + blockers: string[]; + warnings: string[]; + recommendations: string[]; + }; + metrics: { + ticketsCovered: number; + criteriaTotal: number; + criteriaMet: number; + criteriaPartial: number; + criteriaUnmet: number; + testScenariosGenerated: number; + }; +} +/** + * Configuration for Jira integration + */ +export interface JiraConfig { + enabled: boolean; + mcpServerUrl?: string; + instanceUrl?: string; + projectKey?: string; + apiToken?: string; + email?: string; + analyzeAcceptanceCriteria: boolean; + rateTicketQuality: boolean; + generateTestSuggestions: boolean; + checkScopeCreep: boolean; + includeTicketDetailsInOutput: boolean; + verboseOutput: boolean; +} +/** + * Ticket reference extracted from PR title/description/branch + */ +export interface TicketReference { + key: string; + source: 'title' | 'description' | 'branch' | 'commit'; + confidence: number; +} +/** + * Context passed to Jira sub-agent + */ +export interface JiraAnalysisContext { + prTitle: string; + prDescription?: string; + branchName?: string; + commitMessages?: string[]; + diff: string; + files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }>; + prSummary?: string; + prRisks?: string[]; + prComplexity?: number; + config: JiraConfig; +} diff --git a/dist/types/jira.types.js b/dist/types/jira.types.js new file mode 100644 index 0000000..edce57c --- /dev/null +++ b/dist/types/jira.types.js @@ -0,0 +1,6 @@ +/** + * Jira types and interfaces for Peer Review Agent + * Provides structures for Jira ticket analysis and acceptance criteria validation + */ +export {}; +//# sourceMappingURL=jira.types.js.map \ No newline at end of file diff --git a/dist/types/jira.types.js.map b/dist/types/jira.types.js.map new file mode 100644 index 0000000..961155b --- /dev/null +++ b/dist/types/jira.types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jira.types.js","sourceRoot":"","sources":["../../src/types/jira.types.ts"],"names":[],"mappings":"AAAA;;;GAGG"} \ No newline at end of file diff --git a/dist/utils/config-validator.d.ts b/dist/utils/config-validator.d.ts index 2b52001..fa8f610 100644 --- a/dist/utils/config-validator.d.ts +++ b/dist/utils/config-validator.d.ts @@ -11,12 +11,14 @@ export declare const UserConfigSchema: z.ZodObject<{ anthropic: z.ZodOptional; openai: z.ZodOptional; google: z.ZodOptional; + zhipu: z.ZodOptional; }, z.core.$strip>>; ai: z.ZodOptional>; model: z.ZodOptional; temperature: z.ZodOptional; @@ -46,6 +48,24 @@ export declare const UserConfigSchema: z.ZodObject<{ showStrategy: z.ZodOptional; showRecommendations: z.ZodOptional; }, z.core.$strip>>; + peerReview: z.ZodOptional; + provider: z.ZodOptional; + useMcp: z.ZodOptional; + instanceUrl: z.ZodOptional; + email: z.ZodOptional; + apiToken: z.ZodOptional; + defaultProject: z.ZodOptional; + acceptanceCriteriaField: z.ZodOptional; + storyPointsField: z.ZodOptional; + ticketPatterns: z.ZodOptional>; + analyzeAcceptanceCriteria: z.ZodOptional; + rateTicketQuality: z.ZodOptional; + generateTestSuggestions: z.ZodOptional; + checkScopeCreep: z.ZodOptional; + includeTicketDetails: z.ZodOptional; + verbose: z.ZodOptional; + }, z.core.$strip>>; }, z.core.$strip>; /** * Validate configuration object diff --git a/dist/utils/config-validator.js b/dist/utils/config-validator.js index b4ac405..b2f2ef6 100644 --- a/dist/utils/config-validator.js +++ b/dist/utils/config-validator.js @@ -12,11 +12,12 @@ export const UserConfigSchema = z.object({ anthropic: z.string().optional(), openai: z.string().optional(), google: z.string().optional(), + zhipu: z.string().optional(), }) .optional(), ai: z .object({ - provider: z.enum(['anthropic', 'openai', 'google']).optional(), + provider: z.enum(['anthropic', 'openai', 'google', 'zhipu']).optional(), model: z.string().optional(), temperature: z.number().min(0).max(2).optional(), maxTokens: z.number().positive().int().optional(), @@ -62,6 +63,26 @@ export const UserConfigSchema = z.object({ showRecommendations: z.boolean().optional(), }) .optional(), + peerReview: z + .object({ + enabled: z.boolean().optional(), + provider: z.string().optional(), + useMcp: z.boolean().optional(), + instanceUrl: z.string().url().optional(), + email: z.string().email().optional(), + apiToken: z.string().optional(), + defaultProject: z.string().optional(), + acceptanceCriteriaField: z.string().optional(), + storyPointsField: z.string().optional(), + ticketPatterns: z.array(z.string()).optional(), + analyzeAcceptanceCriteria: z.boolean().optional(), + rateTicketQuality: z.boolean().optional(), + generateTestSuggestions: z.boolean().optional(), + checkScopeCreep: z.boolean().optional(), + includeTicketDetails: z.boolean().optional(), + verbose: z.boolean().optional(), + }) + .optional(), }); /** * Validate configuration object diff --git a/dist/utils/config-validator.js.map b/dist/utils/config-validator.js.map index 5322842..7698641 100644 --- a/dist/utils/config-validator.js.map +++ b/dist/utils/config-validator.js.map @@ -1 +1 @@ -{"version":3,"file":"config-validator.js","sourceRoot":"","sources":["../../src/utils/config-validator.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"config-validator.js","sourceRoot":"","sources":["../../src/utils/config-validator.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 36d9467..0475d8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -635,9 +635,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ "ppc64" ], @@ -652,9 +652,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ "arm" ], @@ -669,9 +669,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -686,9 +686,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -703,9 +703,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -720,9 +720,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -737,9 +737,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -754,9 +754,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -771,9 +771,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ "arm" ], @@ -788,9 +788,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -805,9 +805,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ "ia32" ], @@ -822,9 +822,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "cpu": [ "loong64" ], @@ -839,9 +839,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "cpu": [ "mips64el" ], @@ -856,9 +856,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -873,9 +873,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -890,9 +890,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -907,9 +907,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "cpu": [ "x64" ], @@ -924,9 +924,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "cpu": [ "arm64" ], @@ -941,9 +941,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "cpu": [ "x64" ], @@ -958,9 +958,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "cpu": [ "arm64" ], @@ -975,9 +975,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "cpu": [ "x64" ], @@ -992,9 +992,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", "cpu": [ "arm64" ], @@ -1009,9 +1009,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -1026,9 +1026,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "cpu": [ "arm64" ], @@ -1043,9 +1043,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "cpu": [ "ia32" ], @@ -1060,9 +1060,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "cpu": [ "x64" ], @@ -1820,24 +1820,25 @@ } }, "node_modules/@langchain/anthropic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-1.1.3.tgz", - "integrity": "sha512-vJN7Rfl+8lDO+aVFfccDUFxIMwGtf8xHSWvqmeytOB5UBzGxNMRW2Zdu6Gv8vWrKlS6Ca7/8oB1suw1SN0FKGA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-1.3.3.tgz", + "integrity": "sha512-c8K8zEIaD99HxWbAfFD45j6D72viNXX4z4bJjaIEgY9gPtGhJ7YWh80UCa6cHg/cnlEyyUSwLbcl6A5GPVAaPA==", "license": "MIT", "dependencies": { - "@anthropic-ai/sdk": "^0.71.0" + "@anthropic-ai/sdk": "^0.71.0", + "zod": "^3.25.76 || ^4" }, "engines": { "node": ">=20" }, "peerDependencies": { - "@langchain/core": "^1.0.0" + "@langchain/core": "1.1.8" } }, "node_modules/@langchain/anthropic/node_modules/@anthropic-ai/sdk": { - "version": "0.71.0", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.71.0.tgz", - "integrity": "sha512-go1XeWXmpxuiTkosSXpb8tokLk2ZLkIRcXpbWVwJM6gH5OBtHOVsfPfGuqI1oW7RRt4qc59EmYbrXRZ0Ng06Jw==", + "version": "0.71.2", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.71.2.tgz", + "integrity": "sha512-TGNDEUuEstk/DKu0/TflXAEt+p+p/WhTlFzEnoosvbaDU2LTjm42igSdlL0VijrKpWejtOKxX0b8A7uc+XiSAQ==", "license": "MIT", "dependencies": { "json-schema-to-ts": "^3.1.1" @@ -1855,9 +1856,9 @@ } }, "node_modules/@langchain/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.0.tgz", - "integrity": "sha512-yJ6JHcU9psjnQbzRFkXjIdNTA+3074dA+2pHdH8ewvQCSleSk6JcjkCMIb5+NASjeMoi1ZuntlLKVsNqF38YxA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.8.tgz", + "integrity": "sha512-kIUidOgc0ZdyXo4Ahn9Zas+OayqOfk4ZoKPi7XaDipNSWSApc2+QK5BVcjvwtzxstsNOrmXJiJWEN6WPF/MvAw==", "license": "MIT", "dependencies": { "@cfworker/json-schema": "^4.0.2", @@ -1865,10 +1866,9 @@ "camelcase": "6", "decamelize": "1.2.0", "js-tiktoken": "^1.0.12", - "langsmith": "^0.3.64", + "langsmith": ">=0.4.0 <1.0.0", "mustache": "^4.2.0", "p-queue": "^6.6.2", - "p-retry": "^7.0.0", "uuid": "^10.0.0", "zod": "^3.25.76 || ^4" }, @@ -1877,9 +1877,9 @@ } }, "node_modules/@langchain/google-genai": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-2.0.0.tgz", - "integrity": "sha512-PaAWkogQdF+Y2bhhXWXUrC2nO7sTgWLtobBbZl/0V8Aa1F/KG2wrMECie3S17bAdFu/6VmQOuFFrlgSMwQC5KA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-2.1.3.tgz", + "integrity": "sha512-ZdlFK/N10GyU6ATzkM01Sk1rlHBoy36Q/MawGD1SyXdD2lQxZxuQZjFWewj6uzWQ2Nnjj70EvU/kmmHVPn6sfQ==", "license": "MIT", "dependencies": { "@google/generative-ai": "^0.24.0", @@ -1889,7 +1889,7 @@ "node": ">=20" }, "peerDependencies": { - "@langchain/core": "1.1.0" + "@langchain/core": "1.1.8" } }, "node_modules/@langchain/google-genai/node_modules/uuid": { @@ -1906,13 +1906,13 @@ } }, "node_modules/@langchain/langgraph": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.0.2.tgz", - "integrity": "sha512-syxzzWTnmpCL+RhUEvalUeOXFoZy/KkzHa2Da2gKf18zsf9Dkbh3rfnRDrTyUGS1XSTejq07s4rg1qntdEDs2A==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.0.7.tgz", + "integrity": "sha512-EBGqNOWoRiEoLUaeuiXRpUM8/DE6QcwiirNyd97XhezStebBoTTilWH8CUt6S94JRGl5zwfBBRHfzotDnZS/eA==", "license": "MIT", "dependencies": { "@langchain/langgraph-checkpoint": "^1.0.0", - "@langchain/langgraph-sdk": "~1.0.0", + "@langchain/langgraph-sdk": "~1.3.1", "uuid": "^10.0.0" }, "engines": { @@ -1945,9 +1945,9 @@ } }, "node_modules/@langchain/langgraph-sdk": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.0.3.tgz", - "integrity": "sha512-6M4i0XsVO5Eb2vv/3OtIPHW3UqO4zYyXl6AOfS0Jf6d7JiWiSXqzLN8UoS0hpu1ItkcW1j575CRiP/6jn6XXFg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.3.1.tgz", + "integrity": "sha512-zTi7DZHwqtMEzapvm3I1FL4Q7OZsxtq9tTXy6s2gcCxyIU3sphqRboqytqVN7dNHLdTCLb8nXy49QKurs2MIBg==", "license": "MIT", "dependencies": { "p-queue": "^6.6.2", @@ -1971,19 +1971,6 @@ } } }, - "node_modules/@langchain/langgraph-sdk/node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@langchain/langgraph-sdk/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -1998,13 +1985,13 @@ } }, "node_modules/@langchain/openai": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-1.1.3.tgz", - "integrity": "sha512-p+xR+4HRms5Ozjf5miC6U2AYRyNVSTdO7AMBkMYs1Tp6DWHBd+mQ72H8Ogd2dKrPuS5UDJ5dbpI1fS+OrTbgQQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-1.2.0.tgz", + "integrity": "sha512-r2g5Be3Sygw7VTJ89WVM/M94RzYToNTwXf8me1v+kgKxzdHbd/8XPYDFxpXEp3REyPgUrtJs+Oplba9pkTH5ug==", "license": "MIT", "dependencies": { "js-tiktoken": "^1.0.12", - "openai": "^6.9.0", + "openai": "^6.10.0", "zod": "^3.25.76 || ^4" }, "engines": { @@ -2586,6 +2573,18 @@ "@octokit/openapi-types": "^20.0.0" } }, + "node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", @@ -2641,6 +2640,34 @@ "@octokit/openapi-types": "^12.11.0" } }, + "node_modules/@octokit/plugin-throttling": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz", + "integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.1", + "bottleneck": "^2.15.3" + }, + "peerDependencies": { + "@octokit/core": "^3.5.0" + } + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, "node_modules/@octokit/request": { "version": "8.4.1", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", @@ -2760,18 +2787,6 @@ "@octokit/core": ">=6" } }, - "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", - "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, "node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "17.0.0", "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", @@ -3240,9 +3255,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "version": "24.10.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz", + "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==", "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -3749,9 +3764,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.32", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.32.tgz", - "integrity": "sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3765,23 +3780,23 @@ "license": "Apache-2.0" }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -3846,9 +3861,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -3866,11 +3881,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -3982,9 +3997,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001757", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz", - "integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==", + "version": "1.0.30001761", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", + "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", "dev": true, "funding": [ { @@ -4333,18 +4348,18 @@ "license": "MIT" }, "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, "node_modules/create-jest": { @@ -4420,9 +4435,9 @@ } }, "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4545,9 +4560,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.262", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.262.tgz", - "integrity": "sha512-NlAsMteRHek05jRUxUR0a5jpjYq9ykk6+kO0yRaMi5moe7u0fVIOeQ3Y30A8dIiWFBNUoQGi1ljb1i5VtS9WQQ==", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, @@ -4643,9 +4658,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4656,32 +4671,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/escalade": { @@ -4814,39 +4829,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -5000,17 +5015,17 @@ } }, "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "statuses": "2.0.1", + "statuses": "~2.0.2", "unpipe": "~1.0.0" }, "engines": { @@ -5366,19 +5381,23 @@ "license": "MIT" }, "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/human-signals": { @@ -5401,9 +5420,9 @@ } }, "node_modules/iconv-lite": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -5591,18 +5610,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-network-error": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", - "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -6420,12 +6427,12 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "license": "MIT", "dependencies": { - "jws": "^3.2.2", + "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", @@ -6454,9 +6461,9 @@ } }, "node_modules/jwa": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", @@ -6465,12 +6472,12 @@ } }, "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", "license": "MIT", "dependencies": { - "jwa": "^1.4.1", + "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, @@ -6485,14 +6492,14 @@ } }, "node_modules/langchain": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.1.1.tgz", - "integrity": "sha512-z7cOFhLOzbu/lRlIE8GZ5rlfi7obvvHThhMdts1KsUBusJmWLmh1Yik28MHYzJRXclUbqs4u/9D2yNmr36wf0A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.2.3.tgz", + "integrity": "sha512-3k986xJuqg4az53JxV5LnGlOzIXF1d9Kq6Y9s7XjitvzhpsbFuTDV5/kiF4cx3pkNGyw0mUXC4tLz9RxucO0hw==", "license": "MIT", "dependencies": { "@langchain/langgraph": "^1.0.0", "@langchain/langgraph-checkpoint": "^1.0.0", - "langsmith": "~0.3.74", + "langsmith": ">=0.4.0 <1.0.0", "uuid": "^10.0.0", "zod": "^3.25.76 || ^4" }, @@ -6500,13 +6507,13 @@ "node": ">=20" }, "peerDependencies": { - "@langchain/core": "1.1.0" + "@langchain/core": "1.1.8" } }, "node_modules/langsmith": { - "version": "0.3.82", - "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.82.tgz", - "integrity": "sha512-RTcxtRm0zp2lV+pMesMW7EZSsIlqN7OmR2F6sZ/sOFQwmcLVl+VErMPV4VkX4Sycs4/EIAFT5hpr36EqiHoikQ==", + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.4.2.tgz", + "integrity": "sha512-BvBeFgSmR9esl8x5wsiDlALiHKKPybw2wE2Hh6x1tgSZki46H9c9KI9/06LARbPhyyDu/TZU7exfg6fnhdj1Qg==", "license": "MIT", "dependencies": { "@types/uuid": "^10.0.0", @@ -7138,9 +7145,9 @@ } }, "node_modules/openai": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/openai/-/openai-6.9.1.tgz", - "integrity": "sha512-vQ5Rlt0ZgB3/BNmTa7bIijYFhz3YBceAA3Z4JuoMSBftBF9YqFHIEhZakSs+O/Ad7EaoEimZvHxD5ylRjN11Lg==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.15.0.tgz", + "integrity": "sha512-F1Lvs5BoVvmZtzkUEVyh8mDQPPFolq4F+xdsx/DO8Hee8YF3IGAlZqUIsF+DVGhqf4aU0a3bTghsxB6OIsRy1g==", "license": "Apache-2.0", "bin": { "openai": "bin/cli" @@ -7300,18 +7307,16 @@ } }, "node_modules/p-retry": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-7.1.0.tgz", - "integrity": "sha512-xL4PiFRQa/f9L9ZvR4/gUCRNus4N8YX80ku8kv9Jqz+ZokkiZLM0bcvX0gm1F3PDi9SPRsww1BDsTWgE6Y1GLQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", "license": "MIT", "dependencies": { - "is-network-error": "^1.1.0" + "@types/retry": "0.12.0", + "retry": "^0.13.1" }, "engines": { - "node": ">=20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, "node_modules/p-timeout": { @@ -7843,34 +7848,6 @@ "@octokit/openapi-types": "^12.11.0" } }, - "node_modules/probot/node_modules/@octokit/plugin-throttling": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz", - "integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.1", - "bottleneck": "^2.15.3" - }, - "peerDependencies": { - "@octokit/core": "^3.5.0" - } - }, - "node_modules/probot/node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "license": "MIT" - }, - "node_modules/probot/node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, "node_modules/probot/node_modules/@octokit/request": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", @@ -8050,12 +8027,12 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -8080,15 +8057,15 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" @@ -8322,24 +8299,24 @@ } }, "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "range-parser": "~1.2.1", - "statuses": "2.0.1" + "statuses": "~2.0.2" }, "engines": { "node": ">= 0.8.0" @@ -8360,25 +8337,16 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.19.0" + "send": "~0.19.1" }, "engines": { "node": ">= 0.8.0" @@ -8584,9 +8552,9 @@ "license": "MIT" }, "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8795,9 +8763,9 @@ "license": "MIT" }, "node_modules/ts-jest": { - "version": "29.4.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.5.tgz", - "integrity": "sha512-HO3GyiWn2qvTQA4kTgjDcXiMwYQt68a1Y8+JuLRVpdIzm+UOLSHgl/XqR4c6nzJkq5rOkjc02O2I7P7l/Yof0Q==", + "version": "29.4.6", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz", + "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==", "dev": true, "license": "MIT", "dependencies": { @@ -9015,9 +8983,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -9350,9 +9318,9 @@ } }, "node_modules/zod": { - "version": "4.1.13", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", - "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz", + "integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/src/agents/jira-sub-agent.ts b/src/agents/jira-sub-agent.ts new file mode 100644 index 0000000..2f45d95 --- /dev/null +++ b/src/agents/jira-sub-agent.ts @@ -0,0 +1,569 @@ +/** + * Jira Sub-Agent (Peer Review Agent) + * + * This agent acts like an experienced senior developer reviewing a PR. + * It understands not just the code, but the business context from the Jira ticket. + * + * KEY PHILOSOPHY: + * Like a senior developer who deeply knows the codebase, this agent: + * 1. Mentally constructs test scenarios and edge cases (INTERNAL reasoning) + * 2. Uses those mental models to EVALUATE if the implementation is complete + * 3. Checks if changes might break other parts of the application + * 4. Reports FINDINGS, not suggestions for tests + * + * The test scenarios are the agent's internal thought process - like how a + * senior dev thinks "what about when X happens?" while reviewing code. + * The OUTPUT is the conclusion: "This doesn't handle X" or "X case is covered". + */ + +import { ChatPromptTemplate } from '@langchain/core/prompts'; +import { StructuredOutputParser } from '@langchain/core/output_parsers'; +import { z } from 'zod'; +import { IssueTicket } from '../types/issue-tracker.types.js'; +import { BaseLanguageModel } from '@langchain/core/language_models/base'; + +// ========== Output Schemas ========== + +const TicketQualitySchema = z.object({ + overallScore: z.number().min(0).max(100).describe('Overall ticket quality score'), + dimensions: z.object({ + descriptionClarity: z.number().min(0).max(100), + acceptanceCriteriaQuality: z.number().min(0).max(100), + testabilityScore: z.number().min(0).max(100), + scopeDefinition: z.number().min(0).max(100), + technicalContext: z.number().min(0).max(100), + visualDocumentation: z.number().min(0).max(100), + completeness: z.number().min(0).max(100), + }), + feedback: z.object({ + strengths: z.array(z.string()), + weaknesses: z.array(z.string()), + suggestions: z.array(z.string()), + }), + tier: z.enum(['excellent', 'good', 'adequate', 'poor', 'insufficient']), + reviewable: z.boolean(), + reviewabilityReason: z.string(), +}); + +/** + * Acceptance Criteria Validation - focuses on what IS and ISN'T covered + * + * IMPORTANT: The agent DERIVES its own acceptance criteria by analyzing: + * - The full ticket description + * - Any explicit AC field (if present, but don't rely on it) + * - The ticket type (bug vs feature has different expectations) + * - Technical context and constraints mentioned + * + * Like a senior dev who reads the whole ticket and thinks: + * "To implement this properly, I'd need to: 1) do X, 2) handle Y, 3) ensure Z" + */ +const AcceptanceCriteriaValidationSchema = z.object({ + // The agent's derived understanding of what needs to be implemented + derivedRequirements: z.array( + z.object({ + id: z.string(), + requirement: z.string().describe('What the agent derived needs to be done'), + source: z.enum(['description', 'explicit_ac', 'implied', 'ticket_type', 'technical_context']) + .describe('Where this requirement was derived from'), + importance: z.enum(['essential', 'expected', 'nice_to_have']), + }) + ).describe('Requirements derived by analyzing the full ticket, not just AC field'), + + // Analysis of each derived requirement against the PR + criteriaAnalysis: z.array( + z.object({ + criteriaId: z.string().optional(), + criteriaText: z.string(), + status: z.enum(['met', 'unmet', 'partial', 'unclear']), + confidence: z.number().min(0).max(100), + evidence: z.array(z.string()).describe('Code evidence showing coverage or lack thereof'), + explanation: z.string().describe('Why this criteria is/isnt met'), + relatedFiles: z.array(z.string()), + }) + ), + compliancePercentage: z.number().min(0).max(100), + gaps: z.array( + z.object({ + criteriaText: z.string(), + gapDescription: z.string().describe('What specific functionality is missing'), + severity: z.enum(['critical', 'major', 'minor']), + impact: z.string().describe('What will happen if this gap is not addressed'), + }) + ), + // Internal reasoning exposed as findings, not suggestions + missingBehaviors: z.array(z.string()).describe('Behaviors that should exist but dont'), + partialImplementations: z.array(z.string()).describe('Features that are started but incomplete'), +}); + +/** + * Peer Review Analysis - the senior developer's verdict + */ +const PeerReviewAnalysisSchema = z.object({ + implementationCompleteness: z.number().min(0).max(100), + qualityScore: z.number().min(0).max(100), + readyForReview: z.boolean(), + + // Critical findings that block merge + blockers: z.array( + z.object({ + issue: z.string(), + reason: z.string(), + location: z.string().optional().describe('File or component affected'), + }) + ), + + // Important issues that should be fixed + warnings: z.array( + z.object({ + issue: z.string(), + reason: z.string(), + location: z.string().optional(), + }) + ), + + // Nice-to-have improvements + recommendations: z.array(z.string()), + + // Scope analysis + scopeAnalysis: z.object({ + inScope: z.array(z.string()), + outOfScope: z.array(z.string()), + scopeCreepRisk: z.boolean(), + scopeCreepDetails: z.string().optional(), + }), + + // Potential regression analysis - what might break + regressionRisks: z.array( + z.object({ + risk: z.string().describe('What could break'), + affectedArea: z.string().describe('Part of the app that might be affected'), + likelihood: z.enum(['high', 'medium', 'low']), + reasoning: z.string().describe('Why this might happen'), + }) + ), + + // Uncovered scenarios identified during review (findings, not suggestions) + uncoveredScenarios: z.array( + z.object({ + scenario: z.string().describe('A scenario that isnt handled'), + impact: z.enum(['critical', 'major', 'minor']), + relatedCriteria: z.string().optional(), + }) + ), + + // Final verdict + verdict: z.object({ + summary: z.string().describe('One paragraph summary of the review'), + recommendation: z.enum(['approve', 'request_changes', 'needs_discussion']), + confidenceLevel: z.number().min(0).max(100), + }), +}); + +// ========== Types ========== + +export type TicketQualityRating = z.infer; +export type AcceptanceCriteriaValidation = z.infer; +export type PeerReviewAnalysis = z.infer; + +export interface JiraSubAgentResult { + ticketQuality: TicketQualityRating; + acValidation?: AcceptanceCriteriaValidation; + peerReview: PeerReviewAnalysis; +} + +export interface JiraSubAgentContext { + ticket: IssueTicket; + prTitle: string; + prDescription?: string; + diff: string; + files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }>; + prSummary?: string; + prRisks?: string[]; +} + +// ========== Prompts ========== + +const TICKET_QUALITY_PROMPT = `You are an expert at evaluating Jira tickets and user stories. +Analyze the following ticket and rate its quality based on industry best practices. + +TICKET INFORMATION: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} +Description: +{ticketDescription} + +Acceptance Criteria: +{acceptanceCriteria} + +Test Scenarios Defined: {testScenarios} +Has Screenshots/Mockups: {hasScreenshots} +Has Diagrams: {hasDiagrams} +Story Points: {storyPoints} +Labels: {labels} +Components: {components} + +EVALUATION CRITERIA: +1. Description Clarity (0-100): Is the description clear, complete, and unambiguous? +2. Acceptance Criteria Quality (0-100): Are ACs specific, measurable, achievable, and testable (SMART)? +3. Testability Score (0-100): Can this ticket be tested? Are expected behaviors clear? +4. Scope Definition (0-100): Is the scope well-defined and bounded? No scope creep potential? +5. Technical Context (0-100): Are technical requirements, constraints, and dependencies clear? +6. Visual Documentation (0-100): Are there screenshots, mockups, or diagrams where needed? +7. Completeness (0-100): Overall ticket completeness - nothing critical missing? + +QUALITY TIERS: +- excellent (85-100): Exemplary ticket, can be implemented with high confidence +- good (70-84): Well-written ticket with minor gaps +- adequate (50-69): Passable but has notable gaps that may cause issues +- poor (25-49): Significant issues, needs improvement before implementation +- insufficient (0-24): Cannot be implemented reliably, needs major rework + +REVIEWABILITY: +A ticket is "reviewable" if there's enough information to meaningfully derive what needs +to be implemented. This does NOT require an explicit acceptance criteria field! + +A ticket is REVIEWABLE if: +- The description explains what needs to be done (even briefly) +- The title + type give enough context to understand the goal +- A senior developer could reasonably derive requirements from it + +A ticket is NOT REVIEWABLE if: +- It's just a title with no description (e.g., "Fix bug" with nothing else) +- It's too vague to derive any concrete requirements +- There's literally not enough info to know what "done" looks like + +Remember: Many good tickets have detailed descriptions but empty AC fields. +The key is whether YOU can derive what needs to be built. + +{format_instructions}`; + +const AC_VALIDATION_PROMPT = `You are a SENIOR DEVELOPER with deep knowledge of this codebase reviewing a PR. + +Your task: Understand what this ticket requires, then evaluate if the PR implements it correctly. + +CRITICAL: DO NOT just rely on the "Acceptance Criteria" field. Many tickets have empty AC or +poorly written AC. You must DERIVE your own understanding of what needs to be done by reading: +- The full description +- The ticket type (bug fix has different needs than a feature) +- Any technical context mentioned +- The implicit requirements (what any experienced dev would know is needed) + +Think like an experienced dev who reads a ticket and thinks: +"Okay, to implement this properly I need to: handle X, add Y, make sure Z works..." + +JIRA TICKET: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} + +FULL DESCRIPTION (analyze this carefully): +{ticketDescription} + +EXPLICIT ACCEPTANCE CRITERIA (may be empty or incomplete - don't rely solely on this): +{acceptanceCriteria} + +PR INFORMATION: +Title: {prTitle} +Description: {prDescription} + +FILES CHANGED: +{filesChanged} + +CODE DIFF: +{diff} + +PREVIOUS PR ANALYSIS SUMMARY: +{prSummary} + +YOUR TASK: + +1. DERIVE REQUIREMENTS: + First, read the entire ticket and derive what actually needs to be implemented. + For each requirement you identify, note: + - What the requirement is + - Where you derived it from (description, explicit AC, implied by ticket type, technical context) + - How essential it is (essential, expected, nice-to-have) + + Don't just copy the AC field - THINK about what's really needed. + A ticket saying "Add login button" implies: the button should be visible, clickable, + trigger auth flow, handle errors, etc. + +2. VALIDATE EACH REQUIREMENT: + For each derived requirement: + - Is it MET, UNMET, PARTIAL, or UNCLEAR in the code? + - Provide CODE EVIDENCE + - Explain your reasoning + +3. IDENTIFY GAPS: + What's missing? What behaviors should exist but don't? + Think through scenarios: "What if the user does X?" "What about error case Y?" + +Report FINDINGS, not suggestions. Like a senior dev saying: +"This doesn't handle the case when the user is logged out" + +{format_instructions}`; + +const PEER_REVIEW_PROMPT = `You are a SENIOR DEVELOPER doing a thorough peer review. + +You've been with this team for years. You know where the bodies are buried. +You think about: +- Does this actually solve the problem in the ticket? +- What might this break in other parts of the app? +- Are there scenarios the developer didn't consider? +- Is this ready for production? + +JIRA TICKET: +Key: {ticketKey} +Type: {ticketType} +Title: {ticketTitle} +Description: {ticketDescription} +Acceptance Criteria: {acceptanceCriteria} + +PR INFORMATION: +Title: {prTitle} +Description: {prDescription} + +FILES CHANGED: +{filesChanged} + +DIFF SUMMARY: +{diff} + +EXISTING PR ANALYSIS: +Summary: {prSummary} +Risks Identified: {prRisks} + +TICKET QUALITY ASSESSMENT: +Overall Score: {ticketQualityScore}/100 +Reviewable: {isReviewable} + +AC VALIDATION RESULTS: +Compliance: {acCompliancePercentage}% +Gaps Found: {gapsFound} + +YOUR PEER REVIEW TASK: + +1. IMPLEMENTATION COMPLETENESS (0-100): + Does this PR fully implement what the ticket asks for? + +2. QUALITY SCORE (0-100): + Code quality + requirements adherence combined + +3. READY FOR REVIEW: + Would you approve this or request changes? + +4. BLOCKERS: + Critical issues - things that MUST be fixed before merge + (missing functionality, bugs, security issues) + +5. WARNINGS: + Important issues - things that SHOULD be fixed + (edge cases not handled, potential bugs) + +6. RECOMMENDATIONS: + Nice-to-haves for improvement + +7. SCOPE ANALYSIS: + - What's in scope vs out of scope? + - Is there scope creep? + +8. REGRESSION RISKS: + Think: "What else in the app might this break?" + - Consider dependencies, shared code, side effects + - Think about how this interacts with existing features + +9. UNCOVERED SCENARIOS: + As a senior dev, you mentally run through scenarios: + - "What if the user does X?" + - "What about when Y is null?" + - "What happens during Z error condition?" + + Report which scenarios you identified that AREN'T handled. + Don't suggest tests - just flag what's missing. + +10. FINAL VERDICT: + Give your honest assessment: + - APPROVE: Ready to merge (maybe minor nits) + - REQUEST_CHANGES: Needs work before merge + - NEEDS_DISCUSSION: Architectural concerns to discuss + +{format_instructions}`; + +// ========== Agent Class ========== + +export class JiraSubAgent { + private llm: BaseLanguageModel; + + constructor(llm: BaseLanguageModel) { + this.llm = llm; + } + + /** + * Analyze a ticket and PR, providing comprehensive peer review + */ + async analyze(context: JiraSubAgentContext): Promise { + // Step 1: Rate ticket quality + const ticketQuality = await this.rateTicketQuality(context.ticket); + + // Step 2: Derive requirements and validate against PR + // NOTE: We analyze even if there's no explicit AC field - the agent derives + // requirements from the full ticket (description, title, type, context) + let acValidation: AcceptanceCriteriaValidation | undefined; + if (ticketQuality.reviewable) { + // The agent will derive its own requirements from the ticket + // Don't skip just because acceptanceCriteriaList is empty + acValidation = await this.validateAcceptanceCriteria(context); + } + + // Step 3: Generate peer review analysis + const peerReview = await this.generatePeerReview(context, ticketQuality, acValidation); + + return { + ticketQuality, + acValidation, + peerReview, + }; + } + + /** + * Rate the quality of a Jira ticket + */ + async rateTicketQuality(ticket: IssueTicket): Promise { + const parser = StructuredOutputParser.fromZodSchema(TicketQualitySchema); + + const prompt = ChatPromptTemplate.fromTemplate(TICKET_QUALITY_PROMPT); + + const chain = prompt.pipe(this.llm); + + const response = await chain.invoke({ + ticketKey: ticket.key, + ticketType: ticket.type, + ticketTitle: ticket.title, + ticketDescription: ticket.description || 'No description provided', + acceptanceCriteria: ticket.acceptanceCriteria || + ticket.acceptanceCriteriaList?.join('\n') || + 'No acceptance criteria defined', + testScenarios: ticket.testScenarios?.join(', ') || 'None defined', + hasScreenshots: ticket.hasScreenshots ? 'Yes' : 'No', + hasDiagrams: ticket.hasDiagrams ? 'Yes' : 'No', + storyPoints: ticket.storyPoints?.toString() || 'Not estimated', + labels: ticket.labels.join(', ') || 'None', + components: ticket.components.join(', ') || 'None', + format_instructions: parser.getFormatInstructions(), + }); + + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } + + /** + * Validate acceptance criteria against PR changes + */ + async validateAcceptanceCriteria( + context: JiraSubAgentContext + ): Promise { + const parser = StructuredOutputParser.fromZodSchema(AcceptanceCriteriaValidationSchema); + + const prompt = ChatPromptTemplate.fromTemplate(AC_VALIDATION_PROMPT); + + const chain = prompt.pipe(this.llm); + + // Format acceptance criteria with IDs + const acList = context.ticket.acceptanceCriteriaList || []; + const formattedAC = acList + .map((ac, i) => `AC-${i + 1}: ${ac}`) + .join('\n'); + + // Format files changed + const filesChanged = context.files + .map((f) => `${f.path} (+${f.additions}/-${f.deletions}) [${f.status}]`) + .join('\n'); + + // Truncate diff if too long + const maxDiffLength = 15000; + const truncatedDiff = + context.diff.length > maxDiffLength + ? context.diff.substring(0, maxDiffLength) + '\n... [diff truncated]' + : context.diff; + + const response = await chain.invoke({ + ticketKey: context.ticket.key, + ticketType: context.ticket.type, + ticketTitle: context.ticket.title, + ticketDescription: context.ticket.description?.substring(0, 2000) || 'No description', + acceptanceCriteria: formattedAC || 'No acceptance criteria defined', + prTitle: context.prTitle, + prDescription: context.prDescription || 'No description', + filesChanged, + diff: truncatedDiff, + prSummary: context.prSummary || 'No summary available', + format_instructions: parser.getFormatInstructions(), + }); + + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } + + /** + * Generate comprehensive peer review analysis + */ + async generatePeerReview( + context: JiraSubAgentContext, + ticketQuality: TicketQualityRating, + acValidation?: AcceptanceCriteriaValidation + ): Promise { + const parser = StructuredOutputParser.fromZodSchema(PeerReviewAnalysisSchema); + + const prompt = ChatPromptTemplate.fromTemplate(PEER_REVIEW_PROMPT); + + const chain = prompt.pipe(this.llm); + + // Format files changed + const filesChanged = context.files + .map((f) => `${f.path} (+${f.additions}/-${f.deletions}) [${f.status}]`) + .join('\n'); + + // Truncate diff if too long + const maxDiffLength = 10000; + const truncatedDiff = + context.diff.length > maxDiffLength + ? context.diff.substring(0, maxDiffLength) + '\n... [diff truncated]' + : context.diff; + + // Format gaps found + const gapsFound = acValidation?.gaps + .map((g) => `- ${g.criteriaText}: ${g.gapDescription}`) + .join('\n') || 'None identified'; + + const response = await chain.invoke({ + ticketKey: context.ticket.key, + ticketType: context.ticket.type, + ticketTitle: context.ticket.title, + ticketDescription: context.ticket.description?.substring(0, 2000) || 'No description', + acceptanceCriteria: + context.ticket.acceptanceCriteria || + context.ticket.acceptanceCriteriaList?.join('\n') || + 'None defined', + prTitle: context.prTitle, + prDescription: context.prDescription || 'No description', + filesChanged, + diff: truncatedDiff, + prSummary: context.prSummary || 'No summary available', + prRisks: context.prRisks?.join(', ') || 'None identified', + ticketQualityScore: ticketQuality.overallScore, + isReviewable: ticketQuality.reviewable ? 'Yes' : 'No', + acCompliancePercentage: acValidation?.compliancePercentage ?? 'N/A', + gapsFound, + format_instructions: parser.getFormatInstructions(), + }); + + const content = typeof response === 'string' ? response : response.content?.toString() || ''; + return parser.parse(content); + } +} diff --git a/src/cli/commands/analyze.command.ts b/src/cli/commands/analyze.command.ts index 37b75b8..cd782de 100644 --- a/src/cli/commands/analyze.command.ts +++ b/src/cli/commands/analyze.command.ts @@ -7,6 +7,12 @@ import { loadUserConfig, getApiKey } from '../utils/config-loader.js'; import { archDocsExists } from '../../utils/arch-docs-parser.js'; import { resolveDefaultBranch } from '../../utils/branch-resolver.js'; import { ConfigurationError, GitHubAPIError, GitError } from '../../utils/errors.js'; +import { + createPeerReviewIntegration, + formatPeerReviewOutput, + type PeerReviewResult, +} from '../../issue-tracker/index.js'; +import { ProviderFactory, type SupportedProvider } from '../../providers/index.js'; import { Fix } from '../../types/agent.types.js'; interface AnalyzeOptions { @@ -25,6 +31,7 @@ interface AnalyzeOptions { verbose?: boolean; maxCost?: number; archDocs?: boolean; + peerReview?: boolean; // Enable Jira peer review integration } interface AnalysisMode { @@ -262,15 +269,16 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { } throw error; } - + // Get provider and API key from config or environment if (options.verbose) { console.log(chalk.gray(` Debug: options.provider: ${options.provider || 'undefined'}`)); console.log(chalk.gray(` Debug: config.ai?.provider: ${config.ai?.provider || 'undefined'}`)); } - const provider = (options.provider || config.ai?.provider || 'anthropic').toLowerCase() as 'anthropic' | 'openai' | 'google'; + const provider = (options.provider || config.ai?.provider || 'anthropic').toLowerCase() as SupportedProvider; const apiKey = getApiKey(provider, config); - + const model = options.model || config.ai?.model; + if (!apiKey) { spinner.fail('No API key found'); console.error(chalk.yellow('💡 Please set it in one of these ways:')); @@ -279,9 +287,13 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { console.error(chalk.gray(' - Anthropic (Claude): export ANTHROPIC_API_KEY="your-api-key"')); console.error(chalk.gray(' - OpenAI (GPT): export OPENAI_API_KEY="your-api-key"')); console.error(chalk.gray(' - Google (Gemini): export GOOGLE_API_KEY="your-api-key"')); + console.error(chalk.gray(' - Zhipu (GLM): export ZHIPU_API_KEY="your-api-key"')); + if (options.verbose) { + console.error(chalk.gray(` Debug: Provider=${provider}, Config apiKeys=${JSON.stringify(config.apiKeys || {})}`)); + } process.exit(1); } - + spinner.succeed(`Using AI provider: ${provider}`); // Resolve default branch if needed @@ -294,13 +306,13 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { githubToken: process.env.GITHUB_TOKEN, fallbackToGit: true, }); - + defaultBranch = branchResult.branch; - + if (branchResult.warning && options.verbose) { console.log(chalk.yellow(`\n⚠️ ${branchResult.warning}`)); } - + if (options.verbose) { console.log(chalk.gray(` Using branch: ${defaultBranch} (source: ${branchResult.source})`)); } @@ -391,16 +403,15 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { // Check for arch-docs const useArchDocs = options.archDocs !== false; // Default to true if not specified const hasArchDocs = archDocsExists(); - + if (useArchDocs && hasArchDocs) { console.log(chalk.cyan('📚 Architecture documentation detected - including in analysis\n')); } else if (options.archDocs && !hasArchDocs) { console.log(chalk.yellow('⚠️ --arch-docs flag specified but no .arch-docs folder found\n')); } - const model = options.model || config.ai?.model; const agent = new PRAnalyzerAgent({ - provider: provider as any, + provider: provider, apiKey, model, }); @@ -414,9 +425,23 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { // Display results displayAgentResults(result, mode, options.verbose || false); + + // Run Peer Review if enabled (via flag or config) + const peerReviewEnabled = options.peerReview || config.peerReview?.enabled; + if (options.verbose) { + console.log(chalk.gray(`\n Debug: peerReviewEnabled=${peerReviewEnabled}, options.peerReview=${options.peerReview}, config.peerReview?.enabled=${config.peerReview?.enabled}`)); + } + if (peerReviewEnabled) { + // Pass the same provider config to peer review so it uses the same LLM + await runPeerReview(config, diff, title, result, options.verbose || false, { + provider, + apiKey, + model, + }); + } } catch (error: any) { spinner.fail('Analysis failed'); - + // Handle specific error types with user-friendly messages if (error instanceof ConfigurationError) { console.error(chalk.red(`\n❌ Configuration Error: ${error.message}`)); @@ -445,7 +470,7 @@ export async function analyzePR(options: AnalyzeOptions = {}): Promise { .replace(/sk-[a-zA-Z0-9_-]+/g, 'sk-***') .replace(/ghp_[a-zA-Z0-9]+/g, 'ghp_***') .substring(0, 500); // Limit length - + console.error(chalk.red(`\n❌ Error: ${sanitizedMessage}`)); if (options.verbose && error.stack) { console.error(chalk.gray('\nStack trace:')); @@ -551,13 +576,65 @@ function displayAgentResults(result: any, mode: AnalysisMode, verbose: boolean): }); } - const totalFilteredFixes = result.fixes?.filter((f: Fix) => + const totalFilteredFixes = result.fixes?.filter((f: Fix) => (f.severity === 'critical' || f.severity === 'warning') && f.line !== undefined && f.line !== null ).length || 0; - + if (totalFilteredFixes > prCommentFixes.length) { console.log(chalk.gray(` ... and ${totalFilteredFixes - prCommentFixes.length} more issues\n`)); } + } + + // Show recommendations if available + if (result.recommendations.length > 0) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.cyan.bold('\n💡 Recommendations\n')); + result.recommendations.forEach((rec: string, i: number) => { + console.log(chalk.white(` ${i + 1}. ${rec}`)); + }); + console.log('\n'); + } + + // Show agent reasoning if available (minimal) + if (verbose && result.reasoning.length > 0 && result.reasoning.length <= 5) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.cyan.bold('\n🤔 Analysis Strategy\n')); + result.reasoning.forEach((reason: string, i: number) => { + if (reason.includes('Strategy:') || i === 0) { + console.log(chalk.gray(` ${reason.substring(0, 150)}${reason.length > 150 ? '...' : ''}`)); + } + }); + console.log('\n'); + } + + // Show arch-docs impact if used + if (result.archDocsImpact?.used) { + console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')); + console.log(chalk.blue.bold('\n📚 Architecture Documentation Impact\n')); + + console.log(chalk.white(`Documents analyzed: ${result.archDocsImpact.docsAvailable}`)); + console.log(chalk.white(`Relevant sections used: ${result.archDocsImpact.sectionsUsed}\n`)); + + if (result.archDocsImpact.influencedStages.length > 0) { + console.log(chalk.cyan('Stages influenced by arch-docs:')); + result.archDocsImpact.influencedStages.forEach((stage: string) => { + const stageEmoji = stage === 'file-analysis' ? '🔍' : + stage === 'risk-detection' ? '⚠️' : + stage === 'complexity-calculation' ? '📊' : + stage === 'summary-generation' ? '📝' : + stage === 'refinement' ? '🔄' : '✨'; + console.log(chalk.white(` ${stageEmoji} ${stage}`)); + }); + console.log(''); + } + + if (result.archDocsImpact.keyInsights.length > 0) { + console.log(chalk.cyan('Key insights from arch-docs integration:\n')); + result.archDocsImpact.keyInsights.forEach((insight: string, i: number) => { + console.log(chalk.white(` ${i + 1}. ${insight}`)); + }); + console.log(''); + } } else { console.log(chalk.green.bold('✅ Status\n')); console.log(chalk.white(' No critical issues found.\n\n')); @@ -571,4 +648,147 @@ function displayAgentResults(result: any, mode: AnalysisMode, verbose: boolean): console.log(chalk.gray('\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n')); } +/** + * Run Peer Review analysis against linked Jira tickets + * + * This extends the PR analysis with business context validation: + * - Fetches linked Jira tickets from PR title/branch + * - Rates ticket quality + * - Validates implementation against derived requirements + * - Provides senior-dev style verdict + */ +async function runPeerReview( + config: any, + diff: string, + title: string | undefined, + prAnalysisResult: any, + verbose: boolean, + providerOptions: { provider: SupportedProvider; apiKey: string; model?: string } +): Promise { + const spinner = ora('Running Peer Review analysis...').start(); + + try { + // Create LLM using the same provider as main analysis + const llm = ProviderFactory.createChatModel({ + provider: providerOptions.provider, + apiKey: providerOptions.apiKey, + model: providerOptions.model, + temperature: 0.2, + maxTokens: 4000, + }); + + // Create peer review integration from config, passing the LLM + const peerReviewConfig = config.peerReview || {}; + const integration = createPeerReviewIntegration(peerReviewConfig, llm); + + if (!integration.isEnabled()) { + spinner.warn('Peer Review enabled but not configured. Add Jira settings to config.'); + console.log(chalk.gray(' Run: pr-agent config --set peerReview.instanceUrl=https://your.atlassian.net')); + console.log(chalk.gray(' Or configure MCP: peerReview.useMcp=true')); + if (verbose) { + console.log(chalk.gray(` Debug: peerReviewConfig=${JSON.stringify(peerReviewConfig)}`)); + } + return; + } + // Get branch name for ticket extraction + let branchName: string | undefined; + try { + branchName = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf-8' }).trim(); + } catch { + // Ignore - branch name is optional + } + + // Get commit messages for ticket extraction + let commitMessages: string[] = []; + try { + const commits = execSync('git log --oneline -10', { encoding: 'utf-8' }); + commitMessages = commits.trim().split('\n'); + } catch { + // Ignore + } + + // Parse diff to get file info + const files = parseDiffFiles(diff); + + spinner.text = 'Extracting ticket references...'; + + // Run peer review analysis + const result = await integration.analyze({ + prTitle: title || 'Untitled PR', + prDescription: undefined, // Could extract from git commit body + branchName, + commitMessages, + diff, + files, + prSummary: prAnalysisResult.summary, + prRisks: prAnalysisResult.overallRisks, + prComplexity: prAnalysisResult.overallComplexity, + }); + + spinner.succeed('Peer Review analysis complete'); + + // Display peer review results + const output = formatPeerReviewOutput(result); + if (output) { + console.log(output); + } + + if (verbose && result.ticketReferences.length > 0) { + console.log(chalk.gray('Ticket references found:')); + result.ticketReferences.forEach((ref) => { + console.log(chalk.gray(` - ${ref.key} (from ${ref.source}, confidence: ${ref.confidence}%)`)); + }); + } + } catch (error: any) { + spinner.fail('Peer Review analysis failed'); + console.error(chalk.yellow(`⚠️ ${error.message || 'Unknown error'}`)); + console.log(chalk.gray(' The main PR analysis completed successfully.')); + console.log(chalk.gray(' Peer Review is an optional enhancement - check Jira configuration.')); + } +} + +/** + * Parse diff to extract file information + */ +function parseDiffFiles(diff: string): Array<{ + path: string; + additions: number; + deletions: number; + status: string; +}> { + const files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }> = []; + + const filePattern = /^diff --git a\/(.+?) b\/(.+?)$/gm; + let match; + + while ((match = filePattern.exec(diff)) !== null) { + const filePath = match[2] !== '/dev/null' ? match[2] : match[1]; + const isNew = match[1] === '/dev/null' || match[1].startsWith('dev/null'); + const isDeleted = match[2] === '/dev/null'; + + // Count additions and deletions (simplified) + const fileStart = match.index; + const nextFileMatch = filePattern.exec(diff); + const fileEnd = nextFileMatch ? nextFileMatch.index : diff.length; + filePattern.lastIndex = match.index + 1; // Reset to continue from after current match + + const fileContent = diff.substring(fileStart, fileEnd); + const additions = (fileContent.match(/^\+[^+]/gm) || []).length; + const deletions = (fileContent.match(/^-[^-]/gm) || []).length; + + files.push({ + path: filePath, + additions, + deletions, + status: isNew ? 'added' : isDeleted ? 'deleted' : 'modified', + }); + } + + return files; +} diff --git a/src/cli/commands/help.command.ts b/src/cli/commands/help.command.ts index 437f0e3..1fb68ed 100644 --- a/src/cli/commands/help.command.ts +++ b/src/cli/commands/help.command.ts @@ -52,7 +52,7 @@ export function displayHelp(): void { console.log(' Use --branch to override for a single analysis\n'); console.log(chalk.dim(' Advanced Options:')); - console.log(' --provider AI provider: anthropic|openai|google'); + console.log(' --provider AI provider: anthropic|openai|google|zhipu'); console.log(' --model Specific model to use'); console.log(' --title PR title (auto-detected from git)'); console.log(' --max-cost Maximum cost limit (default: $5.00)'); diff --git a/src/cli/index.ts b/src/cli/index.ts index 4c4c3d6..05b9576 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -35,7 +35,7 @@ program .option('--staged', 'Analyze staged changes (git diff --staged)') .option('--branch ', 'Analyze against specific branch') .option('--title ', 'PR title (auto-detected from git)') - .option('--provider ', 'AI provider (anthropic|openai|google)') + .option('--provider ', 'AI provider (anthropic|openai|google|zhipu)') .option('--model ', 'Specific model to use') .option('--agent', 'Force intelligent agent (recommended for large diffs)') .option('--summary', 'Show summary only') diff --git a/src/cli/utils/config-loader.ts b/src/cli/utils/config-loader.ts index f6331e4..390410b 100644 --- a/src/cli/utils/config-loader.ts +++ b/src/cli/utils/config-loader.ts @@ -11,6 +11,7 @@ export interface UserConfig { anthropic?: string; openai?: string; google?: string; + zhipu?: string; }; ai?: { provider?: string; @@ -37,6 +38,37 @@ export interface UserConfig { showStrategy?: boolean; showRecommendations?: boolean; }; + /** + * Peer Review configuration - integrates with issue trackers (Jira, etc.) + * to validate PRs against tickets and acceptance criteria + */ + peerReview?: { + // Enable/disable peer review feature + enabled?: boolean; + // Issue tracker provider: 'jira' | 'linear' | 'azure-devops' | 'github-issues' + provider?: string; + // Use MCP server for Jira access (recommended) + useMcp?: boolean; + // Direct API access settings (fallback if MCP not available) + instanceUrl?: string; + email?: string; + apiToken?: string; + // Default project key + defaultProject?: string; + // Custom field IDs (Jira-specific) + acceptanceCriteriaField?: string; + storyPointsField?: string; + // Custom ticket patterns (regex) - defaults to PROJ-123 format + ticketPatterns?: string[]; + // Analysis options + analyzeAcceptanceCriteria?: boolean; + rateTicketQuality?: boolean; + generateTestSuggestions?: boolean; + checkScopeCreep?: boolean; + // Output options + includeTicketDetails?: boolean; + verbose?: boolean; + }; } /** @@ -190,6 +222,7 @@ export function getApiKey(provider: string, config?: UserConfig): string | undef anthropic: 'ANTHROPIC_API_KEY', openai: 'OPENAI_API_KEY', google: 'GOOGLE_API_KEY', + zhipu: 'ZHIPU_API_KEY', }; const envVar = envVarMap[provider.toLowerCase()]; diff --git a/src/issue-tracker/index.ts b/src/issue-tracker/index.ts new file mode 100644 index 0000000..013f13e --- /dev/null +++ b/src/issue-tracker/index.ts @@ -0,0 +1,34 @@ +/** + * Issue Tracker Module + * + * Provides integration with issue tracking systems (Jira, Linear, etc.) + * for context-aware PR reviews. + */ + +// Types +export * from '../types/issue-tracker.types.js'; + +// Jira Client +export { JiraMcpClient, type JiraConfig } from './jira-mcp-client.js'; + +// Integration +export { + PeerReviewIntegration, + createPeerReviewIntegration, + formatPeerReviewOutput, + formatPeerReviewMarkdown, + type PeerReviewConfig, + type PeerReviewContext, + type PeerReviewResult, + type PeerReviewUserConfig, +} from './peer-review-integration.js'; + +// Sub-Agent +export { + JiraSubAgent, + type JiraSubAgentResult, + type JiraSubAgentContext, + type TicketQualityRating, + type AcceptanceCriteriaValidation, + type PeerReviewAnalysis, +} from '../agents/jira-sub-agent.js'; diff --git a/src/issue-tracker/jira-mcp-client.ts b/src/issue-tracker/jira-mcp-client.ts new file mode 100644 index 0000000..a332cc1 --- /dev/null +++ b/src/issue-tracker/jira-mcp-client.ts @@ -0,0 +1,658 @@ +/** + * Jira MCP Client + * + * Implements IssueTrackerProvider interface using the Atlassian MCP server. + * This client fetches Jira tickets and extracts ticket references from PR metadata. + * + * The MCP server is expected to provide Jira access through its tools. + * For environments without MCP, falls back to direct Jira API (if configured). + */ + +import { + IssueTrackerProvider, + IssueTrackerType, + IssueTicket, + IssueType, + IssuePriority, + TicketReference, + TicketExtractionContext, + IssueComment, + LinkedIssue, + SubtaskInfo, +} from '../types/issue-tracker.types.js'; + +// Jira-specific configuration +export interface JiraConfig { + // MCP-based access (preferred) + useMcp: boolean; + + // Direct API access (fallback) + instanceUrl?: string; + email?: string; + apiToken?: string; + + // Project settings + defaultProject?: string; + + // Custom field mappings + acceptanceCriteriaField?: string; // Custom field ID for AC + storyPointsField?: string; // Custom field ID for story points + + // Ticket patterns for extraction + ticketPatterns?: string[]; +} + +// Default patterns to match Jira ticket keys +const DEFAULT_TICKET_PATTERNS = [ + /([A-Z][A-Z0-9]+-\d+)/g, // Standard Jira format: PROJ-123 +]; + +export class JiraMcpClient implements IssueTrackerProvider { + readonly name = 'Jira'; + readonly type: IssueTrackerType = 'jira'; + + private config: JiraConfig; + private ticketPatterns: RegExp[]; + + // MCP callback for making MCP tool calls + // This is injected at runtime when MCP is available + private mcpCallback?: ( + tool: string, + params: Record + ) => Promise; + + constructor(config: JiraConfig) { + this.config = config; + this.ticketPatterns = this.buildTicketPatterns(); + } + + /** + * Set the MCP callback function for making MCP tool calls + */ + setMcpCallback( + callback: ( + tool: string, + params: Record + ) => Promise + ): void { + this.mcpCallback = callback; + } + + /** + * Check if the client is properly configured + */ + isConfigured(): boolean { + if (this.config.useMcp) { + return !!this.mcpCallback; + } + // Direct API requires instance URL and credentials + return !!( + this.config.instanceUrl && + this.config.email && + this.config.apiToken + ); + } + + /** + * Test connection to Jira + */ + async testConnection(): Promise { + try { + // Try to fetch any ticket to verify connection + if (this.config.useMcp && this.mcpCallback) { + // Use MCP to test connection + const result = await this.mcpCallback('atlassian:search-company-knowledge', { + query: 'test connection', + limit: 1, + }); + return !!result; + } else if (this.config.instanceUrl) { + // Direct API test + const response = await this.fetchJiraApi('/rest/api/3/myself'); + return response.ok; + } + return false; + } catch { + return false; + } + } + + /** + * Extract ticket references from PR metadata + */ + extractTicketReferences(context: TicketExtractionContext): TicketReference[] { + const references: Map = new Map(); + + // Extract from title (highest confidence) + this.extractFromText(context.prTitle, 'title', 95, references); + + // Extract from branch name (high confidence) + if (context.branchName) { + this.extractFromText(context.branchName, 'branch', 90, references); + } + + // Extract from description (medium confidence) + if (context.prDescription) { + this.extractFromText(context.prDescription, 'description', 80, references); + } + + // Extract from commit messages (lower confidence due to potential noise) + if (context.commitMessages) { + for (const msg of context.commitMessages) { + this.extractFromText(msg, 'commit', 70, references); + } + } + + // Sort by confidence (highest first) + return Array.from(references.values()).sort( + (a, b) => b.confidence - a.confidence + ); + } + + /** + * Fetch a single ticket by key + */ + async getTicket(key: string): Promise { + try { + const rawTicket = await this.fetchJiraTicket(key); + if (!rawTicket) return null; + return this.normalizeTicket(rawTicket); + } catch (error) { + console.error(`Failed to fetch ticket ${key}:`, error); + return null; + } + } + + /** + * Fetch multiple tickets by keys + */ + async getTickets(keys: string[]): Promise { + const tickets: IssueTicket[] = []; + + // Fetch in parallel with concurrency limit + const batchSize = 5; + for (let i = 0; i < keys.length; i += batchSize) { + const batch = keys.slice(i, i + batchSize); + const results = await Promise.all( + batch.map((key) => this.getTicket(key)) + ); + tickets.push(...results.filter((t): t is IssueTicket => t !== null)); + } + + return tickets; + } + + /** + * Search for tickets matching a query + */ + async searchTickets(query: string, limit = 10): Promise { + try { + if (this.config.useMcp && this.mcpCallback) { + // Use MCP search + const result = await this.mcpCallback('atlassian:search-company-knowledge', { + query, + limit, + }); + // Parse and normalize results + if (Array.isArray(result)) { + return result.map((r) => this.normalizeTicket(r as JiraApiIssue)); + } + } else { + // Direct JQL search + const jql = `text ~ "${query}" ORDER BY updated DESC`; + const response = await this.fetchJiraApi( + `/rest/api/3/search?jql=${encodeURIComponent(jql)}&maxResults=${limit}` + ); + if (response.ok) { + const data = await response.json() as { issues?: JiraApiIssue[] }; + return (data.issues || []).map((issue: JiraApiIssue) => + this.normalizeTicket(issue) + ); + } + } + } catch (error) { + console.error('Failed to search tickets:', error); + } + return []; + } + + /** + * Get comments for a ticket + */ + async getComments(ticketKey: string): Promise { + try { + const response = await this.fetchJiraApi( + `/rest/api/3/issue/${ticketKey}/comment` + ); + if (response.ok) { + const data = await response.json() as { comments?: JiraApiComment[] }; + return (data.comments || []).map((c: JiraApiComment) => { + let bodyText = ''; + if (typeof c.body === 'string') { + bodyText = c.body; + } else if (c.body && typeof c.body === 'object' && 'content' in c.body) { + bodyText = c.body.content?.[0]?.content?.[0]?.text || ''; + } + return { + id: c.id, + author: c.author?.displayName || 'Unknown', + body: bodyText, + createdAt: c.created, + }; + }); + } + } catch (error) { + console.error(`Failed to get comments for ${ticketKey}:`, error); + } + return []; + } + + // ========== Private Helper Methods ========== + + private buildTicketPatterns(): RegExp[] { + if (this.config.ticketPatterns?.length) { + return this.config.ticketPatterns.map((p) => new RegExp(p, 'g')); + } + return DEFAULT_TICKET_PATTERNS; + } + + private extractFromText( + text: string, + source: TicketReference['source'], + baseConfidence: number, + references: Map + ): void { + for (const pattern of this.ticketPatterns) { + // Reset lastIndex for global patterns + pattern.lastIndex = 0; + let match; + while ((match = pattern.exec(text)) !== null) { + const key = match[1] || match[0]; + const upperKey = key.toUpperCase(); + + // Skip if we already have this reference with higher confidence + const existing = references.get(upperKey); + if (existing && existing.confidence >= baseConfidence) { + continue; + } + + references.set(upperKey, { + key: upperKey, + source, + rawMatch: match[0], + confidence: baseConfidence, + }); + } + } + } + + private async fetchJiraTicket(key: string): Promise { + if (this.config.useMcp && this.mcpCallback) { + // Use MCP to fetch ticket + // The MCP server should have a tool for fetching individual issues + try { + const result = await this.mcpCallback('atlassian:get-issue', { + issueKey: key, + }); + return result as JiraApiIssue; + } catch { + // If specific tool not available, try search + const searchResult = await this.mcpCallback('atlassian:search-company-knowledge', { + query: `key:${key}`, + limit: 1, + }); + if (Array.isArray(searchResult) && searchResult.length > 0) { + return searchResult[0] as JiraApiIssue; + } + } + } + + // Direct API fetch + const response = await this.fetchJiraApi(`/rest/api/3/issue/${key}?expand=renderedFields`); + if (response.ok) { + return response.json() as Promise; + } + return null; + } + + private async fetchJiraApi(path: string): Promise { + if (!this.config.instanceUrl || !this.config.email || !this.config.apiToken) { + throw new Error('Jira API credentials not configured'); + } + + const url = `${this.config.instanceUrl}${path}`; + const auth = Buffer.from(`${this.config.email}:${this.config.apiToken}`).toString('base64'); + + return fetch(url, { + headers: { + Authorization: `Basic ${auth}`, + Accept: 'application/json', + }, + }); + } + + private normalizeTicket(raw: JiraApiIssue): IssueTicket { + const fields = raw.fields || {}; + + // Extract acceptance criteria from description or custom field + const acceptanceCriteria = this.extractAcceptanceCriteria(fields); + + // Normalize issue type + const issueType = this.normalizeIssueType(fields.issuetype?.name); + + // Normalize priority + const priority = this.normalizePriority(fields.priority?.name); + + // Extract linked issues + const linkedIssues = this.extractLinkedIssues(fields); + + // Extract subtasks + const subtasks = this.extractSubtasks(fields); + + // Check for visual documentation + const attachments = fields.attachment || []; + const hasScreenshots = attachments.some((a: JiraApiAttachment) => + a.mimeType?.startsWith('image/') + ); + const hasDiagrams = attachments.some( + (a: JiraApiAttachment) => + a.filename?.includes('diagram') || + a.filename?.includes('flow') || + a.mimeType?.includes('svg') + ); + + // Extract epic key - handle custom field which may be string or undefined + const epicKey = fields.epic?.key || (fields.customfield_10014 as string | undefined); + + return { + id: raw.id, + key: raw.key, + url: `${this.config.instanceUrl || ''}/browse/${raw.key}`, + title: fields.summary || '', + description: this.extractDescription(fields), + type: issueType, + status: fields.status?.name || 'Unknown', + priority, + assignee: fields.assignee?.displayName, + reporter: fields.reporter?.displayName, + labels: fields.labels || [], + components: (fields.components || []).map((c: { name: string }) => c.name), + project: fields.project?.key, + storyPoints: this.extractStoryPoints(fields), + acceptanceCriteria: acceptanceCriteria.text, + acceptanceCriteriaList: acceptanceCriteria.list, + testScenarios: this.extractTestScenarios(fields), + linkedTestCases: [], // Would need Zephyr/Xray integration + hasScreenshots, + hasDiagrams, + attachmentCount: attachments.length, + parentKey: fields.parent?.key, + epicKey, + linkedIssues, + subtasks, + createdAt: fields.created || '', + updatedAt: fields.updated || '', + rawData: raw as unknown as Record, + }; + } + + private extractDescription(fields: JiraApiFields): string { + // Handle Atlassian Document Format (ADF) or plain text + if (typeof fields.description === 'string') { + return fields.description; + } + if (fields.description?.content) { + return this.adfToText(fields.description); + } + return ''; + } + + private adfToText(adf: JiraAdfDocument): string { + // Simple ADF to text conversion + const extractText = (node: JiraAdfNode): string => { + if (node.type === 'text') { + return node.text || ''; + } + if (node.content) { + return node.content.map(extractText).join(''); + } + return ''; + }; + + return (adf.content || []) + .map((node) => { + const text = extractText(node); + // Add newlines for block elements + if (['paragraph', 'heading', 'bulletList', 'orderedList', 'listItem'].includes(node.type)) { + return text + '\n'; + } + return text; + }) + .join('') + .trim(); + } + + private extractAcceptanceCriteria(fields: JiraApiFields): { + text: string; + list: string[]; + } { + // Try custom field first + if (this.config.acceptanceCriteriaField) { + const customField = fields[this.config.acceptanceCriteriaField]; + if (customField) { + let text: string; + if (typeof customField === 'string') { + text = customField; + } else if (typeof customField === 'object' && customField !== null && 'type' in customField && 'version' in customField) { + text = this.adfToText(customField as JiraAdfDocument); + } else { + text = ''; + } + return { text, list: this.parseAcceptanceCriteriaList(text) }; + } + } + + // Extract from description - look for common AC patterns + const description = this.extractDescription(fields); + const acPatterns = [ + /acceptance\s*criteria[:\s]*\n([\s\S]*?)(?=\n\n|\n#|$)/i, + /definition\s*of\s*done[:\s]*\n([\s\S]*?)(?=\n\n|\n#|$)/i, + /requirements[:\s]*\n([\s\S]*?)(?=\n\n|\n#|$)/i, + /given[\s\S]*?when[\s\S]*?then/gi, // Gherkin-style + ]; + + for (const pattern of acPatterns) { + const match = description.match(pattern); + if (match) { + const text = match[1] || match[0]; + return { text, list: this.parseAcceptanceCriteriaList(text) }; + } + } + + return { text: '', list: [] }; + } + + private parseAcceptanceCriteriaList(text: string): string[] { + const items: string[] = []; + + // Parse bullet points + const bulletMatches = text.match(/^[\s]*[-*•]\s*(.+)$/gm); + if (bulletMatches) { + items.push(...bulletMatches.map((m) => m.replace(/^[\s]*[-*•]\s*/, '').trim())); + } + + // Parse numbered items + const numberedMatches = text.match(/^[\s]*\d+[.)]\s*(.+)$/gm); + if (numberedMatches) { + items.push(...numberedMatches.map((m) => m.replace(/^[\s]*\d+[.)]\s*/, '').trim())); + } + + // Parse checkboxes + const checkboxMatches = text.match(/^[\s]*\[[ x]\]\s*(.+)$/gim); + if (checkboxMatches) { + items.push(...checkboxMatches.map((m) => m.replace(/^[\s]*\[[ x]\]\s*/i, '').trim())); + } + + // If no structured items found, split by newlines + if (items.length === 0 && text.trim()) { + const lines = text.split('\n').filter((l) => l.trim().length > 10); + items.push(...lines.map((l) => l.trim())); + } + + return [...new Set(items)]; // Remove duplicates + } + + private extractStoryPoints(fields: JiraApiFields): number | undefined { + // Try common story point field IDs + const spFields = [ + this.config.storyPointsField, + 'customfield_10016', // Common Jira Cloud + 'customfield_10004', // Another common one + 'storyPoints', + ].filter(Boolean); + + for (const field of spFields) { + if (field && fields[field] !== undefined) { + const value = fields[field]; + if (typeof value === 'number') return value; + if (typeof value === 'string') return parseFloat(value) || undefined; + } + } + return undefined; + } + + private extractTestScenarios(fields: JiraApiFields): string[] { + const description = this.extractDescription(fields); + const scenarios: string[] = []; + + // Look for test scenario patterns + const testPatterns = [ + /test\s*scenario[s]?[:\s]*\n([\s\S]*?)(?=\n\n|\n#|$)/i, + /test\s*cases?[:\s]*\n([\s\S]*?)(?=\n\n|\n#|$)/i, + /scenario[:\s]+(.+)/gi, + ]; + + for (const pattern of testPatterns) { + const matches = description.match(pattern); + if (matches) { + scenarios.push(...this.parseAcceptanceCriteriaList(matches[1] || matches[0])); + } + } + + return [...new Set(scenarios)]; + } + + private normalizeIssueType(typeName?: string): IssueType { + if (!typeName) return 'other'; + const lower = typeName.toLowerCase(); + if (lower.includes('bug')) return 'bug'; + if (lower.includes('feature')) return 'feature'; + if (lower.includes('story')) return 'story'; + if (lower.includes('epic')) return 'epic'; + if (lower.includes('subtask') || lower.includes('sub-task')) return 'subtask'; + if (lower.includes('task')) return 'task'; + if (lower.includes('improvement')) return 'improvement'; + if (lower.includes('spike')) return 'spike'; + return 'other'; + } + + private normalizePriority(priorityName?: string): IssuePriority { + if (!priorityName) return 'none'; + const lower = priorityName.toLowerCase(); + if (lower.includes('critical') || lower.includes('blocker') || lower.includes('highest')) { + return 'critical'; + } + if (lower.includes('high')) return 'high'; + if (lower.includes('medium') || lower.includes('normal')) return 'medium'; + if (lower.includes('low') || lower.includes('minor')) return 'low'; + return 'none'; + } + + private extractLinkedIssues(fields: JiraApiFields): LinkedIssue[] { + const links = fields.issuelinks || []; + return links.map((link: JiraApiIssueLink) => { + const linkedIssue = link.inwardIssue || link.outwardIssue; + const linkType = link.inwardIssue ? link.type?.inward : link.type?.outward; + return { + key: linkedIssue?.key || '', + type: linkType || 'relates to', + title: linkedIssue?.fields?.summary || '', + status: linkedIssue?.fields?.status?.name || '', + }; + }); + } + + private extractSubtasks(fields: JiraApiFields): SubtaskInfo[] { + const subtasks = fields.subtasks || []; + return subtasks.map((st: JiraApiSubtask) => ({ + key: st.key, + title: st.fields?.summary || '', + status: st.fields?.status?.name || '', + })); + } +} + +// ========== Jira API Types ========== + +interface JiraApiIssue { + id: string; + key: string; + fields: JiraApiFields; +} + +interface JiraApiFields { + summary?: string; + description?: string | JiraAdfDocument; + issuetype?: { name: string }; + status?: { name: string }; + priority?: { name: string }; + assignee?: { displayName: string }; + reporter?: { displayName: string }; + labels?: string[]; + components?: Array<{ name: string }>; + project?: { key: string }; + parent?: { key: string }; + epic?: { key: string }; + created?: string; + updated?: string; + attachment?: JiraApiAttachment[]; + issuelinks?: JiraApiIssueLink[]; + subtasks?: JiraApiSubtask[]; + [key: string]: unknown; // Custom fields +} + +interface JiraAdfDocument { + type: string; + version: number; + content?: JiraAdfNode[]; +} + +interface JiraAdfNode { + type: string; + text?: string; + content?: JiraAdfNode[]; +} + +interface JiraApiAttachment { + id: string; + filename: string; + mimeType: string; +} + +interface JiraApiIssueLink { + type?: { inward: string; outward: string }; + inwardIssue?: { key: string; fields?: { summary?: string; status?: { name: string } } }; + outwardIssue?: { key: string; fields?: { summary?: string; status?: { name: string } } }; +} + +interface JiraApiSubtask { + key: string; + fields?: { summary?: string; status?: { name: string } }; +} + +interface JiraApiComment { + id: string; + author?: { displayName: string }; + body?: string | JiraAdfDocument; + created: string; +} diff --git a/src/issue-tracker/peer-review-integration.ts b/src/issue-tracker/peer-review-integration.ts new file mode 100644 index 0000000..65a0b71 --- /dev/null +++ b/src/issue-tracker/peer-review-integration.ts @@ -0,0 +1,729 @@ +/** + * Peer Review Integration + * + * This module integrates the Jira sub-agent with the main PR analysis workflow. + * It handles: + * - Extracting ticket references from PR metadata + * - Fetching tickets from issue trackers + * - Running the Jira sub-agent analysis + * - Formatting the combined output + */ + +import { JiraMcpClient, JiraConfig } from './jira-mcp-client.js'; +import { JiraSubAgent, JiraSubAgentResult, JiraSubAgentContext } from '../agents/jira-sub-agent.js'; +import { + IssueTrackerProvider, + IssueTrackerConfig, + IssueTrackerType, + IssueTicket, + TicketReference, +} from '../types/issue-tracker.types.js'; +import { BaseLanguageModel } from '@langchain/core/language_models/base'; + +// ========== Types ========== + +export interface PeerReviewConfig { + issueTracker: IssueTrackerConfig; +} + +export interface PeerReviewContext { + prTitle: string; + prDescription?: string; + branchName?: string; + commitMessages?: string[]; + diff: string; + files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }>; + // From existing PR analysis + prSummary?: string; + prRisks?: string[]; + prComplexity?: number; +} + +export interface PeerReviewResult { + enabled: boolean; + ticketReferences: TicketReference[]; + linkedTickets: IssueTicket[]; + primaryTicket?: IssueTicket; + analysis?: JiraSubAgentResult; + error?: string; +} + +// ========== Main Integration Class ========== + +export class PeerReviewIntegration { + private provider: IssueTrackerProvider | null = null; + private subAgent: JiraSubAgent | null = null; + private config: IssueTrackerConfig; + + constructor(config: IssueTrackerConfig, llm?: BaseLanguageModel) { + this.config = config; + this.initializeProvider(); + if (llm) { + this.subAgent = new JiraSubAgent(llm); + } + } + + /** + * Set the LLM for the sub-agent + */ + setLLM(llm: BaseLanguageModel): void { + this.subAgent = new JiraSubAgent(llm); + } + + /** + * Set MCP callback for the Jira client + */ + setMcpCallback( + callback: (tool: string, params: Record) => Promise + ): void { + if (this.provider && this.provider instanceof JiraMcpClient) { + (this.provider as JiraMcpClient).setMcpCallback(callback); + } + } + + /** + * Check if peer review is enabled and properly configured + */ + isEnabled(): boolean { + return this.config.enabled && this.provider !== null && this.provider.isConfigured(); + } + + /** + * Run peer review analysis + */ + async analyze(context: PeerReviewContext): Promise { + if (!this.config.enabled) { + return { + enabled: false, + ticketReferences: [], + linkedTickets: [], + }; + } + + if (!this.provider) { + return { + enabled: true, + ticketReferences: [], + linkedTickets: [], + error: 'Issue tracker provider not configured', + }; + } + + try { + // Step 1: Extract ticket references from PR metadata + const ticketReferences = this.provider.extractTicketReferences({ + prTitle: context.prTitle, + prDescription: context.prDescription, + branchName: context.branchName, + commitMessages: context.commitMessages, + }); + + if (ticketReferences.length === 0) { + return { + enabled: true, + ticketReferences: [], + linkedTickets: [], + error: 'No ticket references found in PR title, description, or branch name', + }; + } + + // Step 2: Fetch tickets + const ticketKeys = [...new Set(ticketReferences.map((r) => r.key))]; + const linkedTickets = await this.provider.getTickets(ticketKeys); + + if (linkedTickets.length === 0) { + return { + enabled: true, + ticketReferences, + linkedTickets: [], + error: `Could not fetch tickets: ${ticketKeys.join(', ')}`, + }; + } + + // Primary ticket is the one with highest confidence reference + const primaryTicket = linkedTickets[0]; + + // Step 3: Run sub-agent analysis (if configured) + let analysis: JiraSubAgentResult | undefined; + if (this.subAgent && primaryTicket) { + const subAgentContext: JiraSubAgentContext = { + ticket: primaryTicket, + prTitle: context.prTitle, + prDescription: context.prDescription, + diff: context.diff, + files: context.files, + prSummary: context.prSummary, + prRisks: context.prRisks, + }; + + analysis = await this.subAgent.analyze(subAgentContext); + } + + return { + enabled: true, + ticketReferences, + linkedTickets, + primaryTicket, + analysis, + }; + } catch (error) { + return { + enabled: true, + ticketReferences: [], + linkedTickets: [], + error: `Peer review analysis failed: ${error instanceof Error ? error.message : String(error)}`, + }; + } + } + + // ========== Private Methods ========== + + private initializeProvider(): void { + if (!this.config.enabled) return; + + switch (this.config.provider) { + case 'jira': + this.provider = new JiraMcpClient(this.config.providerConfig as unknown as JiraConfig); + break; + + // Future providers + case 'linear': + case 'azure-devops': + case 'github-issues': + case 'gitlab-issues': + console.warn(`Provider ${this.config.provider} not yet implemented, using Jira fallback`); + break; + + default: + console.warn(`Unknown provider: ${this.config.provider}`); + } + } +} + +// ========== Factory Function ========== + +/** + * Create a PeerReviewIntegration from user config + */ +export function createPeerReviewIntegration( + userConfig: PeerReviewUserConfig, + llm?: BaseLanguageModel +): PeerReviewIntegration { + const issueTrackerConfig: IssueTrackerConfig = { + enabled: userConfig.enabled ?? false, + provider: (userConfig.provider as IssueTrackerType) || 'jira', + providerConfig: { + useMcp: userConfig.useMcp ?? true, + instanceUrl: userConfig.instanceUrl, + email: userConfig.email, + apiToken: userConfig.apiToken, + defaultProject: userConfig.defaultProject, + acceptanceCriteriaField: userConfig.acceptanceCriteriaField, + storyPointsField: userConfig.storyPointsField, + ticketPatterns: userConfig.ticketPatterns, + }, + analyzeAcceptanceCriteria: userConfig.analyzeAcceptanceCriteria ?? true, + rateTicketQuality: userConfig.rateTicketQuality ?? true, + generateTestSuggestions: userConfig.generateTestSuggestions ?? true, + checkScopeCreep: userConfig.checkScopeCreep ?? true, + ticketPatterns: userConfig.ticketPatterns, + includeTicketDetails: userConfig.includeTicketDetails ?? true, + verbose: userConfig.verbose ?? false, + }; + + return new PeerReviewIntegration(issueTrackerConfig, llm); +} + +// ========== User Config Type ========== + +/** + * User-facing configuration for peer review + * This is what goes in .pragent.config.json + */ +export interface PeerReviewUserConfig { + // Enable/disable peer review feature + enabled?: boolean; + + // Issue tracker provider + provider?: string; // 'jira' | 'linear' | 'azure-devops' | 'github-issues' + + // MCP-based access (preferred for Jira) + useMcp?: boolean; + + // Direct API access (fallback) + instanceUrl?: string; // e.g., "https://company.atlassian.net" + email?: string; + apiToken?: string; + + // Project settings + defaultProject?: string; + + // Custom field mappings (Jira-specific) + acceptanceCriteriaField?: string; + storyPointsField?: string; + + // Ticket patterns for extraction (regex) + ticketPatterns?: string[]; + + // Analysis settings + analyzeAcceptanceCriteria?: boolean; + rateTicketQuality?: boolean; + generateTestSuggestions?: boolean; + checkScopeCreep?: boolean; + + // Output settings + includeTicketDetails?: boolean; + verbose?: boolean; +} + +// ========== Output Formatting ========== + +/** + * Format peer review results for CLI output + */ +export function formatPeerReviewOutput(result: PeerReviewResult): string { + const lines: string[] = []; + + if (!result.enabled) { + return ''; // Silently skip if not enabled + } + + lines.push(''); + lines.push('═══════════════════════════════════════════════════════════════'); + lines.push(' 🔍 PEER REVIEW ANALYSIS'); + lines.push('═══════════════════════════════════════════════════════════════'); + lines.push(''); + + if (result.error) { + lines.push(`⚠️ ${result.error}`); + lines.push(''); + return lines.join('\n'); + } + + // Ticket Information + if (result.primaryTicket) { + const ticket = result.primaryTicket; + lines.push('📋 LINKED TICKET'); + lines.push('───────────────────────────────────────────────────────────────'); + lines.push(` Key: ${ticket.key}`); + lines.push(` Title: ${ticket.title}`); + lines.push(` Type: ${ticket.type.toUpperCase()}`); + lines.push(` Status: ${ticket.status}`); + if (ticket.storyPoints) { + lines.push(` Points: ${ticket.storyPoints}`); + } + lines.push(''); + } + + // Ticket Quality Rating + if (result.analysis?.ticketQuality) { + const quality = result.analysis.ticketQuality; + const scoreEmoji = getScoreEmoji(quality.overallScore); + + lines.push('📊 TICKET QUALITY RATING'); + lines.push('───────────────────────────────────────────────────────────────'); + lines.push(` Overall Score: ${scoreEmoji} ${quality.overallScore}/100 (${quality.tier.toUpperCase()})`); + lines.push(''); + lines.push(' Dimension Scores:'); + lines.push(` • Description Clarity: ${formatScore(quality.dimensions.descriptionClarity)}`); + lines.push(` • Acceptance Criteria: ${formatScore(quality.dimensions.acceptanceCriteriaQuality)}`); + lines.push(` • Testability: ${formatScore(quality.dimensions.testabilityScore)}`); + lines.push(` • Scope Definition: ${formatScore(quality.dimensions.scopeDefinition)}`); + lines.push(` • Technical Context: ${formatScore(quality.dimensions.technicalContext)}`); + lines.push(` • Visual Documentation: ${formatScore(quality.dimensions.visualDocumentation)}`); + lines.push(` • Completeness: ${formatScore(quality.dimensions.completeness)}`); + lines.push(''); + + if (!quality.reviewable) { + lines.push(` ⚠️ Ticket Not Reviewable: ${quality.reviewabilityReason}`); + lines.push(''); + } + + if (quality.feedback.weaknesses.length > 0) { + lines.push(' ⚠️ Ticket Weaknesses:'); + quality.feedback.weaknesses.forEach((w) => lines.push(` • ${w}`)); + lines.push(''); + } + } + + // Requirements Validation (derived from ticket analysis) + if (result.analysis?.acValidation) { + const validation = result.analysis.acValidation; + const complianceEmoji = getScoreEmoji(validation.compliancePercentage); + + lines.push('✅ REQUIREMENTS VALIDATION'); + lines.push('───────────────────────────────────────────────────────────────'); + lines.push(` Compliance: ${complianceEmoji} ${validation.compliancePercentage}%`); + lines.push(''); + + // Show derived requirements (what the agent understood from the ticket) + if (validation.derivedRequirements && validation.derivedRequirements.length > 0) { + lines.push(' 📋 DERIVED REQUIREMENTS (from ticket analysis):'); + validation.derivedRequirements.forEach((req) => { + const importanceIcon = { + essential: '🔴', + expected: '🟡', + nice_to_have: '🟢', + }[req.importance]; + const sourceLabel = { + description: 'desc', + explicit_ac: 'AC', + implied: 'implied', + ticket_type: 'type', + technical_context: 'tech', + }[req.source]; + lines.push(` ${importanceIcon} [${sourceLabel}] ${req.requirement}`); + }); + lines.push(''); + } + + // Show each requirement's validation status + lines.push(' 📊 REQUIREMENT STATUS:'); + validation.criteriaAnalysis.forEach((c) => { + const statusEmoji = { + met: '✅', + partial: '🟡', + unmet: '❌', + unclear: '❓', + }[c.status]; + lines.push(` ${statusEmoji} ${c.criteriaText.substring(0, 60)}${c.criteriaText.length > 60 ? '...' : ''}`); + if (c.status !== 'met') { + lines.push(` └─ ${c.explanation.substring(0, 70)}${c.explanation.length > 70 ? '...' : ''}`); + } + }); + lines.push(''); + + // Show gaps with impact + if (validation.gaps.length > 0) { + lines.push(' ❌ COVERAGE GAPS:'); + validation.gaps.forEach((gap) => { + const severityEmoji = { critical: '🔴', major: '🟠', minor: '🟡' }[gap.severity]; + lines.push(` ${severityEmoji} [${gap.severity.toUpperCase()}] ${gap.gapDescription}`); + lines.push(` └─ Impact: ${gap.impact}`); + }); + lines.push(''); + } + + // Show missing behaviors identified by the agent + if (validation.missingBehaviors && validation.missingBehaviors.length > 0) { + lines.push(' ⚠️ MISSING BEHAVIORS:'); + validation.missingBehaviors.forEach((b) => lines.push(` • ${b}`)); + lines.push(''); + } + } + + // Overall Peer Review Assessment + if (result.analysis?.peerReview) { + const review = result.analysis.peerReview; + + // Final verdict banner + const verdictEmoji = { + approve: '✅', + request_changes: '❌', + needs_discussion: '💬', + }[review.verdict.recommendation]; + const verdictText = { + approve: 'APPROVED', + request_changes: 'CHANGES REQUESTED', + needs_discussion: 'NEEDS DISCUSSION', + }[review.verdict.recommendation]; + + lines.push('🎯 PEER REVIEW VERDICT'); + lines.push('───────────────────────────────────────────────────────────────'); + lines.push(` ${verdictEmoji} ${verdictText} (Confidence: ${review.verdict.confidenceLevel}%)`); + lines.push(''); + lines.push(` ${review.verdict.summary}`); + lines.push(''); + + lines.push(' Scores:'); + lines.push(` • Implementation Completeness: ${formatScore(review.implementationCompleteness)}`); + lines.push(` • Quality Score: ${formatScore(review.qualityScore)}`); + lines.push(''); + + // Blockers with details + if (review.blockers.length > 0) { + lines.push(' 🚫 BLOCKERS (must fix before merge):'); + review.blockers.forEach((b) => { + lines.push(` • ${b.issue}`); + lines.push(` Reason: ${b.reason}`); + if (b.location) { + lines.push(` Location: ${b.location}`); + } + }); + lines.push(''); + } + + // Warnings with details + if (review.warnings.length > 0) { + lines.push(' ⚠️ WARNINGS (should address):'); + review.warnings.forEach((w) => { + lines.push(` • ${w.issue}`); + if (w.reason) { + lines.push(` Reason: ${w.reason}`); + } + }); + lines.push(''); + } + + // Regression risks - critical for senior dev perspective + if (review.regressionRisks && review.regressionRisks.length > 0) { + lines.push(' ⚡ POTENTIAL REGRESSION RISKS:'); + review.regressionRisks.forEach((r) => { + const likelihoodEmoji = { high: '🔴', medium: '🟠', low: '🟡' }[r.likelihood]; + lines.push(` ${likelihoodEmoji} ${r.risk}`); + lines.push(` Affected: ${r.affectedArea}`); + lines.push(` Why: ${r.reasoning}`); + }); + lines.push(''); + } + + // Uncovered scenarios - what the senior dev noticed isn't handled + if (review.uncoveredScenarios && review.uncoveredScenarios.length > 0) { + lines.push(' 🔍 SCENARIOS NOT HANDLED:'); + review.uncoveredScenarios.forEach((s) => { + const impactEmoji = { critical: '🔴', major: '🟠', minor: '🟡' }[s.impact]; + lines.push(` ${impactEmoji} ${s.scenario}`); + if (s.relatedCriteria) { + lines.push(` Related to: ${s.relatedCriteria}`); + } + }); + lines.push(''); + } + + // Scope analysis + if (review.scopeAnalysis.scopeCreepRisk) { + lines.push(' ⚠️ SCOPE CREEP DETECTED:'); + lines.push(` ${review.scopeAnalysis.scopeCreepDetails || 'Changes may exceed ticket scope'}`); + if (review.scopeAnalysis.outOfScope.length > 0) { + lines.push(' Out of scope changes:'); + review.scopeAnalysis.outOfScope.slice(0, 3).forEach((s) => lines.push(` • ${s}`)); + } + lines.push(''); + } + + // Recommendations + if (review.recommendations.length > 0) { + lines.push(' 💡 RECOMMENDATIONS:'); + review.recommendations.slice(0, 3).forEach((r) => lines.push(` • ${r}`)); + lines.push(''); + } + } + + lines.push('═══════════════════════════════════════════════════════════════'); + lines.push(''); + + return lines.join('\n'); +} + +function getScoreEmoji(score: number): string { + if (score >= 85) return '🟢'; + if (score >= 70) return '🟡'; + if (score >= 50) return '🟠'; + return '🔴'; +} + +function formatScore(score: number): string { + const emoji = getScoreEmoji(score); + const bar = '█'.repeat(Math.floor(score / 10)) + '░'.repeat(10 - Math.floor(score / 10)); + return `${emoji} ${bar} ${score}`; +} + +/** + * Format peer review results for GitHub PR comment + */ +export function formatPeerReviewMarkdown(result: PeerReviewResult): string { + if (!result.enabled || result.error) { + return ''; + } + + const lines: string[] = []; + + lines.push('## 🔍 Peer Review Analysis'); + lines.push(''); + + // Verdict banner at the top + if (result.analysis?.peerReview) { + const review = result.analysis.peerReview; + const verdictEmoji = { + approve: '✅', + request_changes: '❌', + needs_discussion: '💬', + }[review.verdict.recommendation]; + const verdictText = { + approve: 'APPROVED', + request_changes: 'CHANGES REQUESTED', + needs_discussion: 'NEEDS DISCUSSION', + }[review.verdict.recommendation]; + + lines.push(`### ${verdictEmoji} Verdict: ${verdictText}`); + lines.push(''); + lines.push(`> ${review.verdict.summary}`); + lines.push(''); + } + + // Ticket Information + if (result.primaryTicket) { + const ticket = result.primaryTicket; + lines.push(`### 📋 Linked Ticket: [${ticket.key}](${ticket.url})`); + lines.push(''); + lines.push(`**${ticket.title}**`); + lines.push(''); + lines.push(`| Property | Value |`); + lines.push(`|----------|-------|`); + lines.push(`| Type | ${ticket.type} |`); + lines.push(`| Status | ${ticket.status} |`); + if (ticket.storyPoints) { + lines.push(`| Story Points | ${ticket.storyPoints} |`); + } + lines.push(''); + } + + // Ticket Quality + if (result.analysis?.ticketQuality) { + const quality = result.analysis.ticketQuality; + lines.push('### 📊 Ticket Quality'); + lines.push(''); + lines.push(`**Overall Score: ${quality.overallScore}/100** (${quality.tier})`); + lines.push(''); + + if (!quality.reviewable) { + lines.push(`> ⚠️ **Warning:** ${quality.reviewabilityReason}`); + lines.push(''); + } + + if (quality.feedback.weaknesses.length > 0) { + lines.push('
'); + lines.push('Ticket Weaknesses'); + lines.push(''); + quality.feedback.weaknesses.forEach((w) => lines.push(`- ${w}`)); + lines.push(''); + lines.push('
'); + lines.push(''); + } + } + + // Requirements Validation (derived from ticket) + if (result.analysis?.acValidation) { + const validation = result.analysis.acValidation; + lines.push('### ✅ Requirements Validation'); + lines.push(''); + lines.push(`**Compliance: ${validation.compliancePercentage}%**`); + lines.push(''); + + // Show derived requirements + if (validation.derivedRequirements && validation.derivedRequirements.length > 0) { + lines.push('
'); + lines.push('📋 Derived Requirements (from ticket analysis)'); + lines.push(''); + lines.push('| Importance | Source | Requirement |'); + lines.push('|------------|--------|-------------|'); + validation.derivedRequirements.forEach((req) => { + const importanceEmoji = { essential: '🔴', expected: '🟡', nice_to_have: '🟢' }[req.importance]; + lines.push(`| ${importanceEmoji} ${req.importance} | ${req.source} | ${req.requirement} |`); + }); + lines.push(''); + lines.push('
'); + lines.push(''); + } + + lines.push('| Status | Requirement |'); + lines.push('|--------|-------------|'); + validation.criteriaAnalysis.forEach((c) => { + const statusEmoji = { met: '✅', partial: '🟡', unmet: '❌', unclear: '❓' }[c.status]; + lines.push(`| ${statusEmoji} ${c.status} | ${c.criteriaText.substring(0, 80)}${c.criteriaText.length > 80 ? '...' : ''} |`); + }); + lines.push(''); + + if (validation.gaps.length > 0) { + lines.push('#### ❌ Coverage Gaps'); + lines.push(''); + validation.gaps.forEach((gap) => { + lines.push(`- **[${gap.severity}]** ${gap.gapDescription}`); + lines.push(` - _Impact:_ ${gap.impact}`); + }); + lines.push(''); + } + } + + // Peer Review Details + if (result.analysis?.peerReview) { + const review = result.analysis.peerReview; + lines.push('### 🎯 Assessment Details'); + lines.push(''); + lines.push(`| Metric | Score |`); + lines.push(`|--------|-------|`); + lines.push(`| Implementation Completeness | ${review.implementationCompleteness}% |`); + lines.push(`| Quality Score | ${review.qualityScore}% |`); + lines.push(`| Confidence | ${review.verdict.confidenceLevel}% |`); + lines.push(''); + + if (review.blockers.length > 0) { + lines.push('#### 🚫 Blockers (Must Fix)'); + lines.push(''); + review.blockers.forEach((b) => { + lines.push(`- **${b.issue}**`); + lines.push(` - ${b.reason}`); + if (b.location) { + lines.push(` - 📍 ${b.location}`); + } + }); + lines.push(''); + } + + if (review.warnings.length > 0) { + lines.push('#### ⚠️ Warnings (Should Address)'); + lines.push(''); + review.warnings.forEach((w) => { + lines.push(`- **${w.issue}**`); + if (w.reason) { + lines.push(` - ${w.reason}`); + } + }); + lines.push(''); + } + + // Regression risks + if (review.regressionRisks && review.regressionRisks.length > 0) { + lines.push('
'); + lines.push('⚡ Potential Regression Risks'); + lines.push(''); + review.regressionRisks.forEach((r) => { + lines.push(`- **${r.risk}** (${r.likelihood} likelihood)`); + lines.push(` - Affects: ${r.affectedArea}`); + lines.push(` - Reason: ${r.reasoning}`); + }); + lines.push(''); + lines.push('
'); + lines.push(''); + } + + // Uncovered scenarios + if (review.uncoveredScenarios && review.uncoveredScenarios.length > 0) { + lines.push('
'); + lines.push('🔍 Scenarios Not Handled'); + lines.push(''); + review.uncoveredScenarios.forEach((s) => { + lines.push(`- **[${s.impact}]** ${s.scenario}`); + if (s.relatedCriteria) { + lines.push(` - Related to: ${s.relatedCriteria}`); + } + }); + lines.push(''); + lines.push('
'); + lines.push(''); + } + + // Scope creep + if (review.scopeAnalysis.scopeCreepRisk) { + lines.push('> ⚠️ **Scope Creep Detected:** ' + (review.scopeAnalysis.scopeCreepDetails || 'Changes may exceed ticket scope')); + lines.push(''); + } + } + + return lines.join('\n'); +} diff --git a/src/providers/index.ts b/src/providers/index.ts index 53e97cd..3533f79 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -3,4 +3,5 @@ export * from './provider.factory.js'; export * from './anthropic.provider.js'; export * from './openai.provider.js'; export * from './google.provider.js'; +export * from './zhipu.provider.js'; diff --git a/src/providers/provider.factory.ts b/src/providers/provider.factory.ts index ee7762d..50f7f6c 100644 --- a/src/providers/provider.factory.ts +++ b/src/providers/provider.factory.ts @@ -2,9 +2,10 @@ import { ILLMProvider, ProviderConfig } from './provider.interface.js'; import { AnthropicProvider } from './anthropic.provider.js'; import { OpenAIProvider } from './openai.provider.js'; import { GoogleProvider } from './google.provider.js'; +import { ZhipuProvider } from './zhipu.provider.js'; import { BaseChatModel } from '@langchain/core/language_models/chat_models'; -export type SupportedProvider = 'anthropic' | 'openai' | 'google'; +export type SupportedProvider = 'anthropic' | 'openai' | 'google' | 'zhipu'; export interface ProviderOptions { provider?: SupportedProvider; @@ -48,8 +49,11 @@ export class ProviderFactory { case 'google': provider = new GoogleProvider(apiKey); break; + case 'zhipu': + provider = new ZhipuProvider(apiKey); + break; default: - throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google`); + throw new Error(`Unsupported provider: ${providerName}. Supported: anthropic, openai, google, zhipu`); } // Cache the provider if no specific API key was provided @@ -109,6 +113,7 @@ export class ProviderFactory { const normalized = name.toLowerCase(); if (normalized === 'claude') return 'anthropic'; if (normalized === 'gemini') return 'google'; + if (normalized === 'glm' || normalized === 'zhipuai') return 'zhipu'; return normalized; } @@ -116,7 +121,7 @@ export class ProviderFactory { * Get list of available providers */ public static getAvailableProviders(): SupportedProvider[] { - return ['anthropic', 'openai', 'google']; + return ['anthropic', 'openai', 'google', 'zhipu']; } } diff --git a/src/providers/zhipu.provider.ts b/src/providers/zhipu.provider.ts new file mode 100644 index 0000000..3aa6f29 --- /dev/null +++ b/src/providers/zhipu.provider.ts @@ -0,0 +1,41 @@ +import { ChatAnthropic } from '@langchain/anthropic'; +import { BaseChatModel } from '@langchain/core/language_models/chat_models'; +import { ILLMProvider, ProviderConfig } from './provider.interface.js'; + +/** + * Zhipu AI (智谱AI) provider implementation + * Uses Anthropic-compatible API endpoint + * Docs: https://docs.z.ai/ + */ +export class ZhipuProvider implements ILLMProvider { + public readonly name = 'zhipu'; + private readonly apiKey: string; + private readonly baseUrl = 'https://api.z.ai/api/anthropic'; + + constructor(apiKey?: string) { + this.apiKey = apiKey || process.env.ZHIPU_API_KEY || ''; + } + + public isConfigured(): boolean { + return !!this.apiKey; + } + + public getDefaultModel(): string { + // GLM-4.7 is mapped to claude-sonnet-4-20250514 in Zhipu's Anthropic-compatible API + return 'claude-sonnet-4-20250514'; + } + + public getChatModel(config: ProviderConfig = {}): BaseChatModel { + if (!this.isConfigured()) { + throw new Error('Zhipu API key is not configured. Set ZHIPU_API_KEY environment variable.'); + } + + return new ChatAnthropic({ + anthropicApiKey: this.apiKey, + anthropicApiUrl: this.baseUrl, + modelName: config.model || this.getDefaultModel(), + temperature: config.temperature ?? 0.2, + maxTokens: config.maxTokens ?? 4000, + }); + } +} diff --git a/src/types.ts b/src/types.ts index c2d1c97..136370a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,7 @@ // PR Agent - Basic Types // Core types for PR analysis -export type AIProviderType = 'anthropic' | 'openai' | 'google'; +export type AIProviderType = 'anthropic' | 'openai' | 'google' | 'zhipu'; export interface PRInfo { number: number; diff --git a/src/types/issue-tracker.types.ts b/src/types/issue-tracker.types.ts new file mode 100644 index 0000000..6577ef5 --- /dev/null +++ b/src/types/issue-tracker.types.ts @@ -0,0 +1,211 @@ +/** + * Generic Issue Tracker Provider Interface + * + * This abstraction allows PR Agent to work with different issue tracking systems + * (Jira, Linear, Azure DevOps, GitHub Issues, etc.) through a unified interface. + * + * MVP: Jira implementation via Atlassian MCP + * Future: Linear, Azure DevOps, GitHub Issues, etc. + */ + +/** + * Normalized ticket/issue representation across all providers + */ +export interface IssueTicket { + // Core identifiers + id: string; // Provider-specific ID + key: string; // Human-readable key (e.g., "PROJ-123", "#456") + url: string; // Direct link to the ticket + + // Basic info + title: string; + description: string; + type: IssueType; + status: string; + priority: IssuePriority; + + // People + assignee?: string; + reporter?: string; + + // Categorization + labels: string[]; + components: string[]; + project?: string; + + // Estimates + storyPoints?: number; + estimate?: string; + + // Acceptance criteria - the key field for Peer Review Agent + acceptanceCriteria?: string; + acceptanceCriteriaList?: string[]; + + // Test information + testScenarios?: string[]; + linkedTestCases?: string[]; + + // Attachments and context + hasScreenshots: boolean; + hasDiagrams: boolean; + attachmentCount: number; + + // Relations + parentKey?: string; + epicKey?: string; + linkedIssues: LinkedIssue[]; + subtasks: SubtaskInfo[]; + + // Timestamps + createdAt: string; + updatedAt: string; + + // Raw provider-specific data for edge cases + rawData?: Record; +} + +export type IssueType = + | 'bug' + | 'feature' + | 'story' + | 'task' + | 'epic' + | 'subtask' + | 'improvement' + | 'spike' + | 'other'; + +export type IssuePriority = + | 'critical' + | 'high' + | 'medium' + | 'low' + | 'none'; + +export interface LinkedIssue { + key: string; + type: string; // "blocks", "is blocked by", "relates to", "duplicates", etc. + title: string; + status: string; +} + +export interface SubtaskInfo { + key: string; + title: string; + status: string; +} + +/** + * Reference to a ticket found in PR metadata + */ +export interface TicketReference { + key: string; + source: 'title' | 'description' | 'branch' | 'commit' | 'manual'; + rawMatch: string; // The actual text that matched + confidence: number; // 0-100 +} + +/** + * Issue tracker provider interface - implement this for each provider + */ +export interface IssueTrackerProvider { + /** + * Provider name for display and configuration + */ + readonly name: string; + + /** + * Provider type identifier + */ + readonly type: IssueTrackerType; + + /** + * Check if the provider is properly configured and accessible + */ + isConfigured(): boolean; + + /** + * Test connection to the provider + */ + testConnection(): Promise; + + /** + * Fetch a single ticket by key + */ + getTicket(key: string): Promise; + + /** + * Fetch multiple tickets by keys + */ + getTickets(keys: string[]): Promise; + + /** + * Extract ticket references from PR metadata + */ + extractTicketReferences(context: TicketExtractionContext): TicketReference[]; + + /** + * Search for tickets matching a query + */ + searchTickets?(query: string, limit?: number): Promise; + + /** + * Get ticket comments (if supported) + */ + getComments?(ticketKey: string): Promise; +} + +export type IssueTrackerType = + | 'jira' + | 'linear' + | 'azure-devops' + | 'github-issues' + | 'gitlab-issues' + | 'shortcut' + | 'asana' + | 'other'; + +export interface TicketExtractionContext { + prTitle: string; + prDescription?: string; + branchName?: string; + commitMessages?: string[]; +} + +export interface IssueComment { + id: string; + author: string; + body: string; + createdAt: string; +} + +/** + * Configuration for issue tracker integration + */ +export interface IssueTrackerConfig { + enabled: boolean; + provider: IssueTrackerType; + + // Provider-specific settings (varies by provider) + providerConfig: Record; + + // Analysis settings (common across providers) + analyzeAcceptanceCriteria: boolean; + rateTicketQuality: boolean; + generateTestSuggestions: boolean; + checkScopeCreep: boolean; + + // Ticket extraction patterns (regex) + ticketPatterns?: string[]; + + // Output settings + includeTicketDetails: boolean; + verbose: boolean; +} + +/** + * Factory function type for creating providers + */ +export type IssueTrackerProviderFactory = ( + config: IssueTrackerConfig +) => IssueTrackerProvider | null; diff --git a/src/types/jira.types.ts b/src/types/jira.types.ts new file mode 100644 index 0000000..3205d74 --- /dev/null +++ b/src/types/jira.types.ts @@ -0,0 +1,278 @@ +/** + * Jira types and interfaces for Peer Review Agent + * Provides structures for Jira ticket analysis and acceptance criteria validation + */ + +/** + * Jira ticket from the Atlassian API/MCP + */ +export interface JiraTicket { + key: string; // e.g., "PROJ-123" + id: string; // Jira internal ID + summary: string; // Ticket title + description: string; // Full description (may contain markdown/rich text) + status: string; // e.g., "In Progress", "In Review", "Done" + type: JiraTicketType; // bug, feature, task, story, epic + priority: string; // e.g., "High", "Medium", "Low" + assignee?: string; // Assignee display name + reporter?: string; // Reporter display name + labels: string[]; // Labels/tags + components: string[]; // Affected components + fixVersions: string[]; // Target release versions + storyPoints?: number; // Story points estimate + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + + // Acceptance criteria - can be in description or custom field + acceptanceCriteria?: string; // Extracted AC text + acceptanceCriteriaItems?: AcceptanceCriteriaItem[]; + + // Test-related fields + testScenarios?: string[]; // Listed test scenarios + testCases?: string[]; // Linked test cases + + // Additional context + attachments?: JiraAttachment[]; + linkedIssues?: JiraLinkedIssue[]; + comments?: JiraComment[]; + subtasks?: JiraSubtask[]; + parentKey?: string; // If this is a subtask + epicKey?: string; // Parent epic + + // Raw fields for custom field access + customFields?: Record; +} + +export type JiraTicketType = 'bug' | 'feature' | 'task' | 'story' | 'epic' | 'subtask' | 'improvement' | 'other'; + +export interface AcceptanceCriteriaItem { + id: string; // Generated ID for tracking + text: string; // The AC text + isMet?: boolean; // Whether this AC is covered by the PR + coverageDetails?: string; // Explanation of how it's covered + relatedFiles?: string[]; // Files that implement this AC + confidence: number; // 0-100 confidence in assessment +} + +export interface JiraAttachment { + id: string; + filename: string; + mimeType: string; + url: string; + createdAt: string; + isScreenshot: boolean; +} + +export interface JiraLinkedIssue { + key: string; + type: string; // "blocks", "is blocked by", "relates to", etc. + summary: string; + status: string; +} + +export interface JiraComment { + id: string; + author: string; + body: string; + createdAt: string; +} + +export interface JiraSubtask { + key: string; + summary: string; + status: string; +} + +/** + * Ticket quality rating based on best practices + */ +export interface TicketQualityRating { + overallScore: number; // 0-100 composite score + + // Individual dimension scores (0-100) + dimensions: { + descriptionClarity: number; // Is the description clear and complete? + acceptanceCriteriaQuality: number; // Are ACs specific, measurable, testable? + testabilityScore: number; // Are test scenarios/cases defined? + scopeDefinition: number; // Is scope well-defined and bounded? + technicalContext: number; // Are technical details/constraints provided? + visualDocumentation: number; // Screenshots, diagrams, mockups? + estimationQuality: number; // Story points reasonable for scope? + completeness: number; // Overall ticket completeness + }; + + // Detailed feedback for each dimension + feedback: { + strengths: string[]; // What's good about the ticket + weaknesses: string[]; // What's missing or unclear + suggestions: string[]; // How to improve the ticket + }; + + // Quality tier based on score + tier: 'excellent' | 'good' | 'adequate' | 'poor' | 'insufficient'; + + // Can we provide meaningful PR review with this ticket? + reviewable: boolean; + reviewabilityReason: string; +} + +/** + * Result of acceptance criteria validation against PR changes + */ +export interface AcceptanceCriteriaValidation { + ticketKey: string; + totalCriteria: number; + metCriteria: number; + unmetCriteria: number; + partialCriteria: number; + + // Detailed per-criteria analysis + criteriaAnalysis: CriteriaAnalysisItem[]; + + // Overall compliance percentage + compliancePercentage: number; + + // Summary of gaps + gaps: AcceptanceCriteriaGap[]; + + // Suggested test scenarios for uncovered cases + suggestedTestScenarios: TestScenarioSuggestion[]; +} + +export interface CriteriaAnalysisItem { + criteriaId: string; + criteriaText: string; + status: 'met' | 'unmet' | 'partial' | 'unclear'; + confidence: number; // 0-100 + evidence: string[]; // Code snippets or file references that show coverage + explanation: string; // Why we think it's met/unmet + relatedFiles: string[]; // Files that relate to this criteria +} + +export interface AcceptanceCriteriaGap { + criteriaText: string; + gapDescription: string; + severity: 'critical' | 'major' | 'minor'; + suggestedAction: string; +} + +export interface TestScenarioSuggestion { + scenario: string; // Test scenario description + type: 'unit' | 'integration' | 'e2e' | 'manual'; + priority: 'high' | 'medium' | 'low'; + relatedCriteria: string[]; // Which AC this tests + suggestedApproach: string; // How to implement the test +} + +/** + * Complete Jira analysis result for a PR + */ +export interface JiraAnalysisResult { + // Linked tickets found in PR + linkedTickets: JiraTicket[]; + primaryTicket?: JiraTicket; // Main ticket (first found or specified) + + // Ticket quality assessment + ticketQuality?: TicketQualityRating; + + // Acceptance criteria validation + acValidation?: AcceptanceCriteriaValidation; + + // Cross-reference with PR changes + scopeAnalysis: { + inScope: string[]; // Changes that align with ticket scope + outOfScope: string[]; // Changes that seem unrelated + scopeCreepRisk: boolean; + scopeCreepDetails?: string; + }; + + // Edge cases and test coverage + edgeCaseAnalysis: { + identifiedEdgeCases: string[]; + coveredEdgeCases: string[]; + uncoveredEdgeCases: string[]; + testSuggestions: TestScenarioSuggestion[]; + }; + + // Overall assessment + overallAssessment: { + implementationCompleteness: number; // 0-100 + qualityScore: number; // 0-100 + readyForReview: boolean; + blockers: string[]; + warnings: string[]; + recommendations: string[]; + }; + + // Metrics summary + metrics: { + ticketsCovered: number; + criteriaTotal: number; + criteriaMet: number; + criteriaPartial: number; + criteriaUnmet: number; + testScenariosGenerated: number; + }; +} + +/** + * Configuration for Jira integration + */ +export interface JiraConfig { + enabled: boolean; + + // MCP connection settings + mcpServerUrl?: string; // If using custom MCP server + + // Jira instance settings (for direct API if needed) + instanceUrl?: string; // e.g., "https://company.atlassian.net" + projectKey?: string; // Default project key + + // Authentication (via MCP or direct) + apiToken?: string; // Jira API token + email?: string; // Jira account email + + // Analysis settings + analyzeAcceptanceCriteria: boolean; + rateTicketQuality: boolean; + generateTestSuggestions: boolean; + checkScopeCreep: boolean; + + // Output settings + includeTicketDetailsInOutput: boolean; + verboseOutput: boolean; +} + +/** + * Ticket reference extracted from PR title/description/branch + */ +export interface TicketReference { + key: string; // e.g., "PROJ-123" + source: 'title' | 'description' | 'branch' | 'commit'; + confidence: number; // How confident we are this is the right ticket +} + +/** + * Context passed to Jira sub-agent + */ +export interface JiraAnalysisContext { + prTitle: string; + prDescription?: string; + branchName?: string; + commitMessages?: string[]; + diff: string; + files: Array<{ + path: string; + additions: number; + deletions: number; + status: string; + }>; + + // Pre-analyzed PR data + prSummary?: string; + prRisks?: string[]; + prComplexity?: number; + + // Jira config + config: JiraConfig; +} diff --git a/src/utils/config-validator.ts b/src/utils/config-validator.ts index 9e00c6a..5d24413 100644 --- a/src/utils/config-validator.ts +++ b/src/utils/config-validator.ts @@ -15,11 +15,12 @@ export const UserConfigSchema = z.object({ anthropic: z.string().optional(), openai: z.string().optional(), google: z.string().optional(), + zhipu: z.string().optional(), }) .optional(), ai: z .object({ - provider: z.enum(['anthropic', 'openai', 'google']).optional(), + provider: z.enum(['anthropic', 'openai', 'google', 'zhipu']).optional(), model: z.string().optional(), temperature: z.number().min(0).max(2).optional(), maxTokens: z.number().positive().int().optional(), @@ -66,6 +67,26 @@ export const UserConfigSchema = z.object({ showRecommendations: z.boolean().optional(), }) .optional(), + peerReview: z + .object({ + enabled: z.boolean().optional(), + provider: z.string().optional(), + useMcp: z.boolean().optional(), + instanceUrl: z.string().url().optional(), + email: z.string().email().optional(), + apiToken: z.string().optional(), + defaultProject: z.string().optional(), + acceptanceCriteriaField: z.string().optional(), + storyPointsField: z.string().optional(), + ticketPatterns: z.array(z.string()).optional(), + analyzeAcceptanceCriteria: z.boolean().optional(), + rateTicketQuality: z.boolean().optional(), + generateTestSuggestions: z.boolean().optional(), + checkScopeCreep: z.boolean().optional(), + includeTicketDetails: z.boolean().optional(), + verbose: z.boolean().optional(), + }) + .optional(), }); /**