Spaces:
Sleeping
Sleeping
| """Identifier generation for OpenCode API - ULID-based IDs""" | |
| from ulid import ULID | |
| from datetime import datetime | |
| from typing import Literal | |
| PrefixType = Literal["session", "message", "part", "tool", "question"] | |
| class Identifier: | |
| """ | |
| ULID-based identifier generator. | |
| Generates sortable, unique IDs with type prefixes. | |
| """ | |
| PREFIXES = { | |
| "session": "ses", | |
| "message": "msg", | |
| "part": "prt", | |
| "tool": "tol", | |
| "question": "qst", | |
| } | |
| def generate(cls, prefix: PrefixType) -> str: | |
| """Generate a new ULID with prefix""" | |
| ulid = ULID() | |
| prefix_str = cls.PREFIXES.get(prefix, prefix[:3]) | |
| return f"{prefix_str}_{str(ulid).lower()}" | |
| def ascending(cls, prefix: PrefixType) -> str: | |
| """Generate an ascending (time-based) ID""" | |
| return cls.generate(prefix) | |
| def descending(cls, prefix: PrefixType) -> str: | |
| """ | |
| Generate a descending ID (for reverse chronological sorting). | |
| Uses inverted timestamp bits. | |
| """ | |
| # For simplicity, just use regular ULID | |
| # In production, you'd invert the timestamp bits | |
| return cls.generate(prefix) | |
| def parse(cls, id: str) -> tuple[str, str]: | |
| """Parse an ID into prefix and ULID parts""" | |
| parts = id.split("_", 1) | |
| if len(parts) != 2: | |
| raise ValueError(f"Invalid ID format: {id}") | |
| return parts[0], parts[1] | |
| def validate(cls, id: str, expected_prefix: PrefixType) -> bool: | |
| """Validate that an ID has the expected prefix""" | |
| try: | |
| prefix, _ = cls.parse(id) | |
| expected = cls.PREFIXES.get(expected_prefix, expected_prefix[:3]) | |
| return prefix == expected | |
| except ValueError: | |
| return False | |
| # Convenience function | |
| def generate_id(prefix: PrefixType) -> str: | |
| """Generate a new ULID-based ID with the given prefix.""" | |
| return Identifier.generate(prefix) | |