view --main connector-ops-skill-dlya-upravleniya-i-sozdaniya-konnektorov.md
connector-ops: Скилл для управления и создания коннекторов
readonly
--- lines
---
name: connector-ops
description: >
Manage Unstract connectors - add, remove, or modify database, filesystem, and queue connectors.
This skill handles backend code, JSON schemas, tests, logo fetching, and dependency management.
Use when the user wants to create a new connector, delete an existing one, or modify connector behavior.
---
# Connector Operations Skill
Manage Unstract connectors with full lifecycle support: add, remove, and modify operations for database, filesystem, and queue connector types.
## When to Use This Skill
- User requests adding a new connector (e.g., "add a Redis connector", "create MongoDB database connector")
- User requests removing a connector (e.g., "remove the Oracle connector", "delete Box filesystem")
- User requests modifying a connector (e.g., "add SSL support to MySQL", "update BigQuery schema")
## Architecture Overview
Connectors live in `/unstract/connectors/src/unstract/connectors/` with three categories:
| Type | Base Class | Directory | Mode |
|------|------------|-----------|------|
| Database | `UnstractDB` | `databases/` | `ConnectorMode.DATABASE` |
| Filesystem | `UnstractFileSystem` | `filesystems/` | `ConnectorMode.FILE_SYSTEM` |
| Queue | `UnstractQueue` | `queues/` | `ConnectorMode.MANUAL_REVIEW` |
### Connector Structure
Each connector follows this structure:
```
connector_name/
├── __init__.py # Metadata dict with is_active flag
├── connector_name.py # Main connector class
├── constants.py # Optional constants
└── static/
├── json_schema.json # Configuration UI schema
└── settings.yaml # Optional settings
```
### Key Files
| File | Purpose |
|------|---------|
| `base.py` | Root `UnstractConnector` abstract class |
| `connectorkit.py` | Singleton registry for all connectors |
| `databases/unstract_db.py` | Database connector base class |
| `filesystems/unstract_file_system.py` | Filesystem connector base class |
| `queues/unstract_queue.py` | Queue connector base class |
| `databases/register.py` | Auto-discovery for database connectors |
| `filesystems/register.py` | Auto-discovery for filesystem connectors |
---
## Operation: ADD Connector
### Step 1: Gather Requirements
Ask the user for:
1. **Connector name** (e.g., "Redis", "MongoDB", "Wasabi")
2. **Connector type** (database, filesystem, or queue)
3. **Brief description** of use case
### Step 2: Research the Service
Use web search to discover:
1. **Official Python library** for the service
2. **Existing fsspec provider** — check if a mature fsspec-compatible library exists (e.g., `s3fs` for S3, `adlfs` for Azure, `gcsfs` for GCS, `boxfs` for Box). **Always prefer wrapping an existing provider over building a custom one.**
3. **All supported authentication modes** (API key, OAuth, connection string, certificates, etc.)
4. **Required connection parameters** for each auth mode
5. **Official logo/icon** source
Document findings before proceeding. If no fsspec provider exists, note that a custom `AbstractFileSystem` subclass will be needed (see Step 5b).
### Step 3: Generate Connector ID
Create a unique connector ID using this pattern:
```python
f"{short_name}|{uuid4()}"
# Example: "redis|a1b2c3d4-e5f6-7890-abcd-ef1234567890"
```
### Step 4: Create Directory Structure
```bash
# For database connector
mkdir -p unstract/connectors/src/unstract/connectors/databases/{connector_name}/static
# For filesystem connector
mkdir -p unstract/connectors/src/unstract/connectors/filesystems/{connector_name}/static
# For queue connector
mkdir -p unstract/connectors/src/unstract/connectors/queues/{connector_name}/static
```
### Step 5: Create Connector Files
#### 5a. Create `__init__.py`
```python
from .{connector_name} import {ClassName}
metadata = {
"name": {ClassName}.__name__,
"version": "1.0.0",
"connector": {ClassName},
"description": "{Description of the connector}",
"is_active": True,
}
```
#### 5b. Create Main Connector Class
Use the appropriate template from `assets/templates/`:
- `database.py.template` for database connectors
- `filesystem.py.template` for filesystem connectors
- `queue.py.template` for queue connectors
Read the template and adapt it for the specific service. Key methods to implement:
**For Database Connectors:**
- `get_engine()` → Return database connection
- `sql_to_db_mapping()` → Map Python types to DB types
- `execute()` → Execute queries (inherited, may override)
**For Filesystem Connectors:**
There are two approaches depending on whether an fsspec provider exists:
**Approach 1: Wrapping an existing fsspec provider (PREFERRED)**
When a library like `s3fs`, `adlfs`, `gcsfs`, `boxfs` exists, the connector only extends `UnstractFileSystem`:
- `get_fsspec_fs()` → Return the provider's filesystem instance (e.g., `S3FileSystem(...)`)
- `test_credentials()` → Verify connection works
- `extract_metadata_file_hash()` → Extract file hash from metadata
- `is_dir_by_metadata()` → Check if path is directory
- `extract_modified_date()` → Extract last modified date
- **Do NOT implement `ls`, `walk`, `info`, etc.** — the provider handles all file operations.
- See `minio.py` for reference.
**Approach 2: Custom AbstractFileSystem (ONLY when no provider exists)**
Create a custom `AbstractFileSystem` subclass with ONLY these core methods:
- `ls(path, detail=True)` — List directory contents (REQUIRED)
- `info(path)` — Get single item metadata (optimization, optional)
- `_open(path, mode)` — Open a file for reading
- `cat_file(path)` — Read file contents
- `pipe_file(path, value)` — Write bytes (NOT `write_bytes` — that's an alias)
- `rm(path)` — Delete a file
- `mkdir(path)` — Create directory
**CRITICAL: NEVER override** `listdir()`, `stat()`, `exists()`, `isdir()`, `isfile()`, `delete()`, `read_bytes()`, or `write_bytes()`. These are provided by `AbstractFileSystem` and delegate to `ls()`/`info()`/`pipe_file()`.
**`walk()` exception**: Override `walk()` ONLY if the filesystem has path normalization that differs from `_strip_protocol` (e.g., SharePoint maps `""` to `"root"`), or if the service raises exceptions that aren't `FileNotFoundError`/`OSError` (the only types the base catches). If you override `walk()`, you MUST support the `detail` kwarg (return dicts when `True`, lists when `False`) and the `on_error` callback.
- See `sharepoint.py` for reference.
**For Queue Connectors:**
- `get_engine()` → Return queue connection
- `enqueue()` → Add message to queue
- `dequeue()` → Get message from queue
- `peek()` → View next message without removing
#### 5c. Create JSON Schema
Generate `static/json_schema.json` based on researched auth modes:
```json
{
"title": "{Connector Display Name}",
"type": "object",
"allOf": [
{
"required": ["connectorName"],
"properties": {
"connectorName": {
"type": "string",
"title": "Name of the connector"
}
}
},
{
"oneOf": [
// Add each auth mode as a separate option
]
}
]
}
```
Use `"format": "password"` for sensitive fields.
### Step 6: Fetch Logo
Execute the logo fetch script:
```bash
python .claude/skills/connector-ops/scripts/fetch_logo.py "{service_name}" "{output_path}"
```
The script tries these sources in order:
1. **SimpleIcons** (simpleicons.org)
2. **Devicon** (devicon.dev)
3. **Logo.dev API**
4. **Web search** for official logo
5. **Skip** if not found (log warning)
Place logo at: `/frontend/public/icons/connector-icons/{ConnectorName}.png`
### Step 7: Add Dependencies
Research required Python packages and add to `pyproject.toml`:
```bash
# Read current dependencies
cat unstract/connectors/pyproject.toml
# Add new dependency in the [project.dependencies] section
# Follow existing version pinning patterns (e.g., ~=, ==, >=)
```
### Step 8: Create Tests
Generate both mock-based and integration tests in `unstract/connectors/tests/`:
#### Mock-based Test (always runnable):
```python
import unittest
from unittest.mock import patch, Mock
class Test{ClassName}(unittest.TestCase):
def setUp(self):
self.config = {
# Test configuration
}
@patch("{module_path}.{connection_method}")
def test_connection_params(self, mock_connect):
mock_connect.return_value = Mock()
connector = {ClassName}(self.config)
# Assertions
```
#### Integration Test (requires real service):
```python
import os
import unittest
class Test{ClassName}Integration(unittest.TestCase):
@unittest.skipUnless(
os.getenv("{CONNECTOR}_HOST"),
"Integration test requires {CONNECTOR}_* environment variables"
)
def test_real_connection(self):
config = {
"host": os.getenv("{CONNECTOR}_HOST"),
# ... other env vars
}
connector = {ClassName}(config)
self.assertTrue(connector.test_credentials())
```
### Step 9: Verify
Run verification in order:
```bash
# 1. Syntax/type check
cd unstract/connectors && python -m py_compile src/unstract/connectors/{type}/{name}/{name}.py
# 2. Run mock tests
cd unstract/connectors && python -m pytest tests/{type}/test_{name}.py -v
# 3. Run full connector test suite
cd unstract/connectors && python -m pytest tests/ -v --ignore=tests/{type}/test_{name}_integration.py
```
### Step 10: Report to User
Provide summary:
```
## Connector Added: {Name}
**Files created:**
- `src/unstract/connectors/{type}/{name}/__init__.py`
- `src/unstract/connectors/{type}/{name}/{name}.py`
- `src/unstract/connectors/{type}/{name}/static/json_schema.json`
- `tests/{type}/test_{name}.py`
- `tests/{type}/test_{name}_integration.py`
- `frontend/public/icons/connector-icons/{Name}.png`
**Dependencies added:**
- `{package}~={version}`
**Verification:**
- Syntax check: PASSED
- Mock tests: PASSED (X tests)
- Test suite: PASSED
**To run integration tests:**
```bash
export {CONNECTOR}_HOST=your_host
export {CONNECTOR}_USER=your_user
export {CONNECTOR}_PASSWORD=your_password
cd unstract/connectors && python -m pytest tests/{type}/test_{name}_integration.py -v
```
```
---
## Operation: REMOVE Connector
### Step 1: Identify Connector
Locate the connector by name or ID:
```bash
# Search for connector
grep -r "class {Name}" unstract/connectors/src/
```
### Step 2: Check Dependencies
Search for usages across the codebase:
```bash
grep -r "{connector_id}" --include="*.py" .
grep -r "from.*{connector_name}" --include="*.py" .
```
Warn user if connector is referenced elsewhere.
### Step 3: Remove Files
```bash
# Remove connector directory
rm -rf unstract/connectors/src/unstract/connectors/{type}/{name}/
# Remove tests
rm -f unstract/connectors/tests/{type}/test_{name}*.py
# Remove icon
rm -f frontend/public/icons/connector-icons/{Name}.png
```
### Step 4: Clean Dependencies (Optional)
If the removed connector was the only user of a dependency, offer to remove it from `pyproject.toml`.
### Step 5: Verify
```bash
# Ensure no import errors
cd unstract/connectors && python -c "from unstract.connectors.connectorkit import Connectorkit; Connectorkit()"
# Run test suite
cd unstract/connectors && python -m pytest tests/ -v
```
### Step 6: Report to User
```
## Connector Removed: {Name}
**Files deleted:**
- `src/unstract/connectors/{type}/{name}/` (directory)
- `tests/{type}/test_{name}.py`
- `tests/{type}/test_{name}_integration.py`
- `frontend/public/icons/connector-icons/{Name}.png`
**Verification:**
- Import check: PASSED
- Test suite: PASSED
```
---
## Operation: MODIFY Connector
### Step 1: Understand the Change
Ask user what modification is needed:
- Add new configuration field?
- Add new authentication mode?
- Fix a bug?
- Update dependency version?
- Change behavior?
### Step 2: Locate Files
```bash
# Find connector files
find unstract/connectors -name "*{connector_name}*" -type f
```
### Step 3: Make Changes
Based on modification type:
**Adding configuration field:**
1. Update `static/json_schema.json` with new field
2. Update connector class `__init__` to read new field
3. Update usage of field in connector methods
4. Update tests to cover new field
**Adding authentication mode:**
1. Research new auth mode parameters
2. Add new `oneOf` option in JSON schema
3. Update connector class to handle new auth
4. Add tests for new auth mode
**Note**: For connectors that support both OAuth and Client Credentials (like SharePoint/OneDrive), use the **Dual Authentication pattern** documented in `references/connector_patterns.md`. This pattern uses an `auth_type` field with JSON Schema `dependencies` to conditionally show/hide credential fields based on the selected authentication method.
**Bug fix:**
1. Identify root cause
2. Implement fix
3. Add regression test
**Dependency update:**
1. Update version in `pyproject.toml`
2. Check for breaking changes
3. Update connector code if needed
4. Run tests to verify
### Step 4: Update Tests
Ensure tests cover the modification:
- Add new test cases for new functionality
- Update existing tests if behavior changed
- Run full test suite
### Step 5: Verify
```bash
# Type check modified files
cd unstract/connectors && python -m py_compile src/unstract/connectors/{type}/{name}/{name}.py
# Run connector tests
cd unstract/connectors && python -m pytest tests/{type}/test_{name}*.py -v
# Run full suite
cd unstract/connectors && python -m pytest tests/ -v
```
### Step 6: Report to User
```
## Connector Modified: {Name}
**Changes:**
- {Description of each change}
**Files modified:**
- {List of modified files}
**Tests:**
- Added: {count} new test(s)
- Modified: {count} existing test(s)
**Verification:**
- Syntax check: PASSED
- Connector tests: PASSED
- Full suite: PASSED
```
---
## Reference Materials
Consult these files for detailed patterns:
- `references/connector_patterns.md` - Common patterns and anti-patterns
- `references/json_schema_examples.md` - JSON schema examples for all auth types
- `references/test_patterns.md` - Test patterns and fixtures
## Asset Templates
Use these templates as starting points:
- `assets/templates/database.py.template`
- `assets/templates/filesystem.py.template`
- `assets/templates/queue.py.template`
- `assets/templates/init.py.template`
- `assets/templates/json_schema_template.json`
- `assets/templates/test_mock.py.template`
- `assets/templates/test_integration.py.template`
---
## Important Notes
1. **Fork Safety**: For connectors using Google APIs or gRPC, implement lazy loading to prevent SIGSEGV in Celery workers. See Google Drive connector for pattern.
2. **UUID Consistency**: Once a connector ID is assigned, never change it. Existing installations may reference it.
3. **Schema Backwards Compatibility**: When modifying schemas, ensure existing configurations remain valid.
4. **Icon Naming**: Use PascalCase with spaces URL-encoded (e.g., `Google%20Drive.png`).
5. **Test Isolation**: Mock tests should never require external services. Use `@unittest.skipUnless` for integration tests.
6. **fsspec Delegation**: NEVER override `walk()`, `listdir()`, `stat()`, `exists()`, `isdir()`, `isfile()`, `delete()`, `read_bytes()`, or `write_bytes()` in custom `AbstractFileSystem` subclasses. These are provided by fsspec's base class and delegate to `ls()`/`info()`/`pipe_file()`. Overriding them creates maintenance burden and introduces subtle bugs. See `references/connector_patterns.md` for the "Anti-Pattern: Reimplementing fsspec Base Methods" section.
7. **pipe_file vs write_bytes**: When implementing file writes in a custom `AbstractFileSystem`, override `pipe_file()` (not `write_bytes()`). The base `write_bytes()` is an alias that delegates to `pipe_file()`.
Инициализация мануала...
//
$ ls -R related_skills/
2026-04-09
⭐ 6807
hatchet-cli: Скилл для управления и отладки
2026-03-29
⭐ 3556
System Prompts And Models Of Ai Tools — Централизованное хранилище и резервное копирование AI-моделей
2026-03-29
⭐ 3556
ai-system-maintenance — Автоматизированное резервное копирование и архивация ИИ
2026-03-30
⭐ 3588
ntm-memory-system — Хранилище и управление версиями навыков NTM
package.json
$ install --global
skills.sh
npx skills add https://github.com/Zipstack/unstract/tree/main/.claude/skills/connector-ops
$ download --local
man
[HINT] Скачивает всю директорию скилла с GitHub: SKILL.md и все связанные файлы