Repository: Significant-Gravitas/Auto-GPT
File: autogpt_platform/backend/backend/data/graph.py (Python)

Code before:
    def __hash__(self):
        return hash((self.source_id, self.sink_id, self.source_name, self.sink_name))


class Node(BaseDbModel):
    block_id: str
    input_default: BlockInput = {}  # dict[input_name, default_value]
    metadata: dict[str, Any] = {}
    input_links: list[Link] = []
    output_links: list[Link] = []

    webhook_id: Optional[str] = None


class NodeModel(Node):
    graph_id: str
    graph_version: int

    webhook: Optional[Webhook] = None

    @staticmethod
    def from_db(node: AgentNode):
        if not node.AgentBlock:
            raise ValueError(f"Invalid node {node.id}, invalid AgentBlock.")

        NodeModel.migrate_llm_models(node)

        obj = NodeModel(
            id=node.id,
            block_id=node.AgentBlock.id,
            input_default=json.loads(node.constantInput, target_type=dict[str, Any]),
            metadata=json.loads(node.metadata, target_type=dict[str, Any]),
            graph_id=node.agentGraphId,
            graph_version=node.agentGraphVersion,
            webhook_id=node.webhookId,
            webhook=Webhook.from_db(node.Webhook) if node.Webhook else None,
        )
        obj.input_links = [Link.from_db(link) for link in node.Input or []]
        obj.output_links = [Link.from_db(link) for link in node.Output or []]
        return obj

    @staticmethod
    def migrate_llm_models(node: AgentNode):
        if not node.AgentBlock:
            return

        migrated = False
        data = json.loads(node.constantInput, target_type=dict[str, Any])
        for name, field in node.AgentBlock.model_fields.items():
            # Skip non-llm fields
            if not field.annotation == LlmModel:

Review comment (security):
What if we do that here autogpt_platform/backend/backend/server/rest_api.py
```python
@contextlib.asynccontextmanager
async def lifespan_context(app: fastapi.FastAPI):
    await backend.data.db.connect()
    await backend.data.block.initialize_blocks()
    await backend.data.user.migrate_and_encrypt_user_integrations()
    await backend.data.graph.fix_llm_provider_credentials()
    with launch_darkly_context():
        yield
    await backend.data.db.disconnect()
```


Code after:
            sink_name=link.sinkName,
            sink_id=link.agentNodeSinkId,
            is_static=link.isStatic,
        )

    def __hash__(self):
        return hash((self.source_id, self.sink_id, self.source_name, self.sink_name))


class Node(BaseDbModel):
    block_id: str
    input_default: BlockInput = {}  # dict[input_name, default_value]
    metadata: dict[str, Any] = {}
    input_links: list[Link] = []
    output_links: list[Link] = []

    webhook_id: Optional[str] = None


class NodeModel(Node):
    graph_id: str
    graph_version: int

    webhook: Optional[Webhook] = None

    @property
    def block(self) -> Block[BlockSchema, BlockSchema]:
        block = get_block(self.block_id)
        if not block:
            raise ValueError(f"Block #{self.block_id} does not exist")
        return block

    @staticmethod
    def from_db(node: AgentNode, for_export: bool = False) -> "NodeModel":
        obj = NodeModel(
            id=node.id,
            block_id=node.agentBlockId,
            input_default=type_utils.convert(node.constantInput, dict[str, Any]),
            metadata=type_utils.convert(node.metadata, dict[str, Any]),
            graph_id=node.agentGraphId,
            graph_version=node.agentGraphVersion,
            webhook_id=node.webhookId,
            webhook=Webhook.from_db(node.Webhook) if node.Webhook else None,
        )
        obj.input_links = [Link.from_db(link) for link in node.Input or []]
        obj.output_links = [Link.from_db(link) for link in node.Output or []]
        if for_export:
            return obj.stripped_for_export()
        return obj

    def is_triggered_by_event_type(self, event_type: str) -> bool: