GCAP-SPEC-CONNECTOR-DESCRIPTOR-0001 implementation.
ConnectorPlugin — abstract base for governed connectors.
ConnectorRegistry — register/discover connectors.
ConnectorRuntime — wraps invoke with Chronicle lineage.
EchoConnector — dev/test example.
API endpoints:
GET /connectors/ — browse catalogue
GET /connectors/{id}/ — connector descriptor
POST /connectors/{id}/invoke/ — governed invocation
GET /connectors/{id}/health/ — health check
5 tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
"""ConnectorRuntime — governed invocation with Chronicle emission."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from .base import ConnectorContext, ConnectorResult
|
|
from .registry import ConnectorRegistry
|
|
|
|
|
|
class ConnectorRuntime:
|
|
def __init__(
|
|
self, registry: ConnectorRegistry, chronicle_client: Any = None
|
|
) -> None:
|
|
self.registry = registry
|
|
self.chronicle_client = chronicle_client
|
|
|
|
async def invoke(
|
|
self,
|
|
connector_id: str,
|
|
operation: str,
|
|
parameters: dict[str, Any],
|
|
context: ConnectorContext,
|
|
) -> ConnectorResult:
|
|
connector = self.registry.get(connector_id)
|
|
if connector is None:
|
|
return ConnectorResult(success=False, error=f"Unknown connector: {connector_id}")
|
|
|
|
if connector.gsap_required and not context.gsap_context_id:
|
|
return ConnectorResult(success=False, error="GSAP context required but not provided")
|
|
|
|
result = await connector.invoke(operation, parameters, context)
|
|
|
|
# Emit Chronicle event
|
|
if connector.chronicle_enabled and self.chronicle_client is not None:
|
|
try:
|
|
cid = await self.chronicle_client.emit(
|
|
"CONNECTOR_INVOKED",
|
|
{
|
|
"connector_id": connector_id,
|
|
"operation": operation,
|
|
"parameters_cid": connector.compute_parameters_cid(parameters),
|
|
"chronicle_session_id": context.chronicle_session_id,
|
|
"gsap_context_id": context.gsap_context_id,
|
|
"pipeline_run_id": context.pipeline_run_id,
|
|
"dag_id": context.dag_id,
|
|
"success": result.success,
|
|
},
|
|
)
|
|
result.lineage_cid = cid
|
|
except Exception:
|
|
pass # Chronicle failure must not break invocation
|
|
|
|
return result
|