Skill: praveenspeaks/cinematic-script-writer (version 1.4.6)

--- name: cinematic-script-writer version: 1.4.0 description: "Create professional cinematic scripts for AI video generation with character consistency and cinematography knowledge. Use when the user wants to write a cinematic script, create story contexts with characters, generate image prompts for AI video tools (Midjourney, Sora, Veo), or needs cinematography guidance (camera angles, lighting, color grading). Also use for character consistency sheets, voice profiles, anachronism detection, and saving scripts to Google Drive." metadata: openclaw: emoji: "🎬" requires: bins: - node install: - id: npm-install kind: npm package: "cinematic-script-writer" bins: - cinematic-script tags: - creative - video - script - cinematography - youtube - camera - lighting - consistency - character-design - voice - era-accurate - storage - google-drive --- # Cinematic Script Writer Create professional cinematic scripts for AI video generation with character consistency and cinematography knowledge. ## Installation ```bash # Install via npm npm install -g cinematic-script-writer # Or install via OpenClaw CLI openclaw skills install cinematic-script-writer ``` ## CLI Usage ### Context Management Create and manage story contexts with characters, era, and settings: ```bash # Create a new story context cinematic-script create-context --name "My Story" --era "Ancient India" --period "Ramayana Era" # List all saved contexts cinematic-script list-contexts # Get a specific context cinematic-script get-context --id <context-id> # Delete a context cinematic-script delete-context --id <context-id> ``` ### Story Generation Generate story ideas and create cinematic scripts: ```bash # Generate story ideas for a context cinematic-script generate-ideas --context-id <context-id> --count 3 # Create a full cinematic script from an idea cinematic-script create-script --context-id <context-id> --idea-id <idea-id> # Generate YouTube metadata for a script cinematic-script generate-metadata --script-id <script-id> ``` ### Cinematography Reference Access camera angles, lighting, and shot type databases: ```bash # List all camera angles cinematic-script list-angles # List all camera movements cinematic-script list-movements # List all shot types cinematic-script list-shots # Get camera setup recommendation cinematic-script suggest-camera --scene-type "dialogue" --mood "dramatic" # Get lighting suggestions cinematic-script suggest-lighting --scene-type "interior" --mood "mysterious" # Get color grading suggestions cinematic-script suggest-grading --genre "action" # Search cinematography database cinematic-script search --query "low angle lighting" ``` ### Character Consistency Create character references and validate prompts: ```bash # Create a character reference sheet cinematic-script create-character-ref --character-id "char1" --name "Kutil" --visual "Purple rakshasa with golden eyes" --era "Ancient" --style "Pixar 3D" # Create a voice profile for dialogue consistency cinematic-script create-voice --character-id "char1" --name "Kutil" --personality "Mischievous, witty" --age "adult" --role "protagonist" # Validate a prompt for anachronisms cinematic-script validate-prompt --prompt "Your prompt here" --character-ids "char1,char2" --context-id <context-id> ``` ### Storage Save projects to Google Drive or local storage: ```bash # Connect to Google Drive cinematic-script connect-drive # Connect to local storage cinematic-script connect-local # Check storage connection status cinematic-script storage-status # Save project to storage cinematic-script save --title "My Story" --context-id <context-id> --script-id <script-id> ``` Storage implementation details: - **Google Drive**: Uses Google OAuth2 for authentication. Credentials are stored securely in memory. - **Local Storage**: Saves to the user's downloads folder as fallback. - **Library**: Uses `googleapis` for Google Drive integration. ### Export Export scripts in various formats: ```bash # Export as Markdown (default) cinematic-script export --script-id <script-id> --format markdown # Export as JSON cinematic-script export --script-id <script-id> --format json # Export as plain text cinematic-script export --script-id <script-id> --format text ``` ## Features - **Story Context Management**: Create and manage story settings, characters, and eras - **Story Idea Generation**: Generate multiple story concepts with hooks and twists - **Cinematic Script Writing**: Full scripts with camera angles, lighting, and shot types - **Character Consistency**: Reference sheets and voice profiles for consistent characters - **Environment Consistency**: Era-appropriate style guides and anachronism detection - **YouTube Metadata**: Generate titles, descriptions, and SEO tags - **Storage Integration**: Save to Google Drive or local storage - **Export Options**: JSON, Markdown, or plain text formats ## When to Use - Writing cinematic scripts or screenplays - Creating stories with characters for animation/video - Generating image/video prompts for AI tools (Midjourney, Sora, Veo, Runway) - Getting cinematography guidance (camera angles, lighting, color grading) - Maintaining character consistency across scenes - Saving script projects to Google Drive ## Cinematography Reference ### Camera Angles | Angle | Emotional Impact | Best For | |-------|-----------------|----------| | Eye-level | Connection, equality, neutrality | Dialogue, emotional moments | | Low-angle | Power, dominance, heroism | Villain reveals, hero moments | | High-angle | Vulnerability, weakness, overview | Defeat, establishing scale | | Bird-eye | Insignificance, detachment, patterns | Epic scale, isolation | | Worm-eye | Awe, grandeur, overwhelming presence | Monuments, giants, deities | | Dutch angle | Unease, disorientation, tension | Chaos, dreams, horror | | Overhead | Omniscience, surveillance | Table scenes, fight choreography | | Shoulder-level | Intimate, casual, documentary feel | Walking conversations | | Hip-level | Cowboy feel, casual tension | Westerns, standoffs | | Knee-level | Childlike perspective, grounding | Children's stories, humility | ### Camera Movements | Movement | Effect | Use For | |----------|--------|---------| | Static | Stability, observation | Contemplation, portraits | | Pan | Revealing space | Following action horizontally | | Tilt | Revealing height | Following vertical action | | Dolly | Immersion, intimacy | Moving toward/away from subject | | Truck | Following action | Side-to-side parallel movement | | Crane | Epic scale, drama | Sweeping reveals, transitions | | Handheld | Urgency, realism | Documentary, action, chaos | | Steadicam | Smooth floating | Following through space, dreams | | Zoom | Sudden focus, surprise | Dramatic emphasis, comedy | | Rack-focus | Revealing connections | Shifting attention between subjects | ### Shot Types | Shot | Framing | Emotional Impact | |------|---------|-----------------| | Establishing | Wide location | Sets scene, geography, time | | Wide/Full | Subject + surroundings | Context, environment, scale | | Medium | Waist up | Dialogue, body language | | Close-up | Head/shoulders | Emotion, reaction, intimacy | | Extreme close-up | Detail only (eyes, hands) | Intense emotion, symbolism | | Over-shoulder | Past one subject to another | Conversation, perspective | | POV | Character's view | Immersion, subjectivity | | Insert | Object detail | Plot info, symbolism | | Two-shot | Two subjects together | Relationship, tension | ### Lighting Techniques | Technique | Mood | Best For | |-----------|------|----------| | Three-point | Professional, balanced | Dialogue, interviews | | High-key | Happy, optimistic, bright | Comedy, commercials | | Low-key | Dramatic, mysterious | Drama, horror, noir | | Golden-hour | Romantic, nostalgic, magical | Romance, emotional moments | | Blue-hour | Melancholic, mysterious | Urban, cityscapes | | Chiaroscuro | Dramatic contrast | Art films, period pieces | | Rim/backlight | Separation, ethereal | Silhouettes, divine presence | | Practical | Realistic, natural | Candles, fires, lamps | | God-rays | Divine, revelation | Spiritual moments, forests | | Neon | Urban, futuristic | Cyberpunk, nightlife | ### Color Grading | Style | Look | Genre | |-------|------|-------| | Teal-orange | Blockbuster cinematic | Action, sci-fi | | Noir | High-contrast desaturated | Crime, mystery | | Vintage/sepia | Warm, nostalgic | Period pieces, memory | | Pastel | Soft, dreamy | Romance, coming-of-age | | Bleach bypass | Desaturated, gritty | War, thriller | | Cross-process | Surreal colors | Music videos, dreams | ## Image Prompt Format When generating image prompts for AI tools: ``` [Shot type] [camera angle] of [subject doing action], [visual style] style, [lighting technique], [composition rule], [color grading], [era-appropriate details], [mood keywords], highly detailed, cinematic ``` Example: ``` Low-angle close-up of Kutil the purple rakshasa with mischievous golden eyes, Pixar 3D style, dramatic underlighting with rim light, rule-of-thirds composition, warm golden color grading, ancient Lanka palace background with ornate pillars, playful yet mysterious mood, highly detailed, cinematic, 8k ``` ## Output Structure When saving a project, the following files are generated: ``` Story Title/ ├── 00_INDEX.md # Navigation ├── 01_SCRIPT_README.md # Human-readable script ├── 02_IMAGE_PROMPTS.md # All AI generation prompts ├── 03_CHARACTER_REFS.md # Character design guides ├── 04_VOICE_GUIDES.md # Dialogue consistency guides ├── 05_YOUTUBE_META.md # Title, description, tags └── 99_CONTEXT_INFO.md # Story context and background ``` ## Important Rules 1. **Always maintain character consistency** - include character's full visual description in every image prompt 2. **Never include anachronisms** - validate props, clothing, objects against the era 3. **Match cinematography to emotion** - use low angles for power, high angles for vulnerability 4. **Include both image and video prompts** - image prompts are static, video prompts describe motion 5. **Production-ready output** - every script should include enough detail for a team to produce it 6. **Respect the tone** - comedy needs comedic timing; drama needs longer holds on reactions ## License MIT ## Author Praveen Kumar

path: .eslintrc.json
content: {
  "env": {
    "browser": true,
    "es2021": true,
    "node": true
  },
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": [
    "@typescript-eslint"
  ],
  "rules": {
    "@typescript-eslint/no-explicit-any": "off",
    "@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
    "prefer-const": "warn",
    "no-console": "off"
  },
  "ignorePatterns": [
    "dist/",
    "node_modules/"
  ]
}


path: CHANGELOG.md
content: # Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.3.0] - 2026-02-10

### Added
- **Google Drive Storage Integration**
  - Save all generated content to Google Drive
  - Organized folders with story title
  - OAuth authentication
  - Local storage option (downloads)
  - Complete project export (script, prompts, consistency, voice, metadata)
  - Shareable links

### New Files
- `storage-adapter.ts` - Storage adapters (Google Drive, Local)
- `storage-manager.ts` - File organization and saving
- `EXAMPLE-STORAGE.md` - Storage usage examples

## [1.2.0] - 2026-02-10

### Added
- **Consistency System**
  - Character reference sheets for visual consistency
  - Voice profiles for dialogue consistency
  - Environment style guides for era-appropriate content
  - Prompt builder with consistency enforcement
  - Anachronism detection (validates era-appropriate elements)
  - Validation system for prompts

### New Files
- `consistency-system.ts` - Consistency management
- `prompt-builder.ts` - Consistent prompt generation
- `EXAMPLE-CONSISTENCY.md` - Consistency examples

## [1.1.0] - 2026-02-10

### Added
- **Comprehensive Cinematography Database**
  - 20+ camera angles with emotional impact
  - 20+ camera movements
  - 25+ shot types
  - 30+ lighting techniques
  - 20+ composition rules
  - 20+ color grading styles
  - 25+ visual aesthetics
  - 15+ genre cinematography guides
  - Indian cinematography styles

### New Files
- `cinematography-db.ts` - Camera techniques database
- `cinematography-api.ts` - Unified API
- `lighting-db.ts` - Lighting and composition
- `visual-styles-db.ts` - Visual aesthetics

## [1.0.0] - 2026-02-10

### Added
- Initial release of Cinematic Script Writer Skill
- Context management (characters, era, settings)
- Story idea generation
- Cinematic script creation with shots and camera angles
- Image/Video generation prompts
- YouTube metadata generation
- Basic camera techniques

### Files
- `skill-template/` - Template for creating new skills
- `examples/` - Example skills (weather, todo, file-manager)
- `skills/cinematic-script-writer/` - Main skill implementation
- `EXAMPLE-KUTIL.md` - Complete usage example


path: CONTRIBUTING.md
content: # Contributing to OpenClaw Skills

Thank you for your interest in contributing! This document provides guidelines for contributing to this project.

## How to Contribute

### Reporting Bugs

- Check if the bug has already been reported in [Issues](../../issues)
- Include a clear description of the bug
- Provide steps to reproduce
- Include error messages and stack traces
- Specify your environment (OS, Node.js version, etc.)

### Suggesting Features

- Check if the feature has already been suggested in [Issues](../../issues)
- Describe the feature and its use case
- Explain why it would be useful

### Pull Requests

1. Fork the repository
2. Create a new branch: `git checkout -b feature/your-feature-name`
3. Make your changes
4. Add tests if applicable
5. Ensure all tests pass: `npm test`
6. Commit your changes: `git commit -am 'Add new feature'`
7. Push to the branch: `git push origin feature/your-feature-name`
8. Submit a pull request

## Development Setup

```bash
# Clone your fork
git clone https://github.com/yourusername/openclawskills.git
cd openclawskills

# Install dependencies
npm install

# Run tests
npm test

# Build
npm run build
```

## Code Style

- Use TypeScript for type safety
- Follow existing code formatting
- Add JSDoc comments for public methods
- Keep functions focused and modular

## Commit Messages

- Use present tense ("Add feature" not "Added feature")
- Use imperative mood ("Move cursor to..." not "Moves cursor to...")
- Reference issues and pull requests where appropriate

## License

By contributing, you agree that your contributions will be licensed under the MIT License.


path: README.md
content: # Cinematic Script Writer Skill

[![CI](https://github.com/yourusername/openclawskills/actions/workflows/ci.yml/badge.svg)](https://github.com/yourusername/openclawskills/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.0-blue.svg)](https://www.typescriptlang.org/)

> Professional cinematic script generation for AI video creation with character consistency, comprehensive cinematography knowledge, and Google Drive integration.

## Features

| Feature | Description |
|---------|-------------|
| **175+ Cinematography Techniques** | Camera angles, movements, shots, lighting, composition |
| **Character Consistency** | Reference sheets ensuring same appearance across all shots |
| **Voice Consistency** | Speech profiles for consistent dialogue |
| **Environment Consistency** | Era-appropriate architecture, clothing, props |
| **Anachronism Detection** | Validates no modern elements in historical settings |
| **Google Drive Integration** | Auto-save all content to organized folders |
| **YouTube Metadata** | Titles, descriptions, tags for upload |
| **CLI Tool** | `cinematic-script` command for all operations |

## Quick Start

```bash
# Install globally
npm install -g cinematic-script-writer

# Create a story context
cinematic-script create-context --name "My Story" --genre comedy --era "Modern"

# Browse cinematography techniques
cinematic-script list-angles
cinematic-script suggest-lighting --scene-type interior-day --mood comedy
```

See [SKILL.md](SKILL.md) for full CLI documentation.

## Repository Structure

```
openclawskills/
├── SKILL.md                         # Skill definition (ClawHub auto-detects this)
├── bin/
│   └── cinematic-script.ts          # CLI entry point
├── skills/
│   └── cinematic-script-writer/     # Main skill implementation
│       ├── index.ts                 # Main class
│       ├── skill.json               # Tool definitions (55 methods)
│       ├── cinematography-*.ts      # Camera techniques database
│       ├── consistency-*.ts         # Consistency system
│       ├── storage-*.ts             # Storage system
│       └── EXAMPLE-*.md             # Usage examples
├── examples/                        # Reference skill examples
├── skill-template/                  # Template for new skills
├── README.md                        # This file
└── SETUP-GUIDE.md                   # Complete setup guide
```

## Publishing to ClawHub

1. **Push to GitHub** (make repo public):
   ```bash
   git remote add origin https://github.com/YOUR_USERNAME/openclawskills.git
   git push -u origin main
   ```

2. **Import to ClawHub**:
   - Go to https://clawhub.ai/import
   - Enter your GitHub URL
   - Click **Detect** - it will find `SKILL.md` automatically
   - Fill in details and click **Publish**

ClawHub auto-updates when you push new commits.

## Development

```bash
# Install dependencies
npm install

# Build
npm run build

# Test
npm test

# Lint
npm run lint
```

## Documentation

- [SKILL.md](SKILL.md) - Full skill definition and CLI reference
- [SETUP-GUIDE.md](SETUP-GUIDE.md) - Complete setup and testing guide
- [skills/cinematic-script-writer/EXAMPLE-KUTIL.md](skills/cinematic-script-writer/EXAMPLE-KUTIL.md) - Complete Kutil example
- [skills/cinematic-script-writer/EXAMPLE-CONSISTENCY.md](skills/cinematic-script-writer/EXAMPLE-CONSISTENCY.md) - Consistency guide
- [skills/cinematic-script-writer/EXAMPLE-STORAGE.md](skills/cinematic-script-writer/EXAMPLE-STORAGE.md) - Storage guide

## Requirements

- Node.js 18+
- TypeScript 5.0+
- OpenClaw Agent with memory permissions

## License

MIT License - see [LICENSE](LICENSE)

---

**Made for OpenClaw**


path: SETUP-GUIDE.md
content: # 📖 Complete Setup, Testing & Publishing Guide

This guide walks you through:
1. Creating a GitHub repository
2. Testing the skill
3. Publishing to ClawHub

---

## Step 1: Create GitHub Repository

### Option A: Using GitHub Website (Recommended)

1. **Go to GitHub**: https://github.com/new

2. **Create New Repository**:
   - Repository name: `Cinematic-Writer`
   - Description: `OpenClaw skill for cinematic script generation with consistency and storage`
   - Make it **Public** (or Private if you prefer)
   - **DON'T** initialize with README (we already have one)
   - Click "Create repository"

3. **Connect Local Repository**:
   ```bash
   # In your terminal (PowerShell/CMD), navigate to the project
   cd "D:\My Professional Projects\openclawskills"
   
   # Add the GitHub remote
   git remote add origin https://github.com/YOUR_USERNAME/openclaw-cinematic-writer.git
   
   # Rename branch to main
   git branch -M main
   
   # Push to GitHub
   git push -u origin main
   ```

4. **Verify**: Visit `https://github.com/YOUR_USERNAME/openclaw-cinematic-writer`

### Option B: Using GitHub CLI

```bash
# Install GitHub CLI if not already installed
# https://cli.github.com/

# Login to GitHub
gh auth login

# Create repository from current directory
gh repo create openclaw-cinematic-writer --public --source=. --push
```

---

## Step 2: Testing the Skill

### A. TypeScript Compilation Test

```bash
# Navigate to project
cd "D:\My Professional Projects\openclawskills"

# Install dependencies
npm install

# Build/compile TypeScript
npm run build

# Check for compilation errors
# Should create dist/ folder with compiled JS
```

### B. Lint Test

```bash
# Check code style
npm run lint

# Fix auto-fixable issues
npm run lint:fix
```

### C. Manual Testing Script

Create a test file `test-skill.ts`:

```typescript
import { CinematicScriptWriter } from './skills/cinematic-script-writer';

// Mock context for testing
const mockContext = {
  userId: 'test-user',
  memory: {
    get: async () => null,
    set: async () => {},
    delete: async () => {}
  },
  logger: {
    debug: console.log,
    info: console.log,
    warn: console.warn,
    error: console.error
  }
};

async function testSkill() {
  console.log('🧪 Testing Cinematic Script Writer Skill\n');
  
  const skill = new CinematicScriptWriter({}, mockContext);
  
  // Test 1: Cinematography Database
  console.log('✓ Testing Cinematography Database...');
  const angles = skill.getAllCameraAngles();
  console.log(`  - Found ${Object.keys(angles).length} camera angles`);
  
  const movements = skill.getAllCameraMovements();
  console.log(`  - Found ${Object.keys(movements).length} camera movements`);
  
  const shots = skill.getAllShotTypes();
  console.log(`  - Found ${Object.keys(shots).length} shot types`);
  
  // Test 2: Consistency System
  console.log('\n✓ Testing Consistency System...');
  const charRef = skill.createCharacterReference(
    'test-char',
    'Test Character',
    'Purple fur, golden eyes',
    'Ramayana Era',
    'pixar-3d'
  );
  console.log(`  - Created character reference: ${charRef.characterName}`);
  
  // Test 3: Environment Guide
  console.log('\n✓ Testing Environment Guide...');
  const envGuide = skill.createEnvironmentStyleGuide(
    'test-context',
    'Ramayana Era',
    'Treta Yuga',
    'Lanka',
    'pixar-3d'
  );
  console.log(`  - Created environment guide: ${envGuide.era}`);
  console.log(`  - Forbidden items: ${envGuide.eraSpecs.anachronismsForbidden.slice(0, 3).join(', ')}...`);
  
  // Test 4: Validation
  console.log('\n✓ Testing Anachronism Validation...');
  const badResult = skill.validatePrompt(
    'Character wearing sunglasses',
    ['test-char'],
    'test-context'
  );
  console.log(`  - Detected anachronism: ${!badResult.valid}`);
  console.log(`  - Errors: ${badResult.errors.join(', ')}`);
  
  // Test 5: Prompt Builder
  console.log('\n✓ Testing Prompt Builder...');
  const prompts = skill.buildConsistentPrompts({
    characterIds: ['test-char'],
    contextId: 'test-context',
    shotType: 'close-up',
    cameraAngle: 'eye-level',
    cameraMovement: 'static',
    lighting: 'golden-hour',
    mood: 'happy'
  });
  console.log(`  - Generated image prompt length: ${prompts.imagePrompt.length} chars`);
  console.log(`  - Generated negative prompt length: ${prompts.negativePrompt.length} chars`);
  
  console.log('\n✅ All tests passed!');
}

testSkill().catch(console.error);
```

Run the test:
```bash
npx ts-node test-skill.ts
```

### D. Testing Storage (Manual)

```typescript
// Test storage connection
async function testStorage() {
  const skill = new CinematicScriptWriter({}, mockContext);
  
  // Check status
  const status = await skill.getStorageStatus();
  console.log('Storage status:', status);
  
  // Test Google Drive connection (requires auth)
  // const result = await skill.connectGoogleDrive();
  // console.log('Auth URL:', result.authUrl);
}
```

---

## Step 3: Publishing to ClawHub

### Prerequisites

1. ✅ GitHub repository created
2. ✅ All code committed
3. ✅ README.md is complete
4. ✅ skill.json is properly configured
5. ✅ Tests pass

### ClawHub Submission Process

#### Option 1: Web Interface (Recommended for first time)

1. **Visit ClawHub**: https://clawhub.ai/publish

2. **Fill in the form**:

   ```yaml
   # Basic Information
   Skill Name: cinematic-script-writer
   Version: 1.3.0
   Description: Professional cinematic script generation with character consistency, 
                comprehensive cinematography (175+ techniques), and Google Drive storage.
   
   # Repository
   GitHub URL: https://github.com/YOUR_USERNAME/openclaw-cinematic-writer
   License: MIT
   
   # Entry Point
   Main File: skills/cinematic-script-writer/index.ts
   
   # Configuration
   Config Schema: skills/cinematic-script-writer/schema.json
   
   # Permissions Required
   Permissions:
     - memory:read    (Store/retrieve contexts, scripts)
     - memory:write   (Save generated content)
     - http:request   (Google Drive API)
   
   # Tags
   Tags:
     - creative
     - video
     - script
     - cinematography
     - consistency
     - character-design
     - voice
     - storage
     - google-drive
     - youtube
   
   # Documentation
   README: https://github.com/YOUR_USERNAME/openclaw-cinematic-writer/blob/main/README.md
   Examples: 
     - https://github.com/YOUR_USERNAME/openclaw-cinematic-writer/blob/main/skills/cinematic-script-writer/EXAMPLE-KUTIL.md
   ```

3. **Upload or Provide**:
   - Screenshot/demo GIF (optional but recommended)
   - Video tutorial link (optional)

4. **Submit** and wait for review (usually 1-3 days)

#### Option 2: ClawHub CLI (When Available)

```bash
# Install ClawHub CLI
npm install -g @clawhub/cli

# Login
clawhub login

# Publish from repository
clawhub publish

# Or specify directory
clawhub publish ./skills/cinematic-script-writer
```

#### Option 3: API Submission (Advanced)

```bash
# Create skill bundle
cd skills/cinematic-script-writer
tar -czvf cinematic-script-writer-v1.3.0.tar.gz .

# Submit via API (requires API key from ClawHub)
curl -X POST https://api.clawhub.ai/v1/skills \
  -H "[REDACTED_SECRET]" \
  -H "Content-Type: multipart/form-data" \
  -F "name=cinematic-script-writer" \
  -F "version=1.3.0" \
  -F "bundle=@cinematic-script-writer-v1.3.0.tar.gz" \
  -F "repository=https://github.com/YOUR_USERNAME/openclaw-cinematic-writer"
```

---

## Step 4: Post-Publication

### Create GitHub Release

1. Go to GitHub → Releases → "Draft a new release"
2. Choose tag: `v1.3.0`
3. Title: `v1.3.0 - Cinematic Script Writer`
4. Description:
   ```markdown
   ## What's New
   - Google Drive storage integration
   - Character/voice/environment consistency
   - 175+ cinematography techniques
   - Anachronism detection
   - YouTube metadata generation
   
   ## Installation
   ```bash
   npx clawhub@latest install cinematic-script-writer
   ```
   ```
5. Publish release

### Announce

- Share on Twitter/X with #OpenClaw hashtag
- Post in OpenClaw Discord/community
- Write a blog post about your skill

---

## Troubleshooting

### Git Push Issues

```bash
# If you get "fatal: unable to access"
# Make sure you're using HTTPS URL
git remote set-url origin https://github.com/YOUR_USERNAME/openclaw-cinematic-writer.git

# Or use SSH
git remote set-url origin [REDACTED_SECRET]:YOUR_USERNAME/openclaw-cinematic-writer.git
```

### Build Errors

```bash
# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

# Check TypeScript version
npx tsc --version  # Should be 5.0+
```

### ClawHub Rejection

Common reasons and fixes:

| Issue | Fix |
|-------|-----|
| Missing documentation | Add more examples in README |
| Tests fail | Fix errors and add more tests |
| Security concerns | Review and limit permissions |
| Code quality | Run linter, add comments |
| Duplicate skill | Ensure unique functionality |

---

## Quick Reference

```bash
# Full workflow
npm install          # Install dependencies
npm run build        # Compile TypeScript
npm run lint         # Check code style
npm test             # Run tests
git add .            # Stage changes
git commit -m "..."  # Commit
git push origin main # Push to GitHub

# ClawHub commands
clawhub validate     # Validate skill before publishing
clawhub publish      # Publish to ClawHub
clawhub update       # Update published skill
```

---

## Need Help?

- **ClawHub Docs**: https://clawhub.ai/docs
- **OpenClaw Community**: [Discord](https://discord.gg/openclaw)
- **GitHub Issues**: Create issue in your repo

Good luck! 🚀


path: bin/cinematic-script.ts
content: #!/usr/bin/env node

/**
 * Cinematic Script Writer CLI
 * Thin wrapper around the CinematicScriptWriter class for shell usage.
 */

import { CinematicScriptWriter, SkillConfig, SkillContext } from '../skills/cinematic-script-writer/index';

// ---------------------------------------------------------------------------
// Minimal in-memory implementations of MemoryStore and Logger
// ---------------------------------------------------------------------------

const memoryData = new Map<string, any>();

const memory = {
  async get(key: string) { return memoryData.get(key) ?? null; },
  async set(key: string, value: any) { memoryData.set(key, value); },
  async delete(key: string) { memoryData.delete(key); },
};

const logger = {
  debug(msg: string) { if (process.env.DEBUG) console.error('[debug]', msg); },
  info(msg: string) { console.error('[info]', msg); },
  warn(msg: string) { console.error('[warn]', msg); },
  error(msg: string) { console.error('[error]', msg); },
};

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function createSkill(): CinematicScriptWriter {
  const config: SkillConfig = {};
  const context: SkillContext = { userId: 'cli-user', memory, logger };
  return new CinematicScriptWriter(config, context);
}

function printJson(data: any): void {
  console.log(JSON.stringify(data, null, 2));
}

function requiredArg(args: string[], flag: string): string {
  const idx = args.indexOf(flag);
  if (idx === -1 || idx + 1 >= args.length) {
    console.error(`Missing required argument: ${flag}`);
    process.exit(1);
  }
  return args[idx + 1];
}

function optionalArg(args: string[], flag: string, fallback: string): string {
  const idx = args.indexOf(flag);
  if (idx === -1 || idx + 1 >= args.length) return fallback;
  return args[idx + 1];
}

// ---------------------------------------------------------------------------
// Command handlers
// ---------------------------------------------------------------------------

const commands: Record<string, (skill: CinematicScriptWriter, args: string[]) => Promise<void>> = {

  // -- Context Management ---------------------------------------------------

  'create-context': async (skill, args) => {
    const name = requiredArg(args, '--name');
    const description = optionalArg(args, '--description', '');
    const period = optionalArg(args, '--period', 'Modern');
    const era = optionalArg(args, '--era', 'Contemporary');
    const location = optionalArg(args, '--location', 'City');
    const videoType = optionalArg(args, '--video-type', 'short') as any;
    const tone = optionalArg(args, '--tone', 'comedy') as any;
    const audience = optionalArg(args, '--audience', 'General');
    const style = optionalArg(args, '--style', 'cinematic');

    const ctx = await skill.createContext(
      name, description, [], period, era, location, videoType, tone, audience, style,
    );
    printJson(ctx);
  },

  'list-contexts': async (skill) => {
    printJson(await skill.listContexts());
  },

  'get-context': async (skill, args) => {
    const id = requiredArg(args, '--id');
    const ctx = await skill.getContext(id);
    if (!ctx) { console.error('Context not found'); process.exit(1); }
    printJson(ctx);
  },

  'delete-context': async (skill, args) => {
    const id = requiredArg(args, '--id');
    await skill.deleteContext(id);
    console.log('Deleted.');
  },

  // -- Story Generation -----------------------------------------------------

  'generate-ideas': async (skill, args) => {
    const contextId = requiredArg(args, '--context-id');
    const count = parseInt(optionalArg(args, '--count', '3'), 10);
    printJson(await skill.generateStoryIdeas(contextId, count));
  },

  'create-script': async (skill, args) => {
    const contextId = requiredArg(args, '--context-id');
    const ideaId = requiredArg(args, '--idea-id');
    // Load saved ideas to find the matching one
    const ideas = await (skill as any).context.memory.get(
      (skill as any).getStorageKey('ideas', contextId),
    );
    const idea = ideas?.find((i: any) => i.id === ideaId);
    if (!idea) { console.error('Idea not found. Run generate-ideas first.'); process.exit(1); }
    printJson(await skill.createCinematicScript(contextId, ideaId, idea));
  },

  'generate-metadata': async (skill, args) => {
    const scriptId = requiredArg(args, '--script-id');
    printJson(await skill.generateYouTubeMetadata(scriptId));
  },

  // -- Cinematography -------------------------------------------------------

  'list-angles': async (skill) => { printJson(skill.getAllCameraAngles()); },
  'list-movements': async (skill) => { printJson(skill.getAllCameraMovements()); },
  'list-shots': async (skill) => { printJson(skill.getAllShotTypes()); },

  'suggest-camera': async (skill, args) => {
    const sceneType = requiredArg(args, '--scene-type');
    const mood = requiredArg(args, '--mood');
    const level = optionalArg(args, '--level', 'intermediate') as any;
    printJson(skill.getRecommendedCameraSetup(sceneType, mood, level));
  },

  'suggest-lighting': async (skill, args) => {
    const sceneType = requiredArg(args, '--scene-type');
    const mood = requiredArg(args, '--mood');
    printJson(skill.suggestLighting(sceneType, mood));
  },

  'suggest-grading': async (skill, args) => {
    const genre = requiredArg(args, '--genre');
    printJson(skill.suggestColorGrading(genre));
  },

  'search': async (skill, args) => {
    const query = requiredArg(args, '--query');
    printJson(skill.searchCinematography(query));
  },

  // -- Consistency ----------------------------------------------------------

  'create-character-ref': async (skill, args) => {
    const characterId = requiredArg(args, '--character-id');
    const name = requiredArg(args, '--name');
    const visual = requiredArg(args, '--visual');
    const era = requiredArg(args, '--era');
    const style = requiredArg(args, '--style');
    printJson(skill.createCharacterReference(characterId, name, visual, era, style));
  },

  'create-voice': async (skill, args) => {
    const characterId = requiredArg(args, '--character-id');
    const name = requiredArg(args, '--name');
    const personality = requiredArg(args, '--personality');
    const age = optionalArg(args, '--age', 'adult');
    const role = optionalArg(args, '--role', 'supporting');
    printJson(skill.createVoiceProfile(characterId, name, personality, age, role));
  },

  'validate-prompt': async (skill, args) => {
    const prompt = requiredArg(args, '--prompt');
    const charIds = requiredArg(args, '--character-ids').split(',');
    const contextId = requiredArg(args, '--context-id');
    printJson(skill.validatePrompt(prompt, charIds, contextId));
  },

  // -- Storage --------------------------------------------------------------

  'connect-drive': async (skill) => {
    printJson(await skill.connectGoogleDrive());
  },

  'connect-local': async (skill, args) => {
    const basePath = optionalArg(args, '--path', '');
    printJson(await skill.connectLocalStorage(basePath || undefined));
  },

  'storage-status': async (skill) => {
    printJson(await skill.getStorageStatus());
  },

  'save': async (skill, args) => {
    const title = requiredArg(args, '--title');
    const contextId = requiredArg(args, '--context-id');
    const scriptId = optionalArg(args, '--script-id', '');
    printJson(await skill.saveScriptToStorage(title, contextId, scriptId));
  },

  // -- Export ---------------------------------------------------------------

  'export': async (skill, args) => {
    const scriptId = requiredArg(args, '--script-id');
    const format = optionalArg(args, '--format', 'markdown') as 'json' | 'text' | 'markdown';
    console.log(await skill.exportScript(scriptId, format));
  },
};

// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------

async function main() {
  const args = process.argv.slice(2);
  const command = args[0];

  if (!command || command === '--help' || command === '-h') {
    console.log(`
Cinematic Script Writer CLI

Usage: cinematic-script <command> [options]

Commands:
  Context:
    create-context      Create a new story context
    list-contexts       List all contexts
    get-context         Get a specific context
    delete-context      Delete a context

  Story:
    generate-ideas      Generate story ideas for a context
    create-script       Create a cinematic script from an idea
    generate-metadata   Generate YouTube metadata for a script

  Cinematography:
    list-angles         List all camera angles
    list-movements      List all camera movements
    list-shots          List all shot types
    suggest-camera      Get camera setup recommendation
    suggest-lighting    Get lighting suggestions
    suggest-grading     Get color grading suggestions
    search              Search cinematography database

  Consistency:
    create-character-ref  Create a character reference sheet
    create-voice          Create a voice profile
    validate-prompt       Validate a prompt for anachronisms

  Storage:
    connect-drive       Connect Google Drive
    connect-local       Connect local storage
    storage-status      Check storage connection
    save                Save project to storage

  Export:
    export              Export a script (json, text, markdown)

Run "cinematic-script <command> --help" for command-specific options.
    `.trim());
    process.exit(0);
  }

  const handler = commands[command];
  if (!handler) {
    console.error(`Unknown command: ${command}`);
    console.error('Run "cinematic-script --help" for available commands.');
    process.exit(1);
  }

  const skill = createSkill();
  await skill.loadStorageConfig();
  await handler(skill, args.slice(1));
}

main().catch((err) => {
  console.error(err.message || err);
  process.exit(1);
});


path: examples/file-manager-skill/index.ts
content: /**
 * File Manager Skill
 * Basic file operations
 */

import * as fs from 'fs/promises';
import * as path from 'path';

interface FileManagerConfig {
  basePath?: string;
  allowedExtensions?: string[];
}

interface SkillContext {
  userId: string;
  logger: Logger;
}

interface Logger {
  debug(msg: string): void;
  info(msg: string): void;
  error(msg: string): void;
}

interface FileInfo {
  name: string;
  path: string;
  size: number;
  isDirectory: boolean;
  modifiedAt: Date;
}

export class FileManagerSkill {
  private config: FileManagerConfig;
  private context: SkillContext;

  constructor(config: FileManagerConfig, context: SkillContext) {
    this.config = config;
    this.context = context;
  }

  private resolvePath(filePath: string): string {
    const base = this.config.basePath || process.cwd();
    // Prevent directory traversal
    const resolved = path.resolve(base, filePath);
    if (!resolved.startsWith(path.resolve(base))) {
      throw new Error('Access denied: Path outside base directory');
    }
    return resolved;
  }

  /**
   * Read file contents
   */
  async readFile(filePath: string, encoding: 'utf-8' | 'base64' = 'utf-8'): Promise<string> {
    const fullPath = this.resolvePath(filePath);
    this.context.logger.debug(`Reading file: ${fullPath}`);
    
    try {
      const content = await fs.readFile(fullPath, { encoding });
      return content;
    } catch (error) {
      this.context.logger.error(`Failed to read file: ${error}`);
      throw new Error(`Could not read file: ${filePath}`);
    }
  }

  /**
   * Write to a file
   */
  async writeFile(filePath: string, content: string, encoding: 'utf-8' | 'base64' = 'utf-8'): Promise<void> {
    const fullPath = this.resolvePath(filePath);
    
    // Check extension if restrictions apply
    if (this.config.allowedExtensions) {
      const ext = path.extname(filePath);
      if (!this.config.allowedExtensions.includes(ext)) {
        throw new Error(`File type not allowed: ${ext}`);
      }
    }

    this.context.logger.info(`Writing file: ${fullPath}`);

    // Ensure directory exists
    await fs.mkdir(path.dirname(fullPath), { recursive: true });
    
    await fs.writeFile(fullPath, content, { encoding });
  }

  /**
   * List files in directory
   */
  async listFiles(dirPath: string = ''): Promise<FileInfo[]> {
    const fullPath = this.resolvePath(dirPath);
    this.context.logger.debug(`Listing files: ${fullPath}`);

    try {
      const entries = await fs.readdir(fullPath, { withFileTypes: true });
      const files: FileInfo[] = [];

      for (const entry of entries) {
        const entryPath = path.join(fullPath, entry.name);
        const stats = await fs.stat(entryPath);
        
        files.push({
          name: entry.name,
          path: path.relative(this.config.basePath || process.cwd(), entryPath),
          size: stats.size,
          isDirectory: entry.isDirectory(),
          modifiedAt: stats.mtime
        });
      }

      return files;
    } catch (error) {
      this.context.logger.error(`Failed to list files: ${error}`);
      throw new Error(`Could not list files in: ${dirPath}`);
    }
  }

  /**
   * Delete a file
   */
  async deleteFile(filePath: string): Promise<void> {
    const fullPath = this.resolvePath(filePath);
    this.context.logger.info(`Deleting file: ${fullPath}`);
    
    await fs.unlink(fullPath);
  }

  /**
   * Check if file exists
   */
  async exists(filePath: string): Promise<boolean> {
    try {
      const fullPath = this.resolvePath(filePath);
      await fs.access(fullPath);
      return true;
    } catch {
      return false;
    }
  }
}

export default function createSkill(config: FileManagerConfig, context: SkillContext) {
  return new FileManagerSkill(config, context);
}

export type { FileManagerConfig, FileInfo };


path: examples/file-manager-skill/skill.json
content: {
  "$schema": "https://clawhub.ai/schemas/skill.json",
  "name": "file-manager-skill",
  "version": "1.0.0",
  "description": "Read, write, and manage files",
  "author": "You",
  "license": "MIT",
  "entry": "index.ts",
  "config": {
    "schema": "schema.json",
    "required": false
  },
  "permissions": ["fs:read", "fs:write", "fs:delete"],
  "tools": [
    { "name": "readFile", "description": "Read file contents" },
    { "name": "writeFile", "description": "Write to a file" },
    { "name": "listFiles", "description": "List files in a directory" },
    { "name": "deleteFile", "description": "Delete a file" }
  ],
  "tags": ["filesystem", "utility"]
}


path: examples/todo-skill/index.ts
content: /**
 * Todo Skill
 * Simple todo list with persistent storage
 */

interface TodoConfig {
  storagePath?: string;
}

interface SkillContext {
  userId: string;
  memory: MemoryStore;
  logger: Logger;
}

interface MemoryStore {
  get(key: string): Promise<any>;
  set(key: string, value: any): Promise<void>;
}

interface Logger {
  debug(msg: string): void;
  info(msg: string): void;
}

interface Todo {
  id: string;
  text: string;
  completed: boolean;
  createdAt: string;
  completedAt?: string;
  priority: 'low' | 'medium' | 'high';
}

interface TodoList {
  todos: Todo[];
  lastModified: string;
}

export class TodoSkill {
  private context: SkillContext;
  private storageKey: string;

  constructor(config: TodoConfig, context: SkillContext) {
    this.context = context;
    this.storageKey = `todos:${context.userId}`;
  }

  private async getTodos(): Promise<Todo[]> {
    const data = await this.context.memory.get(this.storageKey);
    return data?.todos || [];
  }

  private async saveTodos(todos: Todo[]): Promise<void> {
    const list: TodoList = {
      todos,
      lastModified: new Date().toISOString()
    };
    await this.context.memory.set(this.storageKey, list);
  }

  /**
   * Add a new todo
   */
  async addTodo(text: string, priority: 'low' | 'medium' | 'high' = 'medium'): Promise<Todo> {
    this.context.logger.info(`Adding todo: ${text}`);

    const todo: Todo = {
      id: Date.now().toString(),
      text,
      completed: false,
      createdAt: new Date().toISOString(),
      priority
    };

    const todos = await this.getTodos();
    todos.push(todo);
    await this.saveTodos(todos);

    return todo;
  }

  /**
   * List all todos
   */
  async listTodos(filter?: 'all' | 'active' | 'completed'): Promise<Todo[]> {
    const todos = await this.getTodos();
    
    switch (filter) {
      case 'active':
        return todos.filter(t => !t.completed);
      case 'completed':
        return todos.filter(t => t.completed);
      default:
        return todos;
    }
  }

  /**
   * Mark a todo as complete
   */
  async completeTodo(id: string): Promise<Todo | null> {
    const todos = await this.getTodos();
    const todo = todos.find(t => t.id === id);
    
    if (!todo) return null;

    todo.completed = true;
    todo.completedAt = new Date().toISOString();
    
    await this.saveTodos(todos);
    this.context.logger.info(`Completed todo: ${todo.text}`);
    
    return todo;
  }

  /**
   * Delete a todo
   */
  async deleteTodo(id: string): Promise<boolean> {
    const todos = await this.getTodos();
    const index = todos.findIndex(t => t.id === id);
    
    if (index === -1) return false;

    todos.splice(index, 1);
    await this.saveTodos(todos);
    
    return true;
  }

  /**
   * Get stats
   */
  async getStats(): Promise<{ total: number; active: number; completed: number }> {
    const todos = await this.getTodos();
    return {
      total: todos.length,
      active: todos.filter(t => !t.completed).length,
      completed: todos.filter(t => t.completed).length
    };
  }
}

export default function createSkill(config: TodoConfig, context: SkillContext) {
  return new TodoSkill(config, context);
}

export type { Todo, TodoConfig };


path: examples/todo-skill/skill.json
content: {
  "$schema": "https://clawhub.ai/schemas/skill.json",
  "name": "todo-skill",
  "version": "1.0.0",
  "description": "Simple todo list management with persistent storage",
  "author": "You",
  "license": "MIT",
  "entry": "index.ts",
  "config": {
    "schema": "schema.json",
    "required": false
  },
  "permissions": ["fs:read", "fs:write"],
  "tools": [
    { "name": "addTodo", "description": "Add a new todo item" },
    { "name": "listTodos", "description": "List all todos" },
    { "name": "completeTodo", "description": "Mark a todo as complete" },
    { "name": "deleteTodo", "description": "Delete a todo" }
  ],
  "tags": ["productivity", "storage"]
}


path: examples/weather-skill/README.md
content: # Weather Skill

Get weather information using OpenWeatherMap API.

## Setup

1. Get a free API key from [OpenWeatherMap](https://openweathermap.org/api)
2. Configure the skill with your API key

## Configuration

```json
{
  "apiKey": "your-api-key-here",
  "defaultLocation": "New York",
  "units": "metric"
}
```

## Tools

- `getCurrentWeather(location?)` - Get current weather
- `getForecast(location?)` - Get 5-day forecast
- `getLastWeather()` - Get cached weather data

## Usage Example

```typescript
const weather = await agent.tools.weather.getCurrentWeather("Tokyo");
// Returns: { location, temperature, feelsLike, humidity, description, windSpeed, timestamp }
```


path: examples/weather-skill/index.ts
content: /**
 * Weather Skill
 * Fetches weather data from OpenWeatherMap API
 */

interface WeatherConfig {
  [REDACTED_SECRET];
  defaultLocation?: string;
  units?: 'metric' | 'imperial' | 'kelvin';
}

interface SkillContext {
  userId: string;
  memory: MemoryStore;
  logger: Logger;
  http: HttpClient;
}

interface MemoryStore {
  get(key: string): Promise<any>;
  set(key: string, value: any): Promise<void>;
}

interface Logger {
  debug(msg: string): void;
  info(msg: string): void;
  error(msg: string): void;
}

interface HttpClient {
  get(url: string, options?: any): Promise<any>;
}

interface WeatherData {
  location: string;
  temperature: number;
  feelsLike: number;
  humidity: number;
  description: string;
  windSpeed: number;
  timestamp: string;
}

export class WeatherSkill {
  private config: WeatherConfig;
  private context: SkillContext;
  private baseUrl = 'https://api.openweathermap.org/data/2.5';

  constructor(config: WeatherConfig, context: SkillContext) {
    this.config = config;
    this.context = context;
  }

  /**
   * Get current weather for a location
   */
  async getCurrentWeather(location?: string): Promise<WeatherData> {
    const targetLocation = location || this.config.defaultLocation || 'London';
    
    this.context.logger.debug(`Fetching weather for: ${targetLocation}`);

    try {
      const response = await this.context.http.get(
        `${this.baseUrl}/weather?q=${encodeURIComponent(targetLocation)}&appid=${this.config.apiKey}&units=${this.config.units || 'metric'}`
      );

      const weather: WeatherData = {
        location: `${response.name}, ${response.sys.country}`,
        temperature: response.main.temp,
        feelsLike: response.main.feels_like,
        humidity: response.main.humidity,
        description: response.weather[0].description,
        windSpeed: response.wind.speed,
        timestamp: new Date().toISOString()
      };

      // Cache in memory
      await this.context.memory.set(
        `weather:last:${this.context.userId}`,
        weather
      );

      return weather;
    } catch (error) {
      this.context.logger.error(`Weather fetch failed: ${error}`);
      throw new Error(`Could not fetch weather for ${targetLocation}`);
    }
  }

  /**
   * Get 5-day forecast
   */
  async getForecast(location?: string): Promise<any> {
    const targetLocation = location || this.config.defaultLocation || 'London';
    
    this.context.logger.debug(`Fetching forecast for: ${targetLocation}`);

    try {
      const response = await this.context.http.get(
        `${this.baseUrl}/forecast?q=${encodeURIComponent(targetLocation)}&appid=${this.config.apiKey}&units=${this.config.units || 'metric'}`
      );

      // Simplify forecast data
      const dailyForecasts = response.list
        .filter((item: any, index: number) => index % 8 === 0) // One per day
        .slice(0, 5)
        .map((item: any) => ({
          date: new Date(item.dt * 1000).toDateString(),
          temp: item.main.temp,
          description: item.weather[0].description,
          humidity: item.main.humidity
        }));

      return {
        location: `${response.city.name}, ${response.city.country}`,
        forecast: dailyForecasts
      };
    } catch (error) {
      this.context.logger.error(`Forecast fetch failed: ${error}`);
      throw new Error(`Could not fetch forecast for ${targetLocation}`);
    }
  }

  /**
   * Get last cached weather
   */
  async getLastWeather(): Promise<WeatherData | null> {
    return await this.context.memory.get(`weather:last:${this.context.userId}`);
  }
}

export default function createSkill(config: WeatherConfig, context: SkillContext) {
  return new WeatherSkill(config, context);
}

export type { WeatherConfig, WeatherData };


path: examples/weather-skill/schema.json
content: {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "apiKey": {
      "type": "string",
      "description": "OpenWeatherMap API key"
    },
    "defaultLocation": {
      "type": "string",
      "description": "Default location for weather queries",
      "default": "London"
    },
    "units": {
      "type": "string",
      "enum": ["metric", "imperial", "kelvin"],
      "default": "metric"
    }
  },
  "required": ["apiKey"]
}


path: examples/weather-skill/skill.json
content: {
  "$schema": "https://clawhub.ai/schemas/skill.json",
  "name": "weather-skill",
  "version": "1.0.0",
  "description": "Get weather information for any location",
  "author": "You",
  "license": "MIT",
  "entry": "index.ts",
  "config": {
    "schema": "schema.json",
    "required": ["apiKey"]
  },
  "permissions": ["http:request", "fs:read"],
  "tools": [
    {
      "name": "getCurrentWeather",
      "description": "Get current weather for a location"
    },
    {
      "name": "getForecast",
      "description": "Get 5-day weather forecast"
    }
  ],
  "dependencies": {},
  "tags": ["weather", "api", "utility"]
}


path: package-lock.json
content: {
  "name": "openclaw-skills",
  "version": "1.4.1",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "openclaw-skills",
      "version": "1.4.1",
      "license": "MIT",
      "dependencies": {
        "uuid": "^9.0.0"
      },
      "bin": {
        "cinematic-script": "dist/bin/cinematic-script.js"
      },
      "devDependencies": {
        "@types/jest": "^29.5.0",
        "@types/node": "^20.0.0",
        "@types/uuid": "^9.0.0",
        "@typescript-eslint/eslint-plugin": "^6.0.0",
        "@typescript-eslint/parser": "^6.0.0",
        "eslint": "^8.45.0",
        "jest": "^29.0.0",
        "ts-jest": "^29.1.0",
        "typescript": "^5.0.0"
      },
      "engines": {
        "node": ">=18.0.0"
      }
    },
    "node_modules/@babel/code-frame": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-validator-identifier": "^7.28.5",
        "js-tokens": "^4.0.0",
        "picocolors": "^1.1.1"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/compat-data": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/core": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/code-frame": "^7.29.0",
        "@babel/generator": "^7.29.0",
        "@babel/helper-compilation-targets": "^7.28.6",
        "@babel/helper-module-transforms": "^7.28.6",
        "@babel/helpers": "^7.28.6",
        "@babel/parser": "^7.29.0",
        "@babel/template": "^7.28.6",
        "@babel/traverse": "^7.29.0",
        "@babel/types": "^7.29.0",
        "@jridgewell/remapping": "^2.3.5",
        "convert-source-map": "^2.0.0",
        "debug": "^4.1.0",
        "gensync": "^1.0.0-beta.2",
        "json5": "^2.2.3",
        "semver": "^6.3.1"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/babel"
      }
    },
    "node_modules/@babel/core/node_modules/semver": {
      "version": "6.3.1",
      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "bin": {
        "semver": "bin/semver.js"
      }
    },
    "node_modules/@babel/generator": {
      "version": "7.29.1",
      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/parser": "^7.29.0",
        "@babel/types": "^7.29.0",
        "@jridgewell/gen-mapping": "^0.3.12",
        "@jridgewell/trace-mapping": "^0.3.28",
        "jsesc": "^3.0.2"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-compilation-targets": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/compat-data": "^7.28.6",
        "@babel/helper-validator-option": "^7.27.1",
        "browserslist": "^4.24.0",
        "lru-cache": "^5.1.1",
        "semver": "^6.3.1"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
      "version": "6.3.1",
      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "bin": {
        "semver": "bin/semver.js"
      }
    },
    "node_modules/@babel/helper-globals": {
      "version": "7.28.0",
      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-module-imports": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/traverse": "^7.28.6",
        "@babel/types": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-module-transforms": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-module-imports": "^7.28.6",
        "@babel/helper-validator-identifier": "^7.28.5",
        "@babel/traverse": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0"
      }
    },
    "node_modules/@babel/helper-plugin-utils": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-string-parser": {
      "version": "7.27.1",
      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-validator-identifier": {
      "version": "7.28.5",
      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helper-validator-option": {
      "version": "7.27.1",
      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/helpers": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/template": "^7.28.6",
        "@babel/types": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/parser": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/types": "^7.29.0"
      },
      "bin": {
        "parser": "bin/babel-parser.js"
      },
      "engines": {
        "node": ">=6.0.0"
      }
    },
    "node_modules/@babel/plugin-syntax-async-generators": {
      "version": "7.8.4",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-bigint": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-class-properties": {
      "version": "7.12.13",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.12.13"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-class-static-block": {
      "version": "7.14.5",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.14.5"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-import-attributes": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-import-meta": {
      "version": "7.10.4",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.10.4"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-json-strings": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-jsx": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
      "version": "7.10.4",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.10.4"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-numeric-separator": {
      "version": "7.10.4",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.10.4"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-object-rest-spread": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-optional-chaining": {
      "version": "7.8.3",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.8.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-private-property-in-object": {
      "version": "7.14.5",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.14.5"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-top-level-await": {
      "version": "7.14.5",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.14.5"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/plugin-syntax-typescript": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0-0"
      }
    },
    "node_modules/@babel/template": {
      "version": "7.28.6",
      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/code-frame": "^7.28.6",
        "@babel/parser": "^7.28.6",
        "@babel/types": "^7.28.6"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/traverse": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/code-frame": "^7.29.0",
        "@babel/generator": "^7.29.0",
        "@babel/helper-globals": "^7.28.0",
        "@babel/parser": "^7.29.0",
        "@babel/template": "^7.28.6",
        "@babel/types": "^7.29.0",
        "debug": "^4.3.1"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@babel/types": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/helper-string-parser": "^7.27.1",
        "@babel/helper-validator-identifier": "^7.28.5"
      },
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/@bcoe/v8-coverage": {
      "version": "0.2.3",
      "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@eslint-community/eslint-utils": {
      "version": "4.9.1",
      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "eslint-visitor-keys": "^3.4.3"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      },
      "peerDependencies": {
        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
      }
    },
    "node_modules/@eslint-community/regexpp": {
      "version": "4.12.2",
      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
      }
    },
    "node_modules/@eslint/eslintrc": {
      "version": "2.1.4",
      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "ajv": "^6.12.4",
        "debug": "^4.3.2",
        "espree": "^9.6.0",
        "globals": "^13.19.0",
        "ignore": "^5.2.0",
        "import-fresh": "^3.2.1",
        "js-yaml": "^4.1.0",
        "minimatch": "^3.1.2",
        "strip-json-comments": "^3.1.1"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      }
    },
    "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "node_modules/@eslint/eslintrc/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^1.1.7"
      },
      "engines": {
        "node": "*"
      }
    },
    "node_modules/@eslint/js": {
      "version": "8.57.1",
      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      }
    },
    "node_modules/@humanwhocodes/config-array": {
      "version": "0.13.0",
      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "Use @eslint/config-array instead",
      "dev": true,
      "license": "Apache-2.0",
      "dependencies": {
        "@humanwhocodes/object-schema": "^2.0.3",
        "debug": "^4.3.1",
        "minimatch": "^3.0.5"
      },
      "engines": {
        "node": ">=10.10.0"
      }
    },
    "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^1.1.7"
      },
      "engines": {
        "node": "*"
      }
    },
    "node_modules/@humanwhocodes/module-importer": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "engines": {
        "node": ">=12.22"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/nzakas"
      }
    },
    "node_modules/@humanwhocodes/object-schema": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "Use @eslint/object-schema instead",
      "dev": true,
      "license": "BSD-3-Clause"
    },
    "node_modules/@istanbuljs/load-nyc-config": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "camelcase": "^5.3.1",
        "find-up": "^4.1.0",
        "get-package-type": "^0.1.0",
        "js-yaml": "^3.13.1",
        "resolve-from": "^5.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
      "version": "1.0.10",
      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "sprintf-js": "~1.0.2"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "locate-path": "^5.0.0",
        "path-exists": "^4.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
      "version": "3.14.2",
      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "argparse": "^1.0.7",
        "esprima": "^4.0.0"
      },
      "bin": {
        "js-yaml": "bin/js-yaml.js"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-locate": "^4.1.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-try": "^2.0.0"
      },
      "engines": {
        "node": ">=6"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-limit": "^2.2.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@istanbuljs/schema": {
      "version": "0.1.3",
      "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/@jest/console": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "jest-message-util": "^29.7.0",
        "jest-util": "^29.7.0",
        "slash": "^3.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/core": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/console": "^29.7.0",
        "@jest/reporters": "^29.7.0",
        "@jest/test-result": "^29.7.0",
        "@jest/transform": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "ansi-escapes": "^4.2.1",
        "chalk": "^4.0.0",
        "ci-info": "^3.2.0",
        "exit": "^0.1.2",
        "graceful-fs": "^4.2.9",
        "jest-changed-files": "^29.7.0",
        "jest-config": "^29.7.0",
        "jest-haste-map": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-regex-util": "^29.6.3",
        "jest-resolve": "^29.7.0",
        "jest-resolve-dependencies": "^29.7.0",
        "jest-runner": "^29.7.0",
        "jest-runtime": "^29.7.0",
        "jest-snapshot": "^29.7.0",
        "jest-util": "^29.7.0",
        "jest-validate": "^29.7.0",
        "jest-watcher": "^29.7.0",
        "micromatch": "^4.0.4",
        "pretty-format": "^29.7.0",
        "slash": "^3.0.0",
        "strip-ansi": "^6.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
      },
      "peerDependenciesMeta": {
        "node-notifier": {
          "optional": true
        }
      }
    },
    "node_modules/@jest/environment": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/fake-timers": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "jest-mock": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/expect": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "expect": "^29.7.0",
        "jest-snapshot": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/expect-utils": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "jest-get-type": "^29.6.3"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/fake-timers": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "@sinonjs/fake-timers": "^10.0.2",
        "@types/node": "*",
        "jest-message-util": "^29.7.0",
        "jest-mock": "^29.7.0",
        "jest-util": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/globals": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/environment": "^29.7.0",
        "@jest/expect": "^29.7.0",
        "@jest/types": "^29.6.3",
        "jest-mock": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/reporters": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@bcoe/v8-coverage": "^0.2.3",
        "@jest/console": "^29.7.0",
        "@jest/test-result": "^29.7.0",
        "@jest/transform": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@jridgewell/trace-mapping": "^0.3.18",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "collect-v8-coverage": "^1.0.0",
        "exit": "^0.1.2",
        "glob": "^7.1.3",
        "graceful-fs": "^4.2.9",
        "istanbul-lib-coverage": "^3.0.0",
        "istanbul-lib-instrument": "^6.0.0",
        "istanbul-lib-report": "^3.0.0",
        "istanbul-lib-source-maps": "^4.0.0",
        "istanbul-reports": "^3.1.3",
        "jest-message-util": "^29.7.0",
        "jest-util": "^29.7.0",
        "jest-worker": "^29.7.0",
        "slash": "^3.0.0",
        "string-length": "^4.0.1",
        "strip-ansi": "^6.0.0",
        "v8-to-istanbul": "^9.0.1"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
      },
      "peerDependenciesMeta": {
        "node-notifier": {
          "optional": true
        }
      }
    },
    "node_modules/@jest/schemas": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@sinclair/typebox": "^0.27.8"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/source-map": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jridgewell/trace-mapping": "^0.3.18",
        "callsites": "^3.0.0",
        "graceful-fs": "^4.2.9"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/test-result": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/console": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/istanbul-lib-coverage": "^2.0.0",
        "collect-v8-coverage": "^1.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/test-sequencer": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/test-result": "^29.7.0",
        "graceful-fs": "^4.2.9",
        "jest-haste-map": "^29.7.0",
        "slash": "^3.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/transform": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/core": "^7.11.6",
        "@jest/types": "^29.6.3",
        "@jridgewell/trace-mapping": "^0.3.18",
        "babel-plugin-istanbul": "^6.1.1",
        "chalk": "^4.0.0",
        "convert-source-map": "^2.0.0",
        "fast-json-stable-stringify": "^2.1.0",
        "graceful-fs": "^4.2.9",
        "jest-haste-map": "^29.7.0",
        "jest-regex-util": "^29.6.3",
        "jest-util": "^29.7.0",
        "micromatch": "^4.0.4",
        "pirates": "^4.0.4",
        "slash": "^3.0.0",
        "write-file-atomic": "^4.0.2"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jest/types": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/schemas": "^29.6.3",
        "@types/istanbul-lib-coverage": "^2.0.0",
        "@types/istanbul-reports": "^3.0.0",
        "@types/node": "*",
        "@types/yargs": "^17.0.8",
        "chalk": "^4.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/@jridgewell/gen-mapping": {
      "version": "0.3.13",
      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jridgewell/sourcemap-codec": "^1.5.0",
        "@jridgewell/trace-mapping": "^0.3.24"
      }
    },
    "node_modules/@jridgewell/remapping": {
      "version": "2.3.5",
      "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jridgewell/gen-mapping": "^0.3.5",
        "@jridgewell/trace-mapping": "^0.3.24"
      }
    },
    "node_modules/@jridgewell/resolve-uri": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.0.0"
      }
    },
    "node_modules/@jridgewell/sourcemap-codec": {
      "version": "1.5.5",
      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@jridgewell/trace-mapping": {
      "version": "0.3.31",
      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jridgewell/resolve-uri": "^3.1.0",
        "@jridgewell/sourcemap-codec": "^1.4.14"
      }
    },
    "node_modules/@nodelib/fs.scandir": {
      "version": "2.1.5",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.stat": "2.0.5",
        "run-parallel": "^1.1.9"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/@nodelib/fs.stat": {
      "version": "2.0.5",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/@nodelib/fs.walk": {
      "version": "1.2.8",
      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.scandir": "2.1.5",
        "fastq": "^1.6.0"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/@sinclair/typebox": {
      "version": "0.27.10",
      "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@sinonjs/commons": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "type-detect": "4.0.8"
      }
    },
    "node_modules/@sinonjs/fake-timers": {
      "version": "10.3.0",
      "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "@sinonjs/commons": "^3.0.0"
      }
    },
    "node_modules/@types/babel__core": {
      "version": "7.20.5",
      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/parser": "^7.20.7",
        "@babel/types": "^7.20.7",
        "@types/babel__generator": "*",
        "@types/babel__template": "*",
        "@types/babel__traverse": "*"
      }
    },
    "node_modules/@types/babel__generator": {
      "version": "7.27.0",
      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/types": "^7.0.0"
      }
    },
    "node_modules/@types/babel__template": {
      "version": "7.4.4",
      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/parser": "^7.1.0",
        "@babel/types": "^7.0.0"
      }
    },
    "node_modules/@types/babel__traverse": {
      "version": "7.28.0",
      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/types": "^7.28.2"
      }
    },
    "node_modules/@types/graceful-fs": {
      "version": "4.1.9",
      "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*"
      }
    },
    "node_modules/@types/istanbul-lib-coverage": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/istanbul-lib-report": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/istanbul-lib-coverage": "*"
      }
    },
    "node_modules/@types/istanbul-reports": {
      "version": "3.0.4",
      "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/istanbul-lib-report": "*"
      }
    },
    "node_modules/@types/jest": {
      "version": "29.5.14",
      "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "expect": "^29.0.0",
        "pretty-format": "^29.0.0"
      }
    },
    "node_modules/@types/json-schema": {
      "version": "7.0.15",
      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/node": {
      "version": "20.19.33",
      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "undici-types": "~6.21.0"
      }
    },
    "node_modules/@types/semver": {
      "version": "7.7.1",
      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/stack-utils": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/uuid": {
      "version": "9.0.8",
      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@types/yargs": {
      "version": "17.0.35",
      "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/yargs-parser": "*"
      }
    },
    "node_modules/@types/yargs-parser": {
      "version": "21.0.3",
      "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/@typescript-eslint/eslint-plugin": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@eslint-community/regexpp": "^4.5.1",
        "@typescript-eslint/scope-manager": "6.21.0",
        "@typescript-eslint/type-utils": "6.21.0",
        "@typescript-eslint/utils": "6.21.0",
        "@typescript-eslint/visitor-keys": "6.21.0",
        "debug": "^4.3.4",
        "graphemer": "^1.4.0",
        "ignore": "^5.2.4",
        "natural-compare": "^1.4.0",
        "semver": "^7.5.4",
        "ts-api-utils": "^1.0.1"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      },
      "peerDependencies": {
        "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
        "eslint": "^7.0.0 || ^8.0.0"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/@typescript-eslint/parser": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "@typescript-eslint/scope-manager": "6.21.0",
        "@typescript-eslint/types": "6.21.0",
        "@typescript-eslint/typescript-estree": "6.21.0",
        "@typescript-eslint/visitor-keys": "6.21.0",
        "debug": "^4.3.4"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      },
      "peerDependencies": {
        "eslint": "^7.0.0 || ^8.0.0"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/@typescript-eslint/scope-manager": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@typescript-eslint/types": "6.21.0",
        "@typescript-eslint/visitor-keys": "6.21.0"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      }
    },
    "node_modules/@typescript-eslint/type-utils": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@typescript-eslint/typescript-estree": "6.21.0",
        "@typescript-eslint/utils": "6.21.0",
        "debug": "^4.3.4",
        "ts-api-utils": "^1.0.1"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      },
      "peerDependencies": {
        "eslint": "^7.0.0 || ^8.0.0"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/@typescript-eslint/types": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      }
    },
    "node_modules/@typescript-eslint/typescript-estree": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "@typescript-eslint/types": "6.21.0",
        "@typescript-eslint/visitor-keys": "6.21.0",
        "debug": "^4.3.4",
        "globby": "^11.1.0",
        "is-glob": "^4.0.3",
        "minimatch": "9.0.3",
        "semver": "^7.5.4",
        "ts-api-utils": "^1.0.1"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      },
      "peerDependenciesMeta": {
        "typescript": {
          "optional": true
        }
      }
    },
    "node_modules/@typescript-eslint/utils": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@eslint-community/eslint-utils": "^4.4.0",
        "@types/json-schema": "^7.0.12",
        "@types/semver": "^7.5.0",
        "@typescript-eslint/scope-manager": "6.21.0",
        "@typescript-eslint/types": "6.21.0",
        "@typescript-eslint/typescript-estree": "6.21.0",
        "semver": "^7.5.4"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      },
      "peerDependencies": {
        "eslint": "^7.0.0 || ^8.0.0"
      }
    },
    "node_modules/@typescript-eslint/visitor-keys": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@typescript-eslint/types": "6.21.0",
        "eslint-visitor-keys": "^3.4.1"
      },
      "engines": {
        "node": "^16.0.0 || >=18.0.0"
      },
      "funding": {
        "type": "opencollective",
        "url": "https://opencollective.com/typescript-eslint"
      }
    },
    "node_modules/@ungap/structured-clone": {
      "version": "1.3.0",
      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/acorn": {
      "version": "8.15.0",
      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "bin": {
        "acorn": "bin/acorn"
      },
      "engines": {
        "node": ">=0.4.0"
      }
    },
    "node_modules/acorn-jsx": {
      "version": "5.3.2",
      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "peerDependencies": {
        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
      }
    },
    "node_modules/ajv": {
      "version": "6.12.6",
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "fast-deep-equal": "^3.1.1",
        "fast-json-stable-stringify": "^2.0.0",
        "json-schema-traverse": "^0.4.1",
        "uri-js": "^4.2.2"
      },
      "funding": {
        "type": "github",
        "url": "https://github.com/sponsors/epoberezkin"
      }
    },
    "node_modules/ansi-escapes": {
      "version": "4.3.2",
      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "type-fest": "^0.21.3"
      },
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/ansi-escapes/node_modules/type-fest": {
      "version": "0.21.3",
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "(MIT OR CC0-1.0)",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/ansi-regex": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/ansi-styles": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "color-convert": "^2.0.1"
      },
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
      }
    },
    "node_modules/anymatch": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "normalize-path": "^3.0.0",
        "picomatch": "^2.0.4"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/argparse": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Python-2.0"
    },
    "node_modules/array-union": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/babel-jest": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/transform": "^29.7.0",
        "@types/babel__core": "^7.1.14",
        "babel-plugin-istanbul": "^6.1.1",
        "babel-preset-jest": "^29.6.3",
        "chalk": "^4.0.0",
        "graceful-fs": "^4.2.9",
        "slash": "^3.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.8.0"
      }
    },
    "node_modules/babel-plugin-istanbul": {
      "version": "6.1.1",
      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "@babel/helper-plugin-utils": "^7.0.0",
        "@istanbuljs/load-nyc-config": "^1.0.0",
        "@istanbuljs/schema": "^0.1.2",
        "istanbul-lib-instrument": "^5.0.4",
        "test-exclude": "^6.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
      "version": "5.2.1",
      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "@babel/core": "^7.12.3",
        "@babel/parser": "^7.14.7",
        "@istanbuljs/schema": "^0.1.2",
        "istanbul-lib-coverage": "^3.2.0",
        "semver": "^6.3.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/babel-plugin-istanbul/node_modules/semver": {
      "version": "6.3.1",
      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "bin": {
        "semver": "bin/semver.js"
      }
    },
    "node_modules/babel-plugin-jest-hoist": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/template": "^7.3.3",
        "@babel/types": "^7.3.3",
        "@types/babel__core": "^7.1.14",
        "@types/babel__traverse": "^7.0.6"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/babel-preset-current-node-syntax": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/plugin-syntax-async-generators": "^7.8.4",
        "@babel/plugin-syntax-bigint": "^7.8.3",
        "@babel/plugin-syntax-class-properties": "^7.12.13",
        "@babel/plugin-syntax-class-static-block": "^7.14.5",
        "@babel/plugin-syntax-import-attributes": "^7.24.7",
        "@babel/plugin-syntax-import-meta": "^7.10.4",
        "@babel/plugin-syntax-json-strings": "^7.8.3",
        "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
        "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
        "@babel/plugin-syntax-numeric-separator": "^7.10.4",
        "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
        "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
        "@babel/plugin-syntax-optional-chaining": "^7.8.3",
        "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
        "@babel/plugin-syntax-top-level-await": "^7.14.5"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0 || ^8.0.0-0"
      }
    },
    "node_modules/babel-preset-jest": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "babel-plugin-jest-hoist": "^29.6.3",
        "babel-preset-current-node-syntax": "^1.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "@babel/core": "^7.0.0"
      }
    },
    "node_modules/balanced-match": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/baseline-browser-mapping": {
      "version": "2.9.19",
      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "bin": {
        "baseline-browser-mapping": "dist/cli.js"
      }
    },
    "node_modules/brace-expansion": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0"
      }
    },
    "node_modules/braces": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "fill-range": "^7.1.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/browserslist": {
      "version": "4.28.1",
      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "opencollective",
          "url": "https://opencollective.com/browserslist"
        },
        {
          "type": "tidelift",
          "url": "https://tidelift.com/funding/github/npm/browserslist"
        },
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "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.2.0"
      },
      "bin": {
        "browserslist": "cli.js"
      },
      "engines": {
        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
      }
    },
    "node_modules/bs-logger": {
      "version": "0.2.6",
      "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "fast-json-stable-stringify": "2.x"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/bser": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "dependencies": {
        "node-int64": "^0.4.0"
      }
    },
    "node_modules/buffer-from": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/callsites": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/camelcase": {
      "version": "5.3.1",
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/caniuse-lite": {
      "version": "1.0.30001769",
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "opencollective",
          "url": "https://opencollective.com/browserslist"
        },
        {
          "type": "tidelift",
          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
        },
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "CC-BY-4.0"
    },
    "node_modules/chalk": {
      "version": "4.1.2",
      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "ansi-styles": "^4.1.0",
        "supports-color": "^7.1.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/chalk/chalk?sponsor=1"
      }
    },
    "node_modules/char-regex": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/ci-info": {
      "version": "3.9.0",
      "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/sibiraj-s"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/cjs-module-lexer": {
      "version": "1.4.3",
      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/cliui": {
      "version": "8.0.1",
      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "string-width": "^4.2.0",
        "strip-ansi": "^6.0.1",
        "wrap-ansi": "^7.0.0"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/co": {
      "version": "4.6.0",
      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "iojs": ">= 1.0.0",
        "node": ">= 0.12.0"
      }
    },
    "node_modules/collect-v8-coverage": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/color-convert": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "color-name": "~1.1.4"
      },
      "engines": {
        "node": ">=7.0.0"
      }
    },
    "node_modules/color-name": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/concat-map": {
      "version": "0.0.1",
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/convert-source-map": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/create-jest": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "chalk": "^4.0.0",
        "exit": "^0.1.2",
        "graceful-fs": "^4.2.9",
        "jest-config": "^29.7.0",
        "jest-util": "^29.7.0",
        "prompts": "^2.0.1"
      },
      "bin": {
        "create-jest": "bin/create-jest.js"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/cross-spawn": {
      "version": "7.0.6",
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "path-key": "^3.1.0",
        "shebang-command": "^2.0.0",
        "which": "^2.0.1"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/debug": {
      "version": "4.4.3",
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "ms": "^2.1.3"
      },
      "engines": {
        "node": ">=6.0"
      },
      "peerDependenciesMeta": {
        "supports-color": {
          "optional": true
        }
      }
    },
    "node_modules/dedent": {
      "version": "1.7.1",
      "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "peerDependencies": {
        "babel-plugin-macros": "^3.1.0"
      },
      "peerDependenciesMeta": {
        "babel-plugin-macros": {
          "optional": true
        }
      }
    },
    "node_modules/deep-is": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/deepmerge": {
      "version": "4.3.1",
      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/detect-newline": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/diff-sequences": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/dir-glob": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "path-type": "^4.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/doctrine": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "dependencies": {
        "esutils": "^2.0.2"
      },
      "engines": {
        "node": ">=6.0.0"
      }
    },
    "node_modules/electron-to-chromium": {
      "version": "1.5.286",
      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/emittery": {
      "version": "0.13.1",
      "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=12"
      },
      "funding": {
        "url": "https://github.com/sindresorhus/emittery?sponsor=1"
      }
    },
    "node_modules/emoji-regex": {
      "version": "8.0.0",
      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/error-ex": {
      "version": "1.3.4",
      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "is-arrayish": "^0.2.1"
      }
    },
    "node_modules/escalade": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/escape-string-regexp": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/eslint": {
      "version": "8.57.1",
      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@eslint-community/eslint-utils": "^4.2.0",
        "@eslint-community/regexpp": "^4.6.1",
        "@eslint/eslintrc": "^2.1.4",
        "@eslint/js": "8.57.1",
        "@humanwhocodes/config-array": "^0.13.0",
        "@humanwhocodes/module-importer": "^1.0.1",
        "@nodelib/fs.walk": "^1.2.8",
        "@ungap/structured-clone": "^1.2.0",
        "ajv": "^6.12.4",
        "chalk": "^4.0.0",
        "cross-spawn": "^7.0.2",
        "debug": "^4.3.2",
        "doctrine": "^3.0.0",
        "escape-string-regexp": "^4.0.0",
        "eslint-scope": "^7.2.2",
        "eslint-visitor-keys": "^3.4.3",
        "espree": "^9.6.1",
        "esquery": "^1.4.2",
        "esutils": "^2.0.2",
        "fast-deep-equal": "^3.1.3",
        "file-entry-cache": "^6.0.1",
        "find-up": "^5.0.0",
        "glob-parent": "^6.0.2",
        "globals": "^13.19.0",
        "graphemer": "^1.4.0",
        "ignore": "^5.2.0",
        "imurmurhash": "^0.1.4",
        "is-glob": "^4.0.0",
        "is-path-inside": "^3.0.3",
        "js-yaml": "^4.1.0",
        "json-stable-stringify-without-jsonify": "^1.0.1",
        "levn": "^0.4.1",
        "lodash.merge": "^4.6.2",
        "minimatch": "^3.1.2",
        "natural-compare": "^1.4.0",
        "optionator": "^0.9.3",
        "strip-ansi": "^6.0.1",
        "text-table": "^0.2.0"
      },
      "bin": {
        "eslint": "bin/eslint.js"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      }
    },
    "node_modules/eslint-scope": {
      "version": "7.2.2",
      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "esrecurse": "^4.3.0",
        "estraverse": "^5.2.0"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      }
    },
    "node_modules/eslint-visitor-keys": {
      "version": "3.4.3",
      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      }
    },
    "node_modules/eslint/node_modules/brace-expansion": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "node_modules/eslint/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^1.1.7"
      },
      "engines": {
        "node": "*"
      }
    },
    "node_modules/espree": {
      "version": "9.6.1",
      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "acorn": "^8.9.0",
        "acorn-jsx": "^5.3.2",
        "eslint-visitor-keys": "^3.4.1"
      },
      "engines": {
        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
      },
      "funding": {
        "url": "https://opencollective.com/eslint"
      }
    },
    "node_modules/esprima": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "bin": {
        "esparse": "bin/esparse.js",
        "esvalidate": "bin/esvalidate.js"
      },
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/esquery": {
      "version": "1.7.0",
      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "estraverse": "^5.1.0"
      },
      "engines": {
        "node": ">=0.10"
      }
    },
    "node_modules/esrecurse": {
      "version": "4.3.0",
      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "estraverse": "^5.2.0"
      },
      "engines": {
        "node": ">=4.0"
      }
    },
    "node_modules/estraverse": {
      "version": "5.3.0",
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=4.0"
      }
    },
    "node_modules/esutils": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/execa": {
      "version": "5.1.1",
      "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "cross-spawn": "^7.0.3",
        "get-stream": "^6.0.0",
        "human-signals": "^2.1.0",
        "is-stream": "^2.0.0",
        "merge-stream": "^2.0.0",
        "npm-run-path": "^4.0.1",
        "onetime": "^5.1.2",
        "signal-exit": "^3.0.3",
        "strip-final-newline": "^2.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sindresorhus/execa?sponsor=1"
      }
    },
    "node_modules/exit": {
      "version": "0.1.2",
      "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/expect": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/expect-utils": "^29.7.0",
        "jest-get-type": "^29.6.3",
        "jest-matcher-utils": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-util": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/fast-deep-equal": {
      "version": "3.1.3",
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/fast-glob": {
      "version": "3.3.3",
      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@nodelib/fs.stat": "^2.0.2",
        "@nodelib/fs.walk": "^1.2.3",
        "glob-parent": "^5.1.2",
        "merge2": "^1.3.0",
        "micromatch": "^4.0.8"
      },
      "engines": {
        "node": ">=8.6.0"
      }
    },
    "node_modules/fast-glob/node_modules/glob-parent": {
      "version": "5.1.2",
      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "is-glob": "^4.0.1"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/fast-json-stable-stringify": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/fast-levenshtein": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/fastq": {
      "version": "1.20.1",
      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "reusify": "^1.0.4"
      }
    },
    "node_modules/fb-watchman": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "dependencies": {
        "bser": "2.1.1"
      }
    },
    "node_modules/file-entry-cache": {
      "version": "6.0.1",
      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "flat-cache": "^3.0.4"
      },
      "engines": {
        "node": "^10.12.0 || >=12.0.0"
      }
    },
    "node_modules/fill-range": {
      "version": "7.1.1",
      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "to-regex-range": "^5.0.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/find-up": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "locate-path": "^6.0.0",
        "path-exists": "^4.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/flat-cache": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "flatted": "^3.2.9",
        "keyv": "^4.5.3",
        "rimraf": "^3.0.2"
      },
      "engines": {
        "node": "^10.12.0 || >=12.0.0"
      }
    },
    "node_modules/flatted": {
      "version": "3.3.3",
      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/fs.realpath": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/fsevents": {
      "version": "2.3.3",
      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "hasInstallScript": true,
      "license": "MIT",
      "optional": true,
      "os": [
        "darwin"
      ],
      "engines": {
        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
      }
    },
    "node_modules/function-bind": {
      "version": "1.1.2",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/gensync": {
      "version": "1.0.0-beta.2",
      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6.9.0"
      }
    },
    "node_modules/get-caller-file": {
      "version": "2.0.5",
      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "engines": {
        "node": "6.* || 8.* || >= 10.*"
      }
    },
    "node_modules/get-package-type": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8.0.0"
      }
    },
    "node_modules/get-stream": {
      "version": "6.0.1",
      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/glob": {
      "version": "7.2.3",
      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [REDACTED_SECRET]",
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "fs.realpath": "^1.0.0",
        "inflight": "^1.0.4",
        "inherits": "2",
        "minimatch": "^3.1.1",
        "once": "^1.3.0",
        "path-is-absolute": "^1.0.0"
      },
      "engines": {
        "node": "*"
      },
      "funding": {
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/glob-parent": {
      "version": "6.0.2",
      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "is-glob": "^4.0.3"
      },
      "engines": {
        "node": ">=10.13.0"
      }
    },
    "node_modules/glob/node_modules/brace-expansion": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "node_modules/glob/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^1.1.7"
      },
      "engines": {
        "node": "*"
      }
    },
    "node_modules/globals": {
      "version": "13.24.0",
      "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "type-fest": "^0.20.2"
      },
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/globby": {
      "version": "11.1.0",
      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "array-union": "^2.1.0",
        "dir-glob": "^3.0.1",
        "fast-glob": "^3.2.9",
        "ignore": "^5.2.0",
        "merge2": "^1.4.1",
        "slash": "^3.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/graceful-fs": {
      "version": "4.2.11",
      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/graphemer": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/handlebars": {
      "version": "4.7.8",
      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "minimist": "^1.2.5",
        "neo-async": "^2.6.2",
        "source-map": "^0.6.1",
        "wordwrap": "^1.0.0"
      },
      "bin": {
        "handlebars": "bin/handlebars"
      },
      "engines": {
        "node": ">=0.4.7"
      },
      "optionalDependencies": {
        "uglify-js": "^3.1.4"
      }
    },
    "node_modules/has-flag": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/hasown": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "function-bind": "^1.1.2"
      },
      "engines": {
        "node": ">= 0.4"
      }
    },
    "node_modules/html-escaper": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/human-signals": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "engines": {
        "node": ">=10.17.0"
      }
    },
    "node_modules/ignore": {
      "version": "5.3.2",
      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 4"
      }
    },
    "node_modules/import-fresh": {
      "version": "3.3.1",
      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "parent-module": "^1.0.0",
        "resolve-from": "^4.0.0"
      },
      "engines": {
        "node": ">=6"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/import-local": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "pkg-dir": "^4.2.0",
        "resolve-cwd": "^3.0.0"
      },
      "bin": {
        "import-local-fixture": "fixtures/cli.js"
      },
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/imurmurhash": {
      "version": "0.1.4",
      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.8.19"
      }
    },
    "node_modules/inflight": {
      "version": "1.0.6",
      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "once": "^1.3.0",
        "wrappy": "1"
      }
    },
    "node_modules/inherits": {
      "version": "2.0.4",
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/is-arrayish": {
      "version": "0.2.1",
      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/is-core-module": {
      "version": "2.16.1",
      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "hasown": "^2.0.2"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/is-extglob": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/is-fullwidth-code-point": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/is-generator-fn": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/is-glob": {
      "version": "4.0.3",
      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "is-extglob": "^2.1.1"
      },
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/is-number": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.12.0"
      }
    },
    "node_modules/is-path-inside": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/is-stream": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/isexe": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/istanbul-lib-coverage": {
      "version": "3.2.2",
      "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/istanbul-lib-instrument": {
      "version": "6.0.3",
      "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "@babel/core": "^7.23.9",
        "@babel/parser": "^7.23.9",
        "@istanbuljs/schema": "^0.1.3",
        "istanbul-lib-coverage": "^3.2.0",
        "semver": "^7.5.4"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/istanbul-lib-report": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "istanbul-lib-coverage": "^3.0.0",
        "make-dir": "^4.0.0",
        "supports-color": "^7.1.0"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/istanbul-lib-source-maps": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "debug": "^4.1.1",
        "istanbul-lib-coverage": "^3.0.0",
        "source-map": "^0.6.1"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/istanbul-reports": {
      "version": "3.2.0",
      "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "html-escaper": "^2.0.0",
        "istanbul-lib-report": "^3.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/jest": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/core": "^29.7.0",
        "@jest/types": "^29.6.3",
        "import-local": "^3.0.2",
        "jest-cli": "^29.7.0"
      },
      "bin": {
        "jest": "bin/jest.js"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
      },
      "peerDependenciesMeta": {
        "node-notifier": {
          "optional": true
        }
      }
    },
    "node_modules/jest-changed-files": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "execa": "^5.0.0",
        "jest-util": "^29.7.0",
        "p-limit": "^3.1.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-circus": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/environment": "^29.7.0",
        "@jest/expect": "^29.7.0",
        "@jest/test-result": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "co": "^4.6.0",
        "dedent": "^1.0.0",
        "is-generator-fn": "^2.0.0",
        "jest-each": "^29.7.0",
        "jest-matcher-utils": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-runtime": "^29.7.0",
        "jest-snapshot": "^29.7.0",
        "jest-util": "^29.7.0",
        "p-limit": "^3.1.0",
        "pretty-format": "^29.7.0",
        "pure-rand": "^6.0.0",
        "slash": "^3.0.0",
        "stack-utils": "^2.0.3"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-cli": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/core": "^29.7.0",
        "@jest/test-result": "^29.7.0",
        "@jest/types": "^29.6.3",
        "chalk": "^4.0.0",
        "create-jest": "^29.7.0",
        "exit": "^0.1.2",
        "import-local": "^3.0.2",
        "jest-config": "^29.7.0",
        "jest-util": "^29.7.0",
        "jest-validate": "^29.7.0",
        "yargs": "^17.3.1"
      },
      "bin": {
        "jest": "bin/jest.js"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
      },
      "peerDependenciesMeta": {
        "node-notifier": {
          "optional": true
        }
      }
    },
    "node_modules/jest-config": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/core": "^7.11.6",
        "@jest/test-sequencer": "^29.7.0",
        "@jest/types": "^29.6.3",
        "babel-jest": "^29.7.0",
        "chalk": "^4.0.0",
        "ci-info": "^3.2.0",
        "deepmerge": "^4.2.2",
        "glob": "^7.1.3",
        "graceful-fs": "^4.2.9",
        "jest-circus": "^29.7.0",
        "jest-environment-node": "^29.7.0",
        "jest-get-type": "^29.6.3",
        "jest-regex-util": "^29.6.3",
        "jest-resolve": "^29.7.0",
        "jest-runner": "^29.7.0",
        "jest-util": "^29.7.0",
        "jest-validate": "^29.7.0",
        "micromatch": "^4.0.4",
        "parse-json": "^5.2.0",
        "pretty-format": "^29.7.0",
        "slash": "^3.0.0",
        "strip-json-comments": "^3.1.1"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "peerDependencies": {
        "@types/node": "*",
        "ts-node": ">=9.0.0"
      },
      "peerDependenciesMeta": {
        "@types/node": {
          "optional": true
        },
        "ts-node": {
          "optional": true
        }
      }
    },
    "node_modules/jest-diff": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "chalk": "^4.0.0",
        "diff-sequences": "^29.6.3",
        "jest-get-type": "^29.6.3",
        "pretty-format": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-docblock": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "detect-newline": "^3.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-each": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "chalk": "^4.0.0",
        "jest-get-type": "^29.6.3",
        "jest-util": "^29.7.0",
        "pretty-format": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-environment-node": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/environment": "^29.7.0",
        "@jest/fake-timers": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "jest-mock": "^29.7.0",
        "jest-util": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-get-type": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-haste-map": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "@types/graceful-fs": "^4.1.3",
        "@types/node": "*",
        "anymatch": "^3.0.3",
        "fb-watchman": "^2.0.0",
        "graceful-fs": "^4.2.9",
        "jest-regex-util": "^29.6.3",
        "jest-util": "^29.7.0",
        "jest-worker": "^29.7.0",
        "micromatch": "^4.0.4",
        "walker": "^1.0.8"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      },
      "optionalDependencies": {
        "fsevents": "^2.3.2"
      }
    },
    "node_modules/jest-leak-detector": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "jest-get-type": "^29.6.3",
        "pretty-format": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-matcher-utils": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "chalk": "^4.0.0",
        "jest-diff": "^29.7.0",
        "jest-get-type": "^29.6.3",
        "pretty-format": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-message-util": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/code-frame": "^7.12.13",
        "@jest/types": "^29.6.3",
        "@types/stack-utils": "^2.0.0",
        "chalk": "^4.0.0",
        "graceful-fs": "^4.2.9",
        "micromatch": "^4.0.4",
        "pretty-format": "^29.7.0",
        "slash": "^3.0.0",
        "stack-utils": "^2.0.3"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-mock": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "jest-util": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-pnp-resolver": {
      "version": "1.2.3",
      "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      },
      "peerDependencies": {
        "jest-resolve": "*"
      },
      "peerDependenciesMeta": {
        "jest-resolve": {
          "optional": true
        }
      }
    },
    "node_modules/jest-regex-util": {
      "version": "29.6.3",
      "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-resolve": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "chalk": "^4.0.0",
        "graceful-fs": "^4.2.9",
        "jest-haste-map": "^29.7.0",
        "jest-pnp-resolver": "^1.2.2",
        "jest-util": "^29.7.0",
        "jest-validate": "^29.7.0",
        "resolve": "^1.20.0",
        "resolve.exports": "^2.0.0",
        "slash": "^3.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-resolve-dependencies": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "jest-regex-util": "^29.6.3",
        "jest-snapshot": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-runner": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/console": "^29.7.0",
        "@jest/environment": "^29.7.0",
        "@jest/test-result": "^29.7.0",
        "@jest/transform": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "emittery": "^0.13.1",
        "graceful-fs": "^4.2.9",
        "jest-docblock": "^29.7.0",
        "jest-environment-node": "^29.7.0",
        "jest-haste-map": "^29.7.0",
        "jest-leak-detector": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-resolve": "^29.7.0",
        "jest-runtime": "^29.7.0",
        "jest-util": "^29.7.0",
        "jest-watcher": "^29.7.0",
        "jest-worker": "^29.7.0",
        "p-limit": "^3.1.0",
        "source-map-support": "0.5.13"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-runtime": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/environment": "^29.7.0",
        "@jest/fake-timers": "^29.7.0",
        "@jest/globals": "^29.7.0",
        "@jest/source-map": "^29.6.3",
        "@jest/test-result": "^29.7.0",
        "@jest/transform": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "cjs-module-lexer": "^1.0.0",
        "collect-v8-coverage": "^1.0.0",
        "glob": "^7.1.3",
        "graceful-fs": "^4.2.9",
        "jest-haste-map": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-mock": "^29.7.0",
        "jest-regex-util": "^29.6.3",
        "jest-resolve": "^29.7.0",
        "jest-snapshot": "^29.7.0",
        "jest-util": "^29.7.0",
        "slash": "^3.0.0",
        "strip-bom": "^4.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-snapshot": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/core": "^7.11.6",
        "@babel/generator": "^7.7.2",
        "@babel/plugin-syntax-jsx": "^7.7.2",
        "@babel/plugin-syntax-typescript": "^7.7.2",
        "@babel/types": "^7.3.3",
        "@jest/expect-utils": "^29.7.0",
        "@jest/transform": "^29.7.0",
        "@jest/types": "^29.6.3",
        "babel-preset-current-node-syntax": "^1.0.0",
        "chalk": "^4.0.0",
        "expect": "^29.7.0",
        "graceful-fs": "^4.2.9",
        "jest-diff": "^29.7.0",
        "jest-get-type": "^29.6.3",
        "jest-matcher-utils": "^29.7.0",
        "jest-message-util": "^29.7.0",
        "jest-util": "^29.7.0",
        "natural-compare": "^1.4.0",
        "pretty-format": "^29.7.0",
        "semver": "^7.5.3"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-util": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "chalk": "^4.0.0",
        "ci-info": "^3.2.0",
        "graceful-fs": "^4.2.9",
        "picomatch": "^2.2.3"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-validate": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/types": "^29.6.3",
        "camelcase": "^6.2.0",
        "chalk": "^4.0.0",
        "jest-get-type": "^29.6.3",
        "leven": "^3.1.0",
        "pretty-format": "^29.7.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-validate/node_modules/camelcase": {
      "version": "6.3.0",
      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/jest-watcher": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/test-result": "^29.7.0",
        "@jest/types": "^29.6.3",
        "@types/node": "*",
        "ansi-escapes": "^4.2.1",
        "chalk": "^4.0.0",
        "emittery": "^0.13.1",
        "jest-util": "^29.7.0",
        "string-length": "^4.0.1"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-worker": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@types/node": "*",
        "jest-util": "^29.7.0",
        "merge-stream": "^2.0.0",
        "supports-color": "^8.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/jest-worker/node_modules/supports-color": {
      "version": "8.1.1",
      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "has-flag": "^4.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/chalk/supports-color?sponsor=1"
      }
    },
    "node_modules/js-tokens": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/js-yaml": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "argparse": "^2.0.1"
      },
      "bin": {
        "js-yaml": "bin/js-yaml.js"
      }
    },
    "node_modules/jsesc": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "bin": {
        "jsesc": "bin/jsesc"
      },
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/json-buffer": {
      "version": "3.0.1",
      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/json-parse-even-better-errors": {
      "version": "2.3.1",
      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/json-schema-traverse": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/json-stable-stringify-without-jsonify": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/json5": {
      "version": "2.2.3",
      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "bin": {
        "json5": "lib/cli.js"
      },
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/keyv": {
      "version": "4.5.4",
      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "json-buffer": "3.0.1"
      }
    },
    "node_modules/kleur": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/leven": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/levn": {
      "version": "0.4.1",
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "prelude-ls": "^1.2.1",
        "type-check": "~0.4.0"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/lines-and-columns": {
      "version": "1.2.4",
      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/locate-path": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-locate": "^5.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/lodash.memoize": {
      "version": "4.1.2",
      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/lodash.merge": {
      "version": "4.6.2",
      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/lru-cache": {
      "version": "5.1.1",
      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "yallist": "^3.0.2"
      }
    },
    "node_modules/make-dir": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "semver": "^7.5.3"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/make-error": {
      "version": "1.3.6",
      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/makeerror": {
      "version": "1.0.12",
      "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "dependencies": {
        "tmpl": "1.0.5"
      }
    },
    "node_modules/merge-stream": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/merge2": {
      "version": "1.4.1",
      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/micromatch": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "braces": "^3.0.3",
        "picomatch": "^2.3.1"
      },
      "engines": {
        "node": ">=8.6"
      }
    },
    "node_modules/mimic-fn": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/minimatch": {
      "version": "9.0.3",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^2.0.1"
      },
      "engines": {
        "node": ">=16 || 14 >=14.17"
      },
      "funding": {
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/minimist": {
      "version": "1.2.8",
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/ms": {
      "version": "2.1.3",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/natural-compare": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/neo-async": {
      "version": "2.6.2",
      "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/node-int64": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/node-releases": {
      "version": "2.0.27",
      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/normalize-path": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/npm-run-path": {
      "version": "4.0.1",
      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "path-key": "^3.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/once": {
      "version": "1.4.0",
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "wrappy": "1"
      }
    },
    "node_modules/onetime": {
      "version": "5.1.2",
      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "mimic-fn": "^2.1.0"
      },
      "engines": {
        "node": ">=6"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/optionator": {
      "version": "0.9.4",
      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "deep-is": "^0.1.3",
        "fast-levenshtein": "^2.0.6",
        "levn": "^0.4.1",
        "prelude-ls": "^1.2.1",
        "type-check": "^0.4.0",
        "word-wrap": "^1.2.5"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/p-limit": {
      "version": "3.1.0",
      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "yocto-queue": "^0.1.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/p-locate": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-limit": "^3.0.2"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/p-try": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/parent-module": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "callsites": "^3.0.0"
      },
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/parse-json": {
      "version": "5.2.0",
      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@babel/code-frame": "^7.0.0",
        "error-ex": "^1.3.1",
        "json-parse-even-better-errors": "^2.3.0",
        "lines-and-columns": "^1.1.6"
      },
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/path-exists": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/path-is-absolute": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/path-key": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/path-parse": {
      "version": "1.0.7",
      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/path-type": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/picocolors": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/picomatch": {
      "version": "2.3.1",
      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8.6"
      },
      "funding": {
        "url": "https://github.com/sponsors/jonschlinkert"
      }
    },
    "node_modules/pirates": {
      "version": "4.0.7",
      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/pkg-dir": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "find-up": "^4.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/pkg-dir/node_modules/find-up": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "locate-path": "^5.0.0",
        "path-exists": "^4.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/pkg-dir/node_modules/locate-path": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-locate": "^4.1.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/pkg-dir/node_modules/p-limit": {
      "version": "2.3.0",
      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-try": "^2.0.0"
      },
      "engines": {
        "node": ">=6"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/pkg-dir/node_modules/p-locate": {
      "version": "4.1.0",
      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "p-limit": "^2.2.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/prelude-ls": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/pretty-format": {
      "version": "29.7.0",
      "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "@jest/schemas": "^29.6.3",
        "ansi-styles": "^5.0.0",
        "react-is": "^18.0.0"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
      }
    },
    "node_modules/pretty-format/node_modules/ansi-styles": {
      "version": "5.2.0",
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
      }
    },
    "node_modules/prompts": {
      "version": "2.4.2",
      "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "kleur": "^3.0.3",
        "sisteransi": "^1.0.5"
      },
      "engines": {
        "node": ">= 6"
      }
    },
    "node_modules/punycode": {
      "version": "2.3.1",
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/pure-rand": {
      "version": "6.1.0",
      "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "individual",
          "url": "https://github.com/sponsors/dubzzz"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/fast-check"
        }
      ],
      "license": "MIT"
    },
    "node_modules/queue-microtask": {
      "version": "1.2.3",
      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT"
    },
    "node_modules/react-is": {
      "version": "18.3.1",
      "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/require-directory": {
      "version": "2.1.1",
      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/resolve": {
      "version": "1.22.11",
      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "is-core-module": "^2.16.1",
        "path-parse": "^1.0.7",
        "supports-preserve-symlinks-flag": "^1.0.0"
      },
      "bin": {
        "resolve": "bin/resolve"
      },
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/resolve-cwd": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "resolve-from": "^5.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/resolve-cwd/node_modules/resolve-from": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/resolve-from": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/resolve.exports": {
      "version": "2.0.3",
      "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/reusify": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "iojs": ">=1.0.0",
        "node": ">=0.10.0"
      }
    },
    "node_modules/rimraf": {
      "version": "3.0.2",
      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "deprecated": "Rimraf versions prior to v4 are no longer supported",
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "glob": "^7.1.3"
      },
      "bin": {
        "rimraf": "bin.js"
      },
      "funding": {
        "url": "https://github.com/sponsors/isaacs"
      }
    },
    "node_modules/run-parallel": {
      "version": "1.2.0",
      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/feross"
        },
        {
          "type": "patreon",
          "url": "https://www.patreon.com/feross"
        },
        {
          "type": "consulting",
          "url": "https://feross.org/support"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "queue-microtask": "^1.2.2"
      }
    },
    "node_modules/semver": {
      "version": "7.7.4",
      "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "bin": {
        "semver": "bin/semver.js"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/shebang-command": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "shebang-regex": "^3.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/shebang-regex": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/signal-exit": {
      "version": "3.0.7",
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/sisteransi": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/slash": {
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/source-map": {
      "version": "0.6.1",
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/source-map-support": {
      "version": "0.5.13",
      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "buffer-from": "^1.0.0",
        "source-map": "^0.6.0"
      }
    },
    "node_modules/sprintf-js": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause"
    },
    "node_modules/stack-utils": {
      "version": "2.0.6",
      "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "escape-string-regexp": "^2.0.0"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/stack-utils/node_modules/escape-string-regexp": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/string-length": {
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "char-regex": "^1.0.2",
        "strip-ansi": "^6.0.0"
      },
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/string-width": {
      "version": "4.2.3",
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "emoji-regex": "^8.0.0",
        "is-fullwidth-code-point": "^3.0.0",
        "strip-ansi": "^6.0.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/strip-ansi": {
      "version": "6.0.1",
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "ansi-regex": "^5.0.1"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/strip-bom": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/strip-final-newline": {
      "version": "2.0.0",
      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/strip-json-comments": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=8"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/supports-color": {
      "version": "7.2.0",
      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "has-flag": "^4.0.0"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/supports-preserve-symlinks-flag": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">= 0.4"
      },
      "funding": {
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/test-exclude": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "@istanbuljs/schema": "^0.1.2",
        "glob": "^7.1.4",
        "minimatch": "^3.0.4"
      },
      "engines": {
        "node": ">=8"
      }
    },
    "node_modules/test-exclude/node_modules/brace-expansion": {
      "version": "1.1.12",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "balanced-match": "^1.0.0",
        "concat-map": "0.0.1"
      }
    },
    "node_modules/test-exclude/node_modules/minimatch": {
      "version": "3.1.2",
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "brace-expansion": "^1.1.7"
      },
      "engines": {
        "node": "*"
      }
    },
    "node_modules/text-table": {
      "version": "0.2.0",
      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/tmpl": {
      "version": "1.0.5",
      "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-3-Clause"
    },
    "node_modules/to-regex-range": {
      "version": "5.0.1",
      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "is-number": "^7.0.0"
      },
      "engines": {
        "node": ">=8.0"
      }
    },
    "node_modules/ts-api-utils": {
      "version": "1.4.3",
      "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=16"
      },
      "peerDependencies": {
        "typescript": ">=4.2.0"
      }
    },
    "node_modules/ts-jest": {
      "version": "29.4.6",
      "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "bs-logger": "^0.2.6",
        "fast-json-stable-stringify": "^2.1.0",
        "handlebars": "^4.7.8",
        "json5": "^2.2.3",
        "lodash.memoize": "^4.1.2",
        "make-error": "^1.3.6",
        "semver": "^7.7.3",
        "type-fest": "^4.41.0",
        "yargs-parser": "^21.1.1"
      },
      "bin": {
        "ts-jest": "cli.js"
      },
      "engines": {
        "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
      },
      "peerDependencies": {
        "@babel/core": ">=7.0.0-beta.0 <8",
        "@jest/transform": "^29.0.0 || ^30.0.0",
        "@jest/types": "^29.0.0 || ^30.0.0",
        "babel-jest": "^29.0.0 || ^30.0.0",
        "jest": "^29.0.0 || ^30.0.0",
        "jest-util": "^29.0.0 || ^30.0.0",
        "typescript": ">=4.3 <6"
      },
      "peerDependenciesMeta": {
        "@babel/core": {
          "optional": true
        },
        "@jest/transform": {
          "optional": true
        },
        "@jest/types": {
          "optional": true
        },
        "babel-jest": {
          "optional": true
        },
        "esbuild": {
          "optional": true
        },
        "jest-util": {
          "optional": true
        }
      }
    },
    "node_modules/ts-jest/node_modules/type-fest": {
      "version": "4.41.0",
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "(MIT OR CC0-1.0)",
      "engines": {
        "node": ">=16"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/type-check": {
      "version": "0.4.0",
      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "prelude-ls": "^1.2.1"
      },
      "engines": {
        "node": ">= 0.8.0"
      }
    },
    "node_modules/type-detect": {
      "version": "4.0.8",
      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=4"
      }
    },
    "node_modules/type-fest": {
      "version": "0.20.2",
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "(MIT OR CC0-1.0)",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    },
    "node_modules/typescript": {
      "version": "5.9.3",
      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "bin": {
        "tsc": "bin/tsc",
        "tsserver": "bin/tsserver"
      },
      "engines": {
        "node": ">=14.17"
      }
    },
    "node_modules/uglify-js": {
      "version": "3.19.3",
      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "optional": true,
      "bin": {
        "uglifyjs": "bin/uglifyjs"
      },
      "engines": {
        "node": ">=0.8.0"
      }
    },
    "node_modules/undici-types": {
      "version": "6.21.0",
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/update-browserslist-db": {
      "version": "1.2.3",
      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "funding": [
        {
          "type": "opencollective",
          "url": "https://opencollective.com/browserslist"
        },
        {
          "type": "tidelift",
          "url": "https://tidelift.com/funding/github/npm/browserslist"
        },
        {
          "type": "github",
          "url": "https://github.com/sponsors/ai"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "escalade": "^3.2.0",
        "picocolors": "^1.1.1"
      },
      "bin": {
        "update-browserslist-db": "cli.js"
      },
      "peerDependencies": {
        "browserslist": ">= 4.21.0"
      }
    },
    "node_modules/uri-js": {
      "version": "4.4.1",
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "BSD-2-Clause",
      "dependencies": {
        "punycode": "^2.1.0"
      }
    },
    "node_modules/uuid": {
      "version": "9.0.1",
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
      "integrity": [REDACTED_SECRET],
      "funding": [
        "https://github.com/sponsors/broofa",
        "https://github.com/sponsors/ctavan"
      ],
      "license": "MIT",
      "bin": {
        "uuid": "dist/bin/uuid"
      }
    },
    "node_modules/v8-to-istanbul": {
      "version": "9.3.0",
      "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "@jridgewell/trace-mapping": "^0.3.12",
        "@types/istanbul-lib-coverage": "^2.0.1",
        "convert-source-map": "^2.0.0"
      },
      "engines": {
        "node": ">=10.12.0"
      }
    },
    "node_modules/walker": {
      "version": "1.0.8",
      "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "Apache-2.0",
      "dependencies": {
        "makeerror": "1.0.12"
      }
    },
    "node_modules/which": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "isexe": "^2.0.0"
      },
      "bin": {
        "node-which": "bin/node-which"
      },
      "engines": {
        "node": ">= 8"
      }
    },
    "node_modules/word-wrap": {
      "version": "1.2.5",
      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/wordwrap": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT"
    },
    "node_modules/wrap-ansi": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "ansi-styles": "^4.0.0",
        "string-width": "^4.1.0",
        "strip-ansi": "^6.0.0"
      },
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
      }
    },
    "node_modules/wrappy": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/write-file-atomic": {
      "version": "4.0.2",
      "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "dependencies": {
        "imurmurhash": "^0.1.4",
        "signal-exit": "^3.0.7"
      },
      "engines": {
        "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
      }
    },
    "node_modules/y18n": {
      "version": "5.0.8",
      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "engines": {
        "node": ">=10"
      }
    },
    "node_modules/yallist": {
      "version": "3.1.1",
      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC"
    },
    "node_modules/yargs": {
      "version": "17.7.2",
      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "dependencies": {
        "cliui": "^8.0.1",
        "escalade": "^3.1.1",
        "get-caller-file": "^2.0.5",
        "require-directory": "^2.1.1",
        "string-width": "^4.2.3",
        "y18n": "^5.0.5",
        "yargs-parser": "^21.1.1"
      },
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/yargs-parser": {
      "version": "21.1.1",
      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "ISC",
      "engines": {
        "node": ">=12"
      }
    },
    "node_modules/yocto-queue": {
      "version": "0.1.0",
      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
      "integrity": [REDACTED_SECRET],
      "dev": true,
      "license": "MIT",
      "engines": {
        "node": ">=10"
      },
      "funding": {
        "url": "https://github.com/sponsors/sindresorhus"
      }
    }
  }
}


path: package.json
content: {
  "name": "cinematic-script-writer",
  "version": "1.4.2",
  "description": "OpenClaw Agent Skills - Cinematic Script Writer with consistency, cinematography, and storage",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "bin": {
    "cinematic-script": "dist/bin/cinematic-script.js"
  },
  "scripts": {
    "build": "tsc",
    "test": "jest",
    "lint": "eslint . --ext .ts",
    "lint:fix": "eslint . --ext .ts --fix",
    "clean": "rm -rf dist",
    "prepare": "npm run build"
  },
  "keywords": [
    "openclaw",
    "cinematic-script-writer",
    "ai",
    "agent",
    "skills",
    "cinematography",
    "script-writing",
    "video-generation",
    "character-consistency",
    "google-drive"
  ],
  "author": "Praveen Kumar",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/praveenspeaks/cinematic-script-writer.git"
  },
  "bugs": {
    "url": "https://github.com/praveenspeaks/cinematic-script-writer/issues"
  },
  "homepage": "https://github.com/praveenspeaks/cinematic-script-writer#readme",
  "devDependencies": {
    "@types/jest": "^29.5.0",
    "@types/node": "^20.0.0",
    "@types/uuid": "^9.0.0",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "eslint": "^8.45.0",
    "jest": "^29.0.0",
    "ts-jest": "^29.1.0",
    "typescript": "^5.0.0"
  },
  "dependencies": {
    "uuid": "^9.0.0"
  },
  "files": [
    "dist/**/*",
    "SKILL.md",
    "README.md",
    "LICENSE"
  ],
  "engines": {
    "node": ">=18.0.0"
  }
}


path: report.md
content: # Cinematic Script Writer Skill - Issue Report & Fix Guide

## Problem Summary

During installation, it took **multiple workarounds** to get this skill recognized by OpenClaw. Here's everything that's wrong and how to fix it for a clean one-line install.

---

## Issue 1: Missing YAML Frontmatter (CRITICAL)

**The #1 reason this skill doesn't work after installation.**

The published SKILL.md on ClawHub starts directly with:

```markdown
# Cinematic Script Writer
```

But OpenClaw **requires** YAML frontmatter at the top of every SKILL.md. Without it, the skill is completely invisible to the engine. OpenClaw uses a 3-level loading system:

- **Level 1** (always in context): `name` + `description` from YAML frontmatter — this is how OpenClaw decides when to activate your skill
- **Level 2** (loaded on trigger): The full SKILL.md body
- **Level 3** (on demand): Scripts, references, assets

Without frontmatter, Level 1 never loads, so the skill never triggers.

**Fix:** Add this to the very top of SKILL.md:

```yaml
---
name: cinematic-script-writer
description: >
  Create professional cinematic scripts for AI video generation with character
  consistency and cinematography knowledge. Use when the user wants to write
  a cinematic script, create story contexts with characters, generate image
  prompts for AI video tools, or needs cinematography guidance (camera angles,
  lighting, color grading). Also use for character consistency sheets, voice
  profiles, and saving scripts to Google Drive.
metadata:
  {
    "openclaw": {
      "emoji": "🎬"
    }
  }
---
```

Notice the `description` includes **"Use when..."** trigger phrases. This is how well-written bundled skills (like `summarize`, `clawhub`, `github`) help OpenClaw know when to activate the skill.

---

## Issue 2: Weak Description (No Trigger Phrases)

Even the version we manually fixed only had:

> "Create professional cinematic scripts for AI video generation with character consistency and cinematography knowledge."

Compare with a well-written bundled skill (`summarize`):

> "Summarize or extract text/transcripts from URLs, podcasts, and local files (great fallback for 'transcribe this YouTube/video')."

The description is OpenClaw's **primary trigger mechanism**. It should include natural-language triggers that match how users actually ask for things.

---

## Issue 3: Body Content is a JavaScript API Reference, Not AI Instructions

The SKILL.md body contains code like:

```javascript
const context = await skill.createContext("Kutil's Adventure", ...);
const ideas = await skill.generateStoryIdeas(context.id, 3);
```

This is a **developer SDK reference**. But OpenClaw skills are meant to be **AI agent instructions** — they tell the AI *how* to accomplish the task, not show JavaScript function signatures. The AI model can't call `skill.createContext()` — it needs plain-language instructions or executable scripts in a `scripts/` directory.

**Fix:** Rewrite the body as instructions for the AI agent. For example:

```markdown
## How to Use This Skill

When a user wants to create a cinematic script:

1. Ask for the story concept, era/setting, and visual style
2. Create character profiles with consistent visual descriptions
3. Generate 3 story ideas and let the user pick one
4. Write the full cinematic script with:
   - Scene descriptions with camera angles and lighting
   - Character dialogue with voice consistency notes
   - Image generation prompts for each shot
5. Validate for anachronisms (no modern items in historical settings)
6. Offer to save to Google Drive or local storage
```

---

## Issue 4: No `requires` or `install` Metadata

Bundled skills that need external tools declare them in frontmatter:

```yaml
metadata:
  {
    "openclaw": {
      "emoji": "🍌",
      "requires": { "bins": ["uv"], "env": ["GEMINI_API_KEY"] },
      "primaryEnv": "GEMINI_API_KEY",
      "install": [
        { "id": "uv-brew", "kind": "brew", "formula": "uv", "bins": ["uv"] }
      ]
    }
  }
```

If cinematic-script-writer needs Google Drive API credentials or any external tools, these should be declared so OpenClaw can check/install them automatically.

---

## Issue 5: ClawHub CLI Installation Path

When we ran `clawdhub install cinematic-script-writer`, it installed to `./skills/` (current working directory) instead of OpenClaw's skill directories. Users then have to manually copy files to the right location. This is a `clawdhub` CLI issue, not your skill's issue — but it's worth noting.

---

## Issue 6: Version Mismatch

`_meta.json` says `"version": "0.1.1"` but the SKILL.md body says `Version 1.3.0`. These should match.

---

## What You Need to Do (Checklist)

To make this a clean one-line install (`openclaw skill install cinematic-script-writer` or `clawdhub install cinematic-script-writer`):

| # | Fix | Priority |
|---|-----|----------|
| 1 | Add YAML frontmatter with `name`, `description`, and `metadata` | **CRITICAL** |
| 2 | Write a rich `description` with "Use when..." trigger phrases | **HIGH** |
| 3 | Rewrite body as AI agent instructions, not JS API docs | **HIGH** |
| 4 | Add `requires`/`install` in metadata if external deps are needed | **MEDIUM** |
| 5 | Sync version number between `_meta.json` and SKILL.md | **LOW** |
| 6 | Add executable scripts in `scripts/` dir for deterministic tasks (e.g., Google Drive upload, prompt generation) | **MEDIUM** |
| 7 | Remove unnecessary files (`README.md`, `CHANGELOG.md`, etc.) if any exist — skill-creator docs say not to | **LOW** |

---

## Ideal SKILL.md Structure

Here's the template based on how properly working bundled skills are structured:

```markdown
---
name: cinematic-script-writer
description: >
  Create professional cinematic scripts for AI video generation with character
  consistency and cinematography knowledge. Use when the user wants to write
  a cinematic script, create story contexts, generate AI image prompts for
  video scenes, or needs camera angle/lighting/color grading guidance.
metadata:
  {
    "openclaw": {
      "emoji": "🎬"
    }
  }
---

# Cinematic Script Writer

[AI agent instructions here — what to do step by step,
not JavaScript API references]

## Cinematography Reference

[Camera angles, lighting techniques, etc. as reference
material the AI can use when writing scripts]

## Character Consistency Rules

[Rules for maintaining consistent character appearance
across shots]

## Output Format

[What the final script should look like]
```

---

## Comparison with Working Bundled Skills

| Feature | nano-banana-pro | summarize | github | cinematic-script-writer |
|---|---|---|---|---|
| YAML frontmatter | Yes | Yes | Yes | **MISSING** |
| Trigger phrases in description | Yes | Yes | Yes | **No** |
| `requires` metadata | bins + env | bins | bins | **None** |
| `install` instructions | brew | brew | brew + apt | **None** |
| Body format | AI instructions | AI instructions | AI instructions | **JS API docs** |
| Scripts directory | Yes (`scripts/`) | No (not needed) | No (uses `gh` CLI) | **No** |

---

## Summary

Once you fix the SKILL.md with proper frontmatter and rewrite the body as AI agent instructions, then republish to ClawHub, anyone should be able to install it with:

```bash
clawdhub install cinematic-script-writer
```

And OpenClaw will automatically recognize and trigger it when users ask for cinematic scripts.


path: skill-template/README.md
content: # Skill Template

A template for creating OpenClaw-compatible skills.

## Skill Structure

```
my-skill/
├── skill.json          # Skill manifest
├── index.ts            # Main entry point
├── schema.json         # Configuration schema
├── README.md           # Documentation
└── tests/
    └── index.test.ts   # Tests
```

## Quick Start

1. Copy this template: `cp -r skill-template my-new-skill`
2. Update `skill.json` with your skill info
3. Implement your logic in `index.ts`
4. Test your skill

## Skill Manifest (skill.json)

```json
{
  "name": "my-skill",
  "version": "1.0.0",
  "description": "What this skill does",
  "author": "Your Name",
  "entry": "index.ts",
  "config": {
    "schema": "schema.json"
  },
  "permissions": ["fs:read", "http:request"],
  "tools": [
    {
      "name": "doSomething",
      "description": "Does something useful"
    }
  ]
}
```


path: skill-template/index.ts
content: /**
 * Skill Template
 * 
 * This is the main entry point for your skill.
 * Export functions that the agent can call as tools.
 */

// Types for skill context and configuration
interface SkillContext {
  userId: string;
  sessionId: string;
  memory: MemoryStore;
  logger: Logger;
}

interface SkillConfig {
  greetingPrefix?: string;
  enableLogging?: boolean;
}

interface MemoryStore {
  get(key: string): Promise<any>;
  set(key: string, value: any): Promise<void>;
  delete(key: string): Promise<void>;
}

interface Logger {
  debug(msg: string): void;
  info(msg: string): void;
  warn(msg: string): void;
  error(msg: string): void;
}

// Skill class - main implementation
export class SkillTemplate {
  private config: SkillConfig;
  private context: SkillContext;

  constructor(config: SkillConfig, context: SkillContext) {
    this.config = config;
    this.context = context;
  }

  /**
   * Greet the user
   * This is a simple example tool
   */
  async greet(name: string): Promise<string> {
    const prefix = this.config.greetingPrefix || "Hello";
    const message = `${prefix}, ${name}! 👋`;
    
    if (this.config.enableLogging) {
      this.context.logger.debug(`Greeting user: ${name}`);
    }

    // Store greeting in memory
    await this.context.memory.set(`lastGreeting:${this.context.userId}`, {
      name,
      timestamp: new Date().toISOString()
    });

    return message;
  }

  /**
   * Perform a calculation
   * Example of a tool that does something useful
   */
  async calculate(expression: string): Promise<{ result: number; expression: string }> {
    if (this.config.enableLogging) {
      this.context.logger.debug(`Calculating: ${expression}`);
    }

    // Simple calculation - in production, use a proper math parser
    try {
      // WARNING: eval is dangerous, use a safe math parser in production
      // This is just for demonstration
      const result = Function('"use strict"; return (' + expression + ')')();
      
      return {
        result,
        expression
      };
    } catch (error) {
      throw new Error(`Invalid expression: ${expression}`);
    }
  }

  /**
   * Get last greeting from memory
   */
  async getLastGreeting(): Promise<any> {
    return await this.context.memory.get(`lastGreeting:${this.context.userId}`);
  }
}

// Factory function - the agent calls this to create your skill instance
export default function createSkill(config: SkillConfig, context: SkillContext) {
  return new SkillTemplate(config, context);
}

// Export types for TypeScript users
export type { SkillConfig, SkillContext };


path: skill-template/schema.json
content: {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "greetingPrefix": {
      "type": "string",
      "description": "Prefix for greeting messages",
      "default": "Hello"
    },
    "enableLogging": {
      "type": "boolean",
      "description": "Enable debug logging",
      "default": false
    }
  },
  "required": []
}


path: skill-template/skill.json
content: {
  "$schema": "https://clawhub.ai/schemas/skill.json",
  "name": "skill-template",
  "version": "1.0.0",
  "description": "Template for creating OpenClaw skills",
  "author": "Your Name",
  "license": "MIT",
  "entry": "index.ts",
  "config": {
    "schema": "schema.json",
    "required": false
  },
  "permissions": [
    "fs:read",
    "fs:write",
    "http:request"
  ],
  "tools": [
    {
      "name": "greet",
      "description": "Greets the user with a personalized message"
    },
    {
      "name": "calculate",
      "description": "Performs a calculation"
    }
  ],
  "dependencies": {},
  "tags": ["template", "example"]
}


path: skill-template/tests/index.test.ts
content: import createSkill, { SkillTemplate } from '../index';

describe('SkillTemplate', () => {
  let skill: SkillTemplate;
  let mockMemory: any;
  let mockLogger: any;

  beforeEach(() => {
    mockMemory = {
      get: jest.fn(),
      set: jest.fn(),
      delete: jest.fn(),
    };

    mockLogger = {
      debug: jest.fn(),
      info: jest.fn(),
      warn: jest.fn(),
      error: jest.fn(),
    };

    skill = createSkill(
      { greetingPrefix: 'Hi', enableLogging: true },
      { userId: 'user-123', sessionId: 'session-456', memory: mockMemory, logger: mockLogger }
    );
  });

  describe('greet', () => {
    it('should greet user with custom prefix', async () => {
      const result = await skill.greet('Alice');
      expect(result).toBe('Hi, Alice! 👋');
    });

    it('should store greeting in memory', async () => {
      await skill.greet('Alice');
      expect(mockMemory.set).toHaveBeenCalledWith(
        'lastGreeting:user-123',
        expect.objectContaining({ name: 'Alice' })
      );
    });
  });

  describe('calculate', () => {
    it('should perform basic calculation', async () => {
      const result = await skill.calculate('2 + 2');
      expect(result.result).toBe(4);
      expect(result.expression).toBe('2 + 2');
    });

    it('should handle complex expressions', async () => {
      const result = await skill.calculate('10 * 5 + 3');
      expect(result.result).toBe(53);
    });
  });
});


path: skills/cinematic-script-writer/EXAMPLE-CONSISTENCY.md
content: # 🎯 Character & Environment Consistency Example

This example shows how to use the consistency system to ensure your characters, voices, and environments stay consistent across all generated content.

## The Problem

Without consistency:
- ❌ Kutil looks different in every shot
- ❌ Characters wear modern clothes in Ramayana era
- ❌ Buildings look like modern architecture
- ❌ Characters sound different in each scene

With consistency:
- ✅ Kutil always has purple fur, small horns, golden eyes
- ✅ Everyone wears era-appropriate clothing (dhotis, sarees, no glasses!)
- ✅ Architecture is stone temples and mud huts
- ✅ Each character has a distinct, consistent voice

## Step-by-Step Setup

### Step 1: Create Context with Consistency

```typescript
const skill = agent.tools['cinematic-script-writer'];

// First, create your base context
const kutilContext = await skill.createContext(
  "Kutil - The Cursed Rakshasa",
  "A lovable rakshasa's misadventures",
  [
    {
      name: "Kutil",
      description: "A small, cute rakshasa with purple fur",
      personality: "Mischievous, determined, secretly kind",
      appearance: "Purple fluffy fur, small curved horns, big expressive golden eyes",
      role: "protagonist",
      backstory: "Cursed by Saint Vardhan - bad deeds become good",
      specialTraits: ["Curse of unintended goodness", "Loves sweets"]
    },
    {
      name: "Saint Vardhan",
      description: "An ancient wise sage",
      personality: "Wise, patient, mischievous sense of humor",
      appearance: "Long white beard with flowers, saffron robes, peaceful aura",
      role: "supporting"
    },
    {
      name: "Maya",
      description: "A clever village girl",
      personality: "Intelligent, brave, quick-witted",
      appearance: "Young girl in simple village cotton clothes, curious eyes",
      role: "supporting"
    }
  ],
  "Ramayana Era",
  "Ancient India - Treta Yuga",
  "Lanka and surrounding villages",
  "short",
  "comedy",
  "All ages",
  "Stylized 3D animation with Indian art influences"
);

// Now setup consistency guides
const { guides } = await skill.setupContextWithConsistency(
  kutilContext,
  {
    // Detailed visual descriptions for each character
    [kutilContext.characters[0].id]: `
      Kutil is a small cute rakshasa (mythical being) with:
      - Fluffy purple fur covering entire body
      - Two small curved horns on head (cream colored tips)
      - Large round golden eyes with black pupils
      - Small fangs visible when smiling
      - Pointed ears with pink insides
      - Short tail with purple fur
      - About 3 feet tall, chibi proportions
      - Expressive face showing emotions clearly
    `,
    [kutilContext.characters[1].id]: `
      Saint Vardhan is an elderly sage with:
      - Long flowing white beard with flowers woven in
      - Kind wrinkled face with twinkling blue eyes
      - Saffron/orange traditional robes
      - Wooden staff with carvings
      - Peaceful glowing aura
      - Barefoot
    `,
    [kutilContext.characters[2].id]: `
      Maya is a young village girl with:
      - Dark brown hair in simple braid
      - Brown eyes full of curiosity
      - Simple white cotton saree/dress
      - Barefoot
      - Carries a basket
      - Around 10 years old
    `
  }
);

console.log("✅ Consistency guides created!");
console.log("Character References:", Object.keys(guides.characters));
console.log("Voice Profiles:", Object.keys(guides.voices));
console.log("Environment Guide:", guides.environment.era);
```

### Step 2: View Consistency Guides

```typescript
// Get Kutil's character reference
const kutilRef = skill.getCharacterReference(kutilContext.characters[0].id);
console.log("Kutil's Reference Sheet:", {
  baseDescription: kutilRef.visual.baseDescription,
  signatureColor: kutilRef.visual.colorPalette.signature,
  keyFeatures: kutilRef.visual.features,
  wardrobe: kutilRef.wardrobe.defaultOutfit.description
});

// Get voice profile
const kutilVoice = skill.getVoiceProfile(kutilContext.characters[0].id);
console.log("Kutil's Voice:", {
  pitch: kutilVoice.speech.pitch,
  catchphrases: kutilVoice.language.catchphrases,
  examples: kutilVoice.examples
});

// Get environment guide
const envGuide = skill.getEnvironmentGuide(kutilContext.id);
console.log("Environment Rules:", {
  era: envGuide.eraSpecs.name,
  forbiddenItems: envGuide.eraSpecs.anachronismsForbidden.slice(0, 5),
  architecture: envGuide.architecture.buildingStyles.map(b => b.type),
  clothingMaterials: envGuide.clothing.materials
});
```

### Step 3: Build Consistent Image Prompts

```typescript
// Build prompts with full consistency
const prompts = skill.buildConsistentPrompts({
  characterIds: [kutilContext.characters[0].id],  // Kutil
  contextId: kutilContext.id,
  shotType: 'close-up',
  cameraAngle: 'low-angle',
  cameraMovement: 'static',
  lighting: 'golden-hour',
  mood: 'determined',
  action: 'trying to look evil but looking cute',
  timeOfDay: 'afternoon',
  includeEnvironment: true
});

console.log("=== IMAGE PROMPT ===");
console.log(prompts.imagePrompt);
// Output: close-up shot, low-angle camera angle, Kutil is a small cute rakshasa with purple fluffy fur, 
// small curved horns, large round golden eyes, purple, golden, fluffy, wearing simple traditional dhoti, 
// Ramayana Era setting, Lanka and surrounding villages, stone temple architecture, golden-hour lighting, 
// afternoon light, determined mood, Stylized 3D animation with Indian art influences, 
// consistent character design, same character across frames, highly detailed, 8k, cinematic composition

console.log("\n=== NEGATIVE PROMPT ===");
console.log(prompts.negativePrompt);
// Output: inconsistent character design, different character in each frame, changing features, 
// wrong eye color, wrong hair color, modern clothing, glasses, watches, plastic, synthetic fabrics, 
// modern furniture, blurry, low quality, deformed...

console.log("\n=== CONSISTENCY NOTES ===");
console.log(prompts.consistencyNotes);

console.log("\n=== VALIDATION WARNINGS ===");
console.log(prompts.validationWarnings);
```

### Step 4: Generate Multiple Shots with Consistency

```typescript
// Generate a series of shots for the same scene
const shots = [
  {
    type: 'close-up',
    angle: 'low-angle',
    action: 'evil grin attempt',
    mood: 'mischievous'
  },
  {
    type: 'medium',
    angle: 'eye-level', 
    action: 'confused expression',
    mood: 'confused'
  },
  {
    type: 'wide',
    angle: 'high-angle',
    action: 'accidentally helping villagers',
    mood: 'heroic-irony'
  }
];

const shotPrompts = shots.map(shot => {
  return skill.buildConsistentPrompts({
    characterIds: [kutilContext.characters[0].id],
    contextId: kutilContext.id,
    shotType: shot.type,
    cameraAngle: shot.angle,
    cameraMovement: 'static',
    lighting: 'golden-hour',
    mood: shot.mood,
    action: shot.action
  });
});

// All prompts will have the SAME character description!
// Kutil will look consistent across all shots
```

### Step 5: Voice Consistency in Dialogue

```typescript
// Get voice guidelines for writing dialogue
const kutilVoiceGuide = skill.generateVoiceGuidelines(kutilContext.characters[0].id);
console.log(kutilVoiceGuide);

// Output:
// Voice Profile for Kutil:
// - Pitch: high, Speed: fast, Volume: normal
// - Vocabulary: simple, Formality: casual
// - Catchphrases: "I am evil!", "Curse you!"
// - Speech Examples:
//   - Greeting: "Tremble before me!"
//   - Question: "What do you mean I'm helping?"
//   - Exclamation: "No, not again!"

// Use this to write consistent dialogue
const dialogue = {
  kutil: [
    {
      text: "Today I shall steal all the sweets! Muahaha!",
      tone: "trying-to-be-evil",
      notes: "High pitch, fast speech, overconfident"
    },
    {
      text: "Wait... why am I arranging them beautifully?",
      tone: "confused",
      notes: "Speed slows down, pitch raises"
    },
    {
      text: "Curse you, Saint Vardhan!",
      tone: "frustrated",
      notes: "Use catchphrase"
    }
  ]
};
```

### Step 6: Validate for Anachronisms

```typescript
// Test a prompt that might have issues
const badPrompt = "Kutil wearing sunglasses and holding a smartphone in a stone temple";

const validation = skill.validatePrompt(
  badPrompt,
  [kutilContext.characters[0].id],
  kutilContext.id
);

console.log(validation);
// Output:
// {
//   valid: false,
//   errors: [
//     'Anachronism detected: "glasses" does not belong in Ramayana Era',
//     'Anachronism detected: "smartphone" does not belong in Ramayana Era'
//   ],
//   warnings: [...],
//   suggestions: [
//     'Consider using era-appropriate material: cotton',
//     'Consider using era-appropriate material: silk'
//   ]
// }

// Fix the prompt
const goodPrompt = "Kutil in traditional dhoti holding a clay pot in a stone temple";
const goodValidation = skill.validatePrompt(
  goodPrompt,
  [kutilContext.characters[0].id],
  kutilContext.id
);
console.log(goodValidation.valid); // true
```

### Step 7: Complete Workflow

```typescript
async function createConsistentScene(contextId: string, sceneNumber: number) {
  const skill = agent.tools['cinematic-script-writer'];
  const context = await skill.getContext(contextId);
  
  // Get all consistency data
  const characterRefs = {};
  const voiceProfiles = {};
  
  for (const char of context.characters) {
    characterRefs[char.id] = skill.getCharacterReference(char.id);
    voiceProfiles[char.id] = skill.getVoiceProfile(char.id);
  }
  
  const envGuide = skill.getEnvironmentGuide(contextId);
  
  // Define shots for the scene
  const shots = [
    {
      number: 1,
      description: "Kutil plans mischief",
      type: "close-up",
      angle: "low-angle",
      characters: [context.characters[0].id],
      action: "evil plotting expression",
      lighting: "dramatic-shadows"
    },
    {
      number: 2,
      description: "Curse activates",
      type: "wide",
      angle: "high-angle",
      characters: [context.characters[0].id],
      action: "magical transformation",
      lighting: "golden-magic-light"
    },
    {
      number: 3,
      description: "Villagers celebrate",
      type: "medium",
      angle: "eye-level",
      characters: context.characters.map(c => c.id),
      action: "celebration scene",
      lighting: "warm-sunlight"
    }
  ];
  
  // Generate consistent prompts for all shots
  const shotPrompts = shots.map(shot => {
    return {
      ...shot,
      prompts: skill.buildConsistentPrompts({
        characterIds: shot.characters,
        contextId,
        shotType: shot.type,
        cameraAngle: shot.angle,
        cameraMovement: 'static',
        lighting: shot.lighting,
        mood: 'comedy',
        action: shot.action
      })
    };
  });
  
  return {
    scene: sceneNumber,
    context,
    characterRefs,
    voiceProfiles,
    environment: envGuide,
    shots: shotPrompts
  };
}

// Use it
const scene1 = await createConsistentScene(kutilContext.id, 1);

// scene1 now contains:
// - Character references ensuring visual consistency
// - Voice profiles ensuring dialogue consistency  
// - Environment guide ensuring era-appropriate elements
// - Shot prompts with consistency built-in
```

## Consistency Features Summary

### Character Consistency
- ✅ Reference sheets with detailed visual breakdown
- ✅ Color palette enforcement
- ✅ Wardrobe variations for different situations
- ✅ Key features tracking (eyes, hair, build)
- ✅ Style keywords for AI generation

### Voice Consistency  
- ✅ Pitch, speed, volume profiles
- ✅ Vocabulary and formality levels
- ✅ Catchphrases and recurring phrases
- ✅ Emotional variations
- ✅ Speech examples

### Environment Consistency
- ✅ Era-appropriate architecture
- ✅ Period-accurate clothing materials
- ✅ Forbidden anachronism detection
- ✅ Props and objects validation
- ✅ Society and customs guidelines

### Validation
- ✅ Anachronism detection
- ✅ Era-accurate material suggestions
- ✅ Consistency warnings
- ✅ Prompt corrections

## Example Output

```typescript
// Generated prompt for Kutil
{
  imagePrompt: "close-up shot, low-angle camera angle, Kutil is a small cute rakshasa with fluffy purple fur covering entire body, two small curved horns on head cream colored tips, large round golden eyes with black pupils, small fangs visible when smiling, pointed ears with pink insides, short tail with purple fur, about 3 feet tall chibi proportions, expressive face, purple golden fluffy, wearing simple traditional cotton dhoti, Ramayana Era setting, Lanka and surrounding villages, stone temple architecture with intricate carvings, mud huts with thatched roofs, golden-hour lighting, afternoon light, mischievous mood, Stylized 3D animation with Indian art influences, consistent character design, same character across frames, highly detailed, 8k, cinematic composition",
  
  negativePrompt: "inconsistent character design, different character in each frame, changing features, wrong eye color, wrong hair color, anatomical errors, modern clothing, glasses, watches, plastic, synthetic fabrics, modern furniture, modern buildings, electric lights, metal utensils, blurry, low quality, deformed, mutated, extra limbs, missing limbs, bad anatomy",
  
  consistencyNotes: "=== CHARACTER CONSISTENCY ===\nKutil:\n  Base: Kutil is a small cute rakshasa...\n  Signature Colors: purple, golden\n  Key Features: golden eyes, purple fluffy hair, small build\n  Wardrobe: Simple cotton dhoti...\n\n=== ENVIRONMENT CONSISTENCY ===\nEra: Ramayana Era\nLocation: Lanka and surrounding villages\nArchitecture: Temple, Palace, Hut, Market\nForbidden Elements: glasses, watches, plastic, synthetic fabrics...",
  
  validationWarnings: []
}
```

This ensures Kutil looks the same in every shot, wears appropriate clothing, and stays true to the Ramayana era setting! 🎬


path: skills/cinematic-script-writer/EXAMPLE-KUTIL.md
content: # 🎬 Example: Kutil's Cursed Adventure

Complete workflow example for creating a comic video about Kutil, the cursed rakshasa.

## 📖 Story Premise

**Kutil** - A cute rakshasa from Lanka in Ramayana era, cursed by a saint that whenever he does something wrong, it transforms into something good.

## 🚀 Step-by-Step Usage

### Step 1: Create the Context

```typescript
const skill = agent.tools['cinematic-script-writer'];

const kutilContext = await skill.createContext(
  "Kutil - The Cursed Rakshasa",
  "A lovable rakshasa's misadventures where every bad deed turns into accidental heroism",
  [
    {
      name: "Kutil",
      description: "A small, cute rakshasa with purple fur, tiny horns, and big innocent eyes. Tries his best to be scary and evil but fails adorably.",
      personality: "Mischievous, determined, secretly kind-hearted, frustrated by his curse, optimistic",
      appearance: "Purple fluffy fur, small curved horns, big expressive golden eyes, wears traditional rakshasa attire but looks cute in it, small fangs that show when he smiles",
      role: "protagonist",
      backstory: "Once a fearsome rakshasa warrior, cursed by Saint Vardhan during a failed raid. Now whenever he attempts evil, it transforms into good deeds.",
      specialTraits: ["Curse of unintended goodness", "Shape-shifting (limited)", "Super strength (can't use for evil)", "Loves sweets", "Terrified of his own cuteness"]
    },
    {
      name: "Saint Vardhan",
      description: "An ancient sage with immense spiritual power",
      personality: "Wise, patient, sees good in everyone, has a mischievous sense of humor",
      appearance: "Long white beard with flowers in it, saffron robes, peaceful glowing aura, kind twinkling eyes",
      role: "supporting",
      backstory: "The sage who cursed Kutil, but actually sees it as a blessing in disguise. Occasionally appears to offer cryptic advice."
    },
    {
      name: "Maya",
      description: "A clever village girl who befriends Kutil",
      personality: "Intelligent, brave, quick-witted, protective of her friends",
      appearance: "Young girl in simple village clothes, curious eyes, always carries a basket",
      role: "supporting",
      backstory: "First human to see through Kutil's 'evil' act and recognize his kind heart. Acts as his moral compass."
    }
  ],
  "Ramayana Era",
  "Ancient India - Treta Yuga",
  "Lanka and surrounding villages/forests",
  "short",
  "comedy",
  "All ages, especially young adults who enjoy anime-style content",
  "Stylized 3D animation blending Indian miniature painting aesthetics with modern Pixar-style character design. Vibrant colors, expressive characters, detailed environments.",
  "Focus on visual comedy and slapstick. Emphasize the contrast between Kutil's evil intentions and the cute/good outcomes. Use bright, warm color palette."
);

console.log("✅ Context created:", kutilContext.id);
```

### Step 2: List Available Contexts

```typescript
// When you want to select a context later
const contexts = await skill.listContexts();
console.log("Your contexts:");
contexts.forEach((ctx, i) => {
  console.log(`${i + 1}. ${ctx.name} (Created: ${new Date(ctx.createdAt).toLocaleDateString()})`);
});
```

**Output:**
```
Your contexts:
1. Kutil - The Cursed Rakshasa (Created: 2/10/2026)
2. Warriors of Ancient Bharat (Created: 2/8/2026)
```

### Step 3: Generate Story Ideas

```typescript
// Select the context (user picks #1)
const selectedContextId = contexts[0].id;

// Generate ideas for a Diwali-themed story
const ideas = await skill.generateStoryIdeas(
  selectedContextId,
  3,              // Generate 3 ideas
  "Diwali festival"  // Theme
);

// Display ideas to user
ideas.forEach((idea, i) => {
  console.log(`\n${i + 1}. ${idea.title}`);
  console.log(`   ${idea.summary}`);
  console.log(`   Genre: ${idea.genre} | Duration: ~${idea.estimatedDuration}s`);
  console.log(`   Hook: ${idea.hook}`);
});
```

**Example Output:**
```
1. Kutil Tries to Steal the Diwali Sweets
   Kutil plans to raid the village's Diwali sweet preparations, but his curse turns every attempt into helping make the sweets even more delicious.
   Genre: Comedy | Duration: ~60s
   Hook: What happens when a monster tries to ruin Diwali but can only make it better?

2. The Accidental Lantern Hero
   Kutil attempts to blow out all the diyas in the village, but his breath creates magical floating lanterns that save a lost child.
   Genre: Comedy-Drama | Duration: ~75s
   Hook: This Diwali, even darkness brings light!

3. Kutil vs. The Firecracker
   Trying to scare the village with a loud firecracker, Kutil accidentally creates the most spectacular firework display ever seen.
   Genre: Action-Comedy | Duration: ~60s
   Hook: The villain who became the celebration!
```

### Step 4: Create Cinematic Script

```typescript
// User selects idea #1: "Kutil Tries to Steal the Diwali Sweets"
const selectedIdea = ideas[0];

const script = await skill.createCinematicScript(
  selectedContextId,
  selectedIdea.id,
  selectedIdea
);

console.log("🎬 Script created:", script.title);
```

### Step 5: Review the Generated Script

The script will include:

#### Hook Script
```typescript
script.hook = {
  text: "What happens when a monster tries to ruin Diwali but can only make it better?",
  duration: 3,
  visualDescription: "Quick cuts: Kutil sneaking → Kutil accidentally decorating → Confused cute face. Fast-paced, festive music.",
  impact: "Creates immediate curiosity about the comedic premise"
}
```

#### Scenes with Detailed Shots

**Scene 1: The Setup**
```typescript
scene.shots = [
  {
    shotNumber: 1,
    type: "establishing",
    cameraAngle: "high-angle",
    cameraMovement: "static",
    duration: 3,
    description: "Wide shot of Lanka village preparing for Diwali, colorful decorations everywhere",
    impact: "Establishes festive atmosphere and setting",
    imagePrompt: "Epic wide establishing shot of ancient Indian village during Diwali preparations, vibrant colors, rangoli patterns, diyas glowing, traditional architecture, golden hour lighting, highly detailed, 8k, stylized 3D animation with Indian art influences",
    videoPrompt: "Wide establishing shot of ancient village during Diwali, gentle camera drift, hundreds of diyas twinkling, smoke from firecrackers, festive atmosphere, golden hour lighting, atmospheric particles, cinematic, 4k quality"
  },
  {
    shotNumber: 2,
    type: "close-up",
    cameraAngle: "low-angle",
    cameraMovement: "dolly",
    duration: 4,
    description: "Kutil emerging from shadows with 'evil' expression that just looks cute",
    impact: "Character introduction with comedic irony",
    imagePrompt: "Close-up low-angle shot of cute purple rakshasa Kutil with tiny horns and big golden eyes, trying to look evil but looking adorable, dramatic underlighting from diyas, stylized 3D animation, expressive face, purple fluffy fur, cinematic shadows, Indian festival background",
    videoPrompt: "Slow dolly in on Kutil's face, expression changing from trying-to-be-evil to confused, rack focus to colorful Diwali decorations behind, warm lighting, 24fps cinematic"
  }
  // ... more shots
];
```

#### Dialogue Example
```typescript
dialogues: [
  {
    character: "Kutil",
    text: "Tonight, I shall steal ALL the sweets! Muahaha!",
    tone: "determined-evil",
    delivery: "Attempting evil laugh but sounding cute"
  },
  {
    character: "Kutil",
    text: "Wait... why am I arranging them beautifully?",
    tone: "confused",
    delivery: "bewildered, looking at hands",
    isPunchline: true
  }
]
```

#### B-Roll Footage
```typescript
bRoll: [
  {
    timestamp: "0:05",
    description: "Close-up of hands making ladoo",
    purpose: "Show sweet-making process for transitions",
    imagePrompt: "Close-up of hands shaping colorful ladoos, vibrant Indian sweets, detailed textures, warm lighting, Diwali decorations in soft background blur, stylized 3D animation, mouth-watering detail",
    videoPrompt: "Macro shot of ladoo preparation in slow motion, hands shaping sweet, steam rising, warm golden lighting, 60fps"
  }
]
```

#### Sound Design
```typescript
soundDesign: {
  ambient: ["Village festival ambience", "Distant firecrackers", "Temple bells"],
  sfx: [
    { timestamp: "0:08", sound: "Comedic slide whistle", description: "Curse activating", intensity: "moderate" },
    { timestamp: "0:23", sound: "Magical sparkle chime", description: "Sweets transforming", intensity: "subtle" }
  ],
  music: [
    {
      timestamp: "0:00",
      type: "intro",
      genre: "fusion",
      mood: "festive-playful",
      tempo: "upbeat",
      instrumentation: ["tabla", "sitar", "modern beats", "festive bells"]
    }
  ]
}
```

### Step 6: Generate YouTube Metadata

```typescript
const metadata = await skill.generateYouTubeMetadata(script.id);

console.log("📺 YouTube Metadata:");
console.log("Title:", metadata.title);
console.log("Tags:", metadata.tags.join(", "));
console.log("\nDescription:\n", metadata.description);
```

**Output:**
```
📺 YouTube Metadata:

Title: Kutil's Diwali Disaster 😂 | Cute Rakshasa Cursed to Be Good

Tags: animated short, comedy animation, diwali animation, ai animation, funny videos, short film, cinematic, comedy, storytelling, character animation, lanka, indie animation, viral video, entertainment, web series, cartoon, mythology, ramayana, kutil, curse comedy, wholesome, feel good, indian animation, festival special, rakshasa

Description:
🎬 Welcome to an epic tale of Kutil, a lovable rakshasa from ancient Lanka!

When a mischievous curse turns every bad deed into accidental good, chaos and comedy ensue! Watch as Kutil tries to steal Diwali sweets but ends up making them even more delicious!

🎨 Created with love using AI-powered storytelling
📍 Setting: Ancient Lanka during Diwali
⏱️ Duration: ~1 minute
🪔 Happy Diwali!

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎭 CHARACTERS:
• Kutil - Protagonist (The cursed cute rakshasa)
• Saint Vardhan - Supporting
• Maya - Supporting

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎵 MUSIC & SFX:
Traditional Ancient Indian instrumentation meets modern cinematic scoring

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📱 FOLLOW FOR MORE:
New animated shorts every week!

#Diwali #Animation #Comedy #ShortFilm #Kutil

Thumbnail Idea: Epic thumbnail: Kutil holding a ladoo with confused expression, surrounded by magical sparkles and Diwali decorations, bold text "SWEET DISASTER! 🪔", warm orange and gold colors, cute character design, clickbait style but artistic
```

### Step 7: Export Script for Production

```typescript
// Export as different formats

// JSON (for programmatic use)
const jsonScript = await skill.exportScript(script.id, 'json');
await fs.writeFile('kutil-script.json', jsonScript);

// Markdown (for reading)
const mdScript = await skill.exportScript(script.id, 'markdown');
await fs.writeFile('kutil-script.md', mdScript);

// Text (simple)
const textScript = await skill.exportScript(script.id, 'text');
await fs.writeFile('kutil-script.txt', textScript);
```

## 🎨 Camera Angle Examples for Kutil

### Low Angle Shot - Making Kutil Look Heroic
```typescript
const lowAngle = skill.getCameraTechnique('angle', 'low-angle');
// Use when Kutil accidentally does something impressive
// Impact: Power, heroism, dominance
```

### Dutch Angle - Comedic Chaos
```typescript
const dutchAngle = skill.getCameraTechnique('angle', 'dutch-angle');
// Use when curse activates unexpectedly
// Impact: Unease, disorientation, comedy
```

### Extreme Close-up - Emotional Moments
```typescript
const ecu = skill.getCameraTechnique('shot', 'extreme-close-up');
// Use for Kutil's eye twitch when curse activates
// Impact: Intense emotion, comedy
```

## 📋 Full Workflow Summary

```typescript
// Complete workflow in one go
async function createKutilVideo(theme = "Diwali festival") {
  const skill = agent.tools['cinematic-script-writer'];
  
  // 1. Get or create context
  let contexts = await skill.listContexts();
  let context = contexts.find(c => c.name.includes("Kutil"));
  
  if (!context) {
    context = await skill.createContext(/* Kutil details */);
  }
  
  // 2. Generate ideas
  const ideas = await skill.generateStoryIdeas(context.id, 3, theme);
  
  // 3. User selects idea (in real app, show UI)
  const selectedIdea = ideas[0]; // or user selection
  
  // 4. Create script
  const script = await skill.createCinematicScript(
    context.id, 
    selectedIdea.id, 
    selectedIdea
  );
  
  // 5. Get YouTube metadata
  const metadata = await skill.generateYouTubeMetadata(script.id);
  
  return {
    context,
    idea: selectedIdea,
    script,
    metadata
  };
}

// Run it
const videoProject = await createKutilVideo("Diwali festival");
console.log("🎬 Ready to produce:", videoProject.metadata.title);
```

## 🎯 Production Tips

### Image Generation (Midjourney/Stable Diffusion)
- Use the `imagePrompt` fields directly
- Add `--ar 16:9` for video aspect ratio
- Add `--style raw` or `--niji 5` for anime style

### Video Generation (Veo 3/Sora 2)
- Use the `videoPrompt` fields
- Specify camera movements clearly
- Include lighting and atmosphere details

### Editing
- Follow the shot durations for timing
- Use the B-roll for transitions
- Layer sound design as specified

## 📂 File Structure After Creation

```
my-kutil-project/
├── script.json              # Full script data
├── script.md                # Readable markdown
├── prompts/
│   ├── scene1-shots.md      # All image/video prompts for scene 1
│   ├── scene2-shots.md
│   └── b-roll.md
├── audio/
│   ├── music-cues.md
│   └── sfx-list.md
└── youtube/
    ├── title.txt
    ├── description.txt
    └── tags.txt
```

---

🎬 **Happy Creating!** May your Kutil videos bring joy and laughter! 🦞


path: skills/cinematic-script-writer/EXAMPLE-STORAGE.md
content: # 💾 Storage & Google Drive Integration Example

This example shows how to save all your generated content to Google Drive with organized folders.

## Quick Start: Save to Google Drive

### Step 1: Ask Where to Store

```typescript
const skill = agent.tools['cinematic-script-writer'];

// Ask user where to store files
const locationQuestion = await skill.askStorageLocation();
console.log(locationQuestion.question);
// "Where would you like to store your generated files?"
//
// Options:
// 1. 📁 Google Drive - Save to your Google Drive account
// 2. 💻 Local Download - Download files to your computer
// 3. ❓ Ask me later - Decide when saving each time
```

### Step 2: Connect to Google Drive

```typescript
// User selects Google Drive
// Get auth URL
const authResult = await skill.connectGoogleDrive();

if (authResult.needsAuth) {
  console.log(authResult.message);
  // Please authorize access to your Google Drive:
  // https://accounts.google.com/o/oauth2/v2/auth?...
  //
  // After authorization, paste the code here.
  
  // User pastes auth code from Google
  const userAuthCode = '4/0Adeu...'; // User provides this
  
  const connectResult = await skill.connectGoogleDrive(userAuthCode);
  console.log(connectResult.message);
  // ✅ Successfully connected to Google Drive!
}
```

### Step 3: Create Your Story

```typescript
// Create context
const kutilContext = await skill.createContext(
  "Kutil - The Cursed Rakshasa",
  "A lovable rakshasa's misadventures",
  [/* characters */],
  "Ramayana Era",
  "Ancient India - Treta Yuga",
  "Lanka",
  "short",
  "comedy",
  "All ages",
  "Stylized 3D animation"
);

// Setup consistency
const { guides } = await skill.setupContextWithConsistency(
  kutilContext,
  { /* character visuals */ }
);

// Generate story
const ideas = await skill.generateStoryIdeas(kutilContext.id, 3);
const script = await skill.createCinematicScript(
  kutilContext.id,
  ideas[0].id,
  ideas[0]
);

// Generate metadata
const metadata = await skill.generateYouTubeMetadata(script.id);
```

### Step 4: Save Everything to Google Drive

```typescript
// Save all content to Google Drive
const saveResult = await skill.saveScriptToStorage(
  "Kutil's Diwali Disaster",  // Folder name (title)
  kutilContext.id,            // Context ID
  script.id,                  // Script ID
  {
    includeScript: true,      // Save 01_SCRIPT.json
    includePrompts: true,     // Save 02_PROMPTS.json
    includeConsistency: true, // Save 03_CONSISTENCY.json
    includeVoice: true,       // Save 04_VOICE_PROFILES.json
    includeMetadata: true     // Save 05_YOUTUBE_METADATA.json
  }
);

console.log(saveResult);
// {
//   success: true,
//   folder: {
//     id: [REDACTED_SECRET],
//     name: "Kutil's Diwali Disaster",
//     path: "/Kutil's Diwali Disaster",
//     webViewLink: "https://drive.google.com/drive/folders/..."
//   },
//   files: [
//     { name: "00_INDEX.md", type: "master", ... },
//     { name: "01_SCRIPT.json", type: "script", ... },
//     { name: "01_SCRIPT_README.md", type: "script", ... },
//     { name: "02_PROMPTS.json", type: "prompts", ... },
//     { name: "02_IMAGE_PROMPTS.md", type: "prompts", ... },
//     { name: "03_CONSISTENCY.json", type: "consistency", ... },
//     { name: "03_CHARACTER_REFERENCES.md", type: "consistency", ... },
//     { name: "03_ENVIRONMENT_GUIDE.md", type: "consistency", ... },
//     { name: "04_VOICE_PROFILES.json", type: "voice", ... },
//     { name: "04_VOICE_GUIDELINES.md", type: "voice", ... },
//     { name: "05_YOUTUBE_METADATA.json", type: "metadata", ... },
//     { name: "05_YOUTUBE_METADATA.md", type: "metadata", ... },
//     { name: "99_CONTEXT_INFO.md", type: "master", ... }
//   ],
//   shareLink: "https://drive.google.com/drive/folders/...",
//   errors: []
// }
```

## 📁 Generated Folder Structure

When you save, it creates this organized folder:

```
📁 Kutil's Diwali Disaster (Google Drive Folder)
│
├── 📄 00_INDEX.md                    ← Start here! Overview of all files
│
├── 📄 01_SCRIPT.json                 ← Full script data (JSON)
├── 📄 01_SCRIPT_README.md            ← Human-readable script
│
├── 📄 02_PROMPTS.json                ← All prompts data
├── 📄 02_IMAGE_PROMPTS.md            ← Copy-paste prompts for Midjourney/SD
│
├── 📄 03_CONSISTENCY.json            ← Consistency data
├── 📄 03_CHARACTER_REFERENCES.md     ← Character design guides
├── 📄 03_ENVIRONMENT_GUIDE.md        ← Era/style guides
│
├── 📄 04_VOICE_PROFILES.json         ← Voice data
├── 📄 04_VOICE_GUIDELINES.md         ← Dialogue writing guide
│
├── 📄 05_YOUTUBE_METADATA.json       ← YouTube data
├── 📄 05_YOUTUBE_METADATA.md         ← Title/description/tags
│
└── 📄 99_CONTEXT_INFO.md             ← Story background
```

## 📄 What's in Each File?

### 00_INDEX.md
Navigation hub showing all files and their purposes.

```markdown
# Kutil's Diwali Disaster

Generated by Cinematic Script Writer
Date: 2/10/2026, 10:30:15 AM

## 📁 Contents

| File | Description |
|------|-------------|
| 00_INDEX.md | This file - overview of all content |
| 01_SCRIPT.json | Full script data (JSON) |
| 01_SCRIPT_README.md | Human-readable script |
| 02_PROMPTS.json | All prompts data (JSON) |
| 02_IMAGE_PROMPTS.md | Copy-paste image prompts |
| 03_CONSISTENCY.json | Consistency data (JSON) |
| 03_CHARACTER_REFERENCES.md | Character design references |
| 03_ENVIRONMENT_GUIDE.md | Era/style environment guide |
| 04_VOICE_PROFILES.json | Voice data (JSON) |
| 04_VOICE_GUIDELINES.md | Voice/dialogue guidelines |
| 05_YOUTUBE_METADATA.json | YouTube metadata (JSON) |
| 05_YOUTUBE_METADATA.md | YouTube title/description/tags |
| 99_CONTEXT_INFO.md | Story context and background |

## 🎬 Quick Start

1. **Script**: Read `01_SCRIPT_README.md` for the full story
2. **Images**: Copy prompts from `02_IMAGE_PROMPTS.md` to Midjourney/Stable Diffusion
3. **Consistency**: Check `03_CHARACTER_REFERENCES.md` to keep characters consistent
4. **Voice**: Use `04_VOICE_GUIDELINES.md` for dialogue writing
5. **YouTube**: Use `05_YOUTUBE_METADATA.md` for upload
```

### 01_SCRIPT_README.md
Human-readable script with all scenes, shots, and dialogue.

```markdown
# Kutil's Diwali Disaster

## 🪝 Hook

What happens when a monster tries to ruin Diwali but can only make it better?

**Duration:** 3s

---

## 🎬 Scene 1: The Setup

**Duration:** 15s | **Location:** Lanka marketplace

### Synopsis
Introduce protagonist and the curse dynamics

### 📷 Shots

**Shot 1** - establishing | high-angle | 3s

Description: Wide shot of Lanka, establishing the setting

**Image Prompt:**
```
Epic wide establishing shot of ancient Lanka marketplace during Diwali preparations, 
vibrant colors, rangoli patterns, diyas glowing, traditional architecture, 
golden hour lighting, highly detailed, 8k, stylized 3D animation with Indian art influences
```

**Video Prompt:**
```
Wide establishing shot of ancient marketplace during Diwali, gentle camera drift, 
hundreds of diyas twinkling, smoke from firecrackers, festive atmosphere, 
golden hour lighting, atmospheric particles, cinematic, 4k quality
```

### 💬 Dialogue

**Kutil:** Today, I shall steal ALL the sweets! Muahaha!
*(determined-evil, confident, evil laugh)*

**Kutil:** Wait... why am I arranging them beautifully?
*(confused, bewildered, high pitch)* 💥
```

### 02_IMAGE_PROMPTS.md
Ready-to-copy prompts for AI image generation.

```markdown
# Image & Video Generation Prompts

Copy these prompts into your AI image/video generation tool:

---

## Shot 1: establishing - Wide shot of Lanka marketplace...

### Image Prompt (Midjourney/Stable Diffusion)
```
close-up shot, low-angle camera angle, Kutil is a small cute rakshasa with 
fluffy purple fur covering entire body, two small curved horns on head cream 
colored tips, large round golden eyes with black pupils, wearing simple 
traditional cotton dhoti, Ramayana Era setting, Lanka marketplace, stone 
temple architecture, golden-hour lighting, mischievous mood, pixar-3d style, 
consistent character design, same character across frames, highly detailed, 8k
```

### Video Prompt (Veo/Sora/Runway)
```
close-up shot, static camera movement, low-angle angle, Kutil: small cute 
rakshasa with purple fur, trying to look evil but looking cute, Ramayana Era 
setting, golden-hour lighting, mischievous atmosphere, smooth motion, 
24fps cinematic, high quality
```

### Negative Prompt
```
inconsistent character design, different character in each frame, changing 
features, wrong eye color, wrong hair color, modern clothing, glasses, 
watches, plastic, synthetic fabrics, blurry, low quality, deformed
```

---
```

### 03_CHARACTER_REFERENCES.md
Visual reference guides for consistency.

```markdown
# Character Reference Sheets

Use these references to keep characters consistent across all images:

---

# Kutil

## Visual Description
Kutil is a small cute rakshasa (mythical being) with:
- Fluffy purple fur covering entire body
- Two small curved horns on head (cream colored tips)
- Large round golden eyes with black pupils
- Small fangs visible when smiling
- Pointed ears with pink insides
- Short tail with purple fur
- About 3 feet tall, chibi proportions

## Color Palette
- **Signature:** purple, golden
- **Primary:** purple, cream
- **Hair:** purple
- **Eyes:** golden

## Default Outfit
Simple traditional cotton dhoti in earthy colors

## Consistency Keywords
Always include these in prompts:
- consistent character design
- same character across frames
- character continuity

## Negative Prompts
Always exclude these:
- modern clothing
- anachronistic elements
- inconsistent features
```

### 04_VOICE_GUIDELINES.md
Voice profiles for consistent dialogue.

```markdown
# Voice Guidelines

Use these guidelines for consistent character dialogue:

---

# Kutil

## Speech Characteristics
- **Pitch:** high
- **Speed:** fast
- **Volume:** normal
- **Clarity:** clear

## Language
- **Vocabulary:** simple
- **Formality:** casual

## Catchphrases
- "I am evil!"
- "Curse you, Saint Vardhan!"
- "Muahaha!"

## Speech Examples
- **Greeting:** "Tremble before me!"
- **Question:** "What do you mean I'm helping?"
- **Exclamation:** "No, not again!"
```

### 05_YOUTUBE_METADATA.md
Ready-to-use YouTube upload info.

```markdown
# YouTube Metadata

## Title

Kutil's Diwali Disaster 😂 | Cute Rakshasa Cursed to Be Good

## Description

🎬 Welcome to an epic tale of Kutil, a lovable rakshasa from ancient Lanka!

When a mischievous curse turns every bad deed into accidental good, 
chaos and comedy ensue! Watch as Kutil tries to steal Diwali sweets 
but ends up making them even more delicious!

🎨 Created with love using AI-powered storytelling
📍 Setting: Ancient Lanka during Diwali
⏱️ Duration: ~1 minute
🪔 Happy Diwali!

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎭 CHARACTERS:
• Kutil - Protagonist (The cursed cute rakshasa)
• Saint Vardhan - Supporting
• Maya - Supporting

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🎵 MUSIC & SFX:
Traditional Ancient Indian instrumentation meets modern cinematic scoring

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📱 FOLLOW FOR MORE:
New animated shorts every week!

#Diwali #Animation #Comedy #ShortFilm #Kutil

## Tags

animated short, comedy animation, diwali animation, ai animation, 
funny videos, short film, cinematic, comedy, storytelling, 
character animation, lanka, indie animation, viral video, 
entertainment, web series, cartoon, mythology, ramayana, 
kutil, curse comedy, wholesome, feel good

## Category

Film & Animation

## Thumbnail Idea

Epic thumbnail: Kutil holding a ladoo with confused expression, 
surrounded by magical sparkles and Diwali decorations, 
bold text "SWEET DISASTER! 🪔", warm orange and gold colors
```

## Complete Workflow Example

```typescript
async function createAndSaveStory() {
  const skill = agent.tools['cinematic-script-writer'];
  
  // 1. Connect to Google Drive (first time only)
  const status = await skill.getStorageStatus();
  if (!status.connected) {
    const auth = await skill.connectGoogleDrive();
    if (auth.needsAuth) {
      console.log("Please visit this URL and paste the code:");
      console.log(auth.authUrl);
      // User visits URL, authorizes, gets code
      const userCode = await askUserForCode(); // Get from user
      await skill.connectGoogleDrive(userCode);
    }
  }
  
  // 2. Create context
  const context = await skill.createContext(
    "Kutil's Adventure",
    "Diwali comedy story",
    [/* characters */],
    "Ramayana Era",
    "Treta Yuga",
    "Lanka",
    "short",
    "comedy",
    "All ages",
    "Pixar 3D style"
  );
  
  // 3. Setup consistency
  await skill.setupContextWithConsistency(context, {
    [context.characters[0].id]: "Purple fur, small horns, golden eyes..."
  });
  
  // 4. Generate story
  const ideas = await skill.generateStoryIdeas(context.id, 3);
  const selectedIdea = ideas[0];
  
  // 5. Create script
  const script = await skill.createCinematicScript(
    context.id,
    selectedIdea.id,
    selectedIdea
  );
  
  // 6. Generate metadata
  const metadata = await skill.generateYouTubeMetadata(script.id);
  
  // 7. Save everything to Google Drive!
  const saveResult = await skill.saveScriptToStorage(
    selectedIdea.title,  // Uses story title as folder name
    context.id,
    script.id,
    {
      includeScript: true,
      includePrompts: true,
      includeConsistency: true,
      includeVoice: true,
      includeMetadata: true
    }
  );
  
  if (saveResult.success) {
    console.log("✅ Saved to Google Drive!");
    console.log("Folder:", saveResult.folder.name);
    console.log("Link:", saveResult.shareLink);
    console.log("Files:", saveResult.files.map(f => f.name).join(', '));
  } else {
    console.error("Save failed:", saveResult.errors);
  }
  
  return saveResult;
}
```

## Local Storage (Download)

If user doesn't want Google Drive:

```typescript
// Connect to local storage
await skill.connectLocalStorage();

// Save will download files
const result = await skill.saveScriptToStorage(
  "Kutil's Story",
  context.id,
  script.id
);
// Files will download to browser/computer
```

## Check Storage Status

```typescript
const status = await skill.getStorageStatus();
console.log(status);
// {
//   connected: true,
//   provider: 'google-drive'
// }
```

## Disconnect

```typescript
await skill.disconnectStorage();
console.log("Disconnected from storage");
```

## Tips

1. **First Time Setup**: Only need to connect Google Drive once
2. **Folder Names**: Uses your story title as the folder name
3. **Re-save**: Can re-save to update files
4. **Share**: Use `shareLink` to share folder with collaborators
5. **Backup**: Everything is saved - script, prompts, consistency guides, metadata

## File Summary

| File | When to Use |
|------|-------------|
| `00_INDEX.md` | Start here - see what's available |
| `01_SCRIPT_README.md` | Read the full story |
| `02_IMAGE_PROMPTS.md` | Copy prompts to Midjourney/Stable Diffusion |
| `03_CHARACTER_REFERENCES.md` | Check when generating character images |
| `04_VOICE_GUIDELINES.md` | Use when writing dialogue |
| `05_YOUTUBE_METADATA.md` | Copy when uploading to YouTube |

All files are organized in a Google Drive folder named after your story title! 🎬


path: skills/cinematic-script-writer/package.json
content: {
  "name": "cinematic-script-writer",
  "version": "1.4.2",
  "description": "Professional cinematic script generation with consistency, cinematography, and storage",
  "type": "module",
  "main": "index.ts",
  "keywords": [
    "openclaw",
    "skill",
    "cinematography",
    "script",
    "video",
    "consistency",
    "google-drive"
  ],
  "author": "Praveen Kumar",
  "license": "MIT",
  "dependencies": {
    "uuid": "^9.0.0"
  },
  "engines": {
    "node": ">=18.0.0"
  }
}


path: skills/cinematic-script-writer/schema.json
content: {
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "llmProvider": {
      "type": "string",
      "enum": ["openai", "anthropic", "local"],
      "default": "anthropic",
      "description": "LLM provider for generating scripts"
    },
    "apiKey": {
      "type": "string",
      "description": "API key for LLM provider"
    },
    "model": {
      "type": "string",
      "description": "Model name (e.g., claude-3-opus, gpt-4)",
      "default": "claude-3-opus"
    },
    "defaultVideoDuration": {
      "type": "number",
      "description": "Default video duration in seconds",
      "default": 60
    },
    "cameraStyle": {
      "type": "string",
      "enum": ["cinematic", "documentary", "anime", "comic-book", "minimalist"],
      "default": "cinematic",
      "description": "Default visual style for camera work"
    }
  },
  "required": []
}


path: tsconfig.json
content: {
  "compilerOptions": {
    "target": "ES2022",
    "module": "CommonJS",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": ".",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": [
    "**/index.ts",
    "bin/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "dist",
    "**/*.test.ts"
  ]
}


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)