upp-python 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
upp/models/client.py ADDED
@@ -0,0 +1,113 @@
1
+ """UPP Client Protocol.
2
+
3
+ Defines :class:`UPPClientProtocol`, the top-level interface that any
4
+ UPP-compliant client must satisfy. It declares all ten operations
5
+ specified by the Universal Personalization Protocol.
6
+
7
+ Design note — why this Protocol does NOT inherit from the backend protocols
8
+ (``IngestBackend``, ``RetrieverBackend``, ``OntologyBackend``):
9
+
10
+ Backends are *infrastructure* components — each one owns a single
11
+ responsibility (persistence, retrieval, ontology metadata). A client
12
+ is an *orchestrator*: it delegates to backends but lives at a higher
13
+ abstraction level. Inheriting from the backend protocols would
14
+ conflate these two roles and allow a client instance to be passed
15
+ where a backend is expected, creating a misleading extra layer of
16
+ indirection.
17
+
18
+ Instead, ``UPPClientProtocol`` declares the same method signatures
19
+ independently. This keeps the type hierarchy honest — a client *is
20
+ not* a backend — while still guaranteeing that every compliant client
21
+ exposes the full set of UPP operations.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any, Protocol, runtime_checkable
27
+
28
+ from upp.models.events import ContextualizeResult, Event, StoredEvent, TaskResult
29
+ from upp.models.labels import LabelDefinition
30
+
31
+
32
+ @runtime_checkable
33
+ class UPPClientProtocol(Protocol):
34
+ """Top-level protocol for a UPP-compliant client.
35
+
36
+ Any implementation that satisfies this protocol exposes the ten
37
+ operations defined by the Universal Personalization Protocol:
38
+
39
+ Core (write):
40
+ 1. ingest — Persist extracted events.
41
+ 2. delete_events — Delete events (GDPR / CCPA compliance).
42
+
43
+ Core (read + write):
44
+ 3. retrieve — Intelligent, query-driven event retrieval.
45
+ 4. get_events — Raw listing of all stored events.
46
+ 5. contextualize — Retrieve context and ingest in the background.
47
+
48
+ Discovery:
49
+ 6. info — Server metadata and capabilities.
50
+ 7. get_labels — Available labels in the ontology.
51
+ 8. get_tasks — Check status of background tasks.
52
+
53
+ Portability:
54
+ 9. export_events — Export events for migration.
55
+ 10. import_events — Import events from another server.
56
+ """
57
+
58
+ # ── Core (write) ─────────────────────────────────────────────────
59
+
60
+ async def ingest(
61
+ self,
62
+ entity_key: str,
63
+ text: str,
64
+ ) -> list[StoredEvent]: ...
65
+
66
+ async def delete_events(
67
+ self,
68
+ entity_key: str,
69
+ event_ids: list[str] | None = None,
70
+ ) -> int: ...
71
+
72
+ # ── Core (read) ──────────────────────────────────────────────────
73
+
74
+ async def retrieve(
75
+ self,
76
+ entity_key: str,
77
+ query: str,
78
+ ) -> list[StoredEvent]: ...
79
+
80
+ async def get_events(
81
+ self,
82
+ entity_key: str,
83
+ ) -> list[StoredEvent]: ...
84
+
85
+ async def contextualize(
86
+ self,
87
+ entity_key: str,
88
+ text: str,
89
+ ) -> ContextualizeResult: ...
90
+
91
+ # ── Discovery ────────────────────────────────────────────────────
92
+
93
+ def info(self) -> dict[str, Any]: ...
94
+
95
+ def get_labels(self) -> list[LabelDefinition]: ...
96
+
97
+ async def get_tasks(
98
+ self,
99
+ task_ids: list[str],
100
+ ) -> list[TaskResult]: ...
101
+
102
+ # ── Portability ──────────────────────────────────────────────────
103
+
104
+ async def export_events(
105
+ self,
106
+ entity_key: str,
107
+ ) -> list[StoredEvent]: ...
108
+
109
+ async def import_events(
110
+ self,
111
+ entity_key: str,
112
+ events: list[Event],
113
+ ) -> list[StoredEvent]: ...
upp/models/enums.py ADDED
@@ -0,0 +1,124 @@
1
+ """UPP Enumerations.
2
+
3
+ Defines the enumeration types used throughout the Universal Personalization
4
+ Protocol. All enums inherit from ``str`` and ``enum.Enum`` so they
5
+ serialize naturally to their string values in JSON.
6
+
7
+ Enumerations:
8
+ EventStatus: Lifecycle state of a stored event.
9
+ SourceType: Provenance classification of an extracted fact.
10
+ SensitivityTier: Privacy classification for ontology labels.
11
+ Cardinality: Whether a label accepts one or many values.
12
+ Durability: Expected lifespan of a fact.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import enum
18
+
19
+ __all__ = [
20
+ "Cardinality",
21
+ "Durability",
22
+ "EventStatus",
23
+ "SensitivityTier",
24
+ "SourceType",
25
+ "TaskStatus",
26
+ ]
27
+
28
+
29
+ class EventStatus(enum.StrEnum):
30
+ """Lifecycle state of a stored event.
31
+
32
+ Events follow an immutable event-sourcing pattern:
33
+
34
+ - ``VALID`` — Active and authoritative.
35
+ - ``STAGED`` — Low confidence, pending reinforcement.
36
+ - ``SUPERSEDED`` — Replaced by a newer event, retained for audit.
37
+ """
38
+
39
+ VALID = "valid"
40
+ """Current, retrievable event."""
41
+
42
+ STAGED = "staged"
43
+ """Low-confidence event awaiting reinforcement."""
44
+
45
+ SUPERSEDED = "superseded"
46
+ """Replaced by a newer event. Retained for audit trail."""
47
+
48
+
49
+ class SourceType(enum.StrEnum):
50
+ """Classifies how a fact was obtained.
51
+
52
+ Source types indicate the provenance of an extracted fact.
53
+ """
54
+
55
+ USER_STATED = "user_stated"
56
+ """The user explicitly stated this fact."""
57
+
58
+ AGENT_OBSERVED = "agent_observed"
59
+ """The agent observed or derived this fact from conversation context."""
60
+
61
+ INFERRED = "inferred"
62
+ """The system inferred this fact from indirect signals."""
63
+
64
+
65
+ class SensitivityTier(enum.StrEnum):
66
+ """Privacy classification for ontology labels.
67
+
68
+ Ordered from least to most sensitive:
69
+ ``TIER_PUBLIC < TIER_WORK < TIER_PERSONAL < TIER_SENSITIVE < TIER_INTERNAL``
70
+ """
71
+
72
+ TIER_PUBLIC = "tier_public"
73
+ """Safe to share broadly."""
74
+
75
+ TIER_WORK = "tier_work"
76
+ """Professional context."""
77
+
78
+ TIER_PERSONAL = "tier_personal"
79
+ """Personal but non-sensitive."""
80
+
81
+ TIER_SENSITIVE = "tier_sensitive"
82
+ """Sensitive personal data."""
83
+
84
+ TIER_INTERNAL = "tier_internal"
85
+ """Never shared externally."""
86
+
87
+
88
+ class Cardinality(enum.StrEnum):
89
+ """Defines whether a label accepts one or many concurrent values.
90
+
91
+ Cardinality determines supersession behavior: singular labels cause
92
+ new events to supersede old ones, while plural labels accumulate.
93
+ """
94
+
95
+ SINGULAR = "singular"
96
+ """Only one value at a time. New values supersede old ones."""
97
+
98
+ PLURAL = "plural"
99
+ """Multiple values coexist. New values are added alongside existing ones."""
100
+
101
+
102
+ class Durability(enum.StrEnum):
103
+ """Indicates how long a fact is expected to remain valid.
104
+
105
+ Ordering (longest to shortest): ``PERMANENT > TRANSIENT > EPHEMERAL``
106
+ """
107
+
108
+ PERMANENT = "permanent"
109
+ """Unlikely to change over a person's lifetime."""
110
+
111
+ TRANSIENT = "transient"
112
+ """Changes over months or years."""
113
+
114
+ EPHEMERAL = "ephemeral"
115
+ """Changes frequently — days or weeks."""
116
+
117
+
118
+ class TaskStatus(enum.StrEnum):
119
+ """Status of a background task."""
120
+
121
+ PENDING = "pending"
122
+ RUNNING = "running"
123
+ COMPLETED = "completed"
124
+ FAILED = "failed"
upp/models/events.py ADDED
@@ -0,0 +1,124 @@
1
+ """UPP Event Models.
2
+
3
+ Defines the core event entities in the Universal Personalization Protocol:
4
+
5
+ - :class:`Event` — The atomic unit of extracted personal information.
6
+ - :class:`StoredEvent` — An Event after persistence, enriched with server metadata.
7
+
8
+ Both models are immutable (frozen). Events follow an event-sourcing pattern
9
+ where they are never modified after creation.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from datetime import datetime
15
+
16
+ from pydantic import BaseModel, Field
17
+
18
+ from upp.models.enums import EventStatus, SourceType, TaskStatus
19
+
20
+ __all__ = [
21
+ "ContextualizeResult",
22
+ "Event",
23
+ "StoredEvent",
24
+ "TaskResult",
25
+ ]
26
+
27
+
28
+ class Event(BaseModel):
29
+ """An atomic unit of extracted personal information.
30
+
31
+ Events are produced by the extraction pipeline and consumed by the
32
+ store layer. They are immutable — once created, they are never modified.
33
+
34
+ Attributes:
35
+ value: The extracted fact as natural-language text.
36
+ labels: One or more ontology label keys this fact maps to.
37
+ confidence: Extraction confidence score in [0.0, 1.0].
38
+ source_type: Provenance classification of the fact.
39
+ """
40
+
41
+ model_config = {"frozen": True}
42
+
43
+ value: str = Field(
44
+ min_length=1,
45
+ description="The extracted fact as natural-language text.",
46
+ )
47
+ labels: list[str] = Field(
48
+ min_length=1,
49
+ description="One or more ontology label keys this fact maps to.",
50
+ )
51
+ confidence: float = Field(
52
+ ge=0.0,
53
+ le=1.0,
54
+ description="Extraction confidence score in [0.0, 1.0].",
55
+ )
56
+ source_type: SourceType = Field(
57
+ description="Provenance classification: user_stated, agent_observed, or inferred.",
58
+ )
59
+ valid_from: str | None = Field(
60
+ default=None,
61
+ description="ISO-8601 start of the fact's validity window.",
62
+ )
63
+ valid_until: str | None = Field(
64
+ default=None,
65
+ description="ISO-8601 end of the fact's validity window.",
66
+ )
67
+
68
+
69
+ class StoredEvent(Event):
70
+ """A persisted event with server-assigned metadata.
71
+
72
+ Extends :class:`Event` with fields assigned by the server upon
73
+ persistence: unique ID, user key, lifecycle status, creation
74
+ timestamp, and optional supersession reference.
75
+
76
+ Like ``Event``, ``StoredEvent`` is immutable.
77
+
78
+ Attributes:
79
+ id: Unique event identifier (UUID v4).
80
+ entity_key: Unique identifier of the user who owns this event.
81
+ status: Lifecycle status (valid, staged, superseded).
82
+ created_at: Timestamp of creation.
83
+ superseded_by: ID of the event that replaced this one.
84
+ """
85
+
86
+ id: str = Field(
87
+ description="Unique event identifier (UUID v4).",
88
+ )
89
+ entity_key: str = Field(
90
+ description="Unique identifier of the user who owns this event.",
91
+ )
92
+ status: EventStatus = Field(
93
+ default=EventStatus.VALID,
94
+ description="Lifecycle status: valid, staged, or superseded.",
95
+ )
96
+ created_at: datetime = Field(
97
+ description="Timestamp of creation (UTC).",
98
+ )
99
+ superseded_by: str | None = Field(
100
+ default=None,
101
+ description="ID of the event that replaced this one (if superseded).",
102
+ )
103
+
104
+
105
+ class TaskResult(BaseModel):
106
+ """Status and result of a background task."""
107
+
108
+ model_config = {"frozen": True}
109
+
110
+ task_id: str = Field(description="The task identifier.")
111
+ status: TaskStatus = Field(description="Current task status.")
112
+ result: list[StoredEvent] | None = Field(default=None, description="Resulting events when completed.")
113
+ error: str | None = Field(default=None, description="Error message when failed.")
114
+ created_at: datetime = Field(description="When the task was created (UTC).")
115
+ completed_at: datetime | None = Field(default=None, description="When the task finished (UTC).")
116
+
117
+
118
+ class ContextualizeResult(BaseModel):
119
+ """Result of a contextualize operation."""
120
+
121
+ model_config = {"frozen": True}
122
+
123
+ events: list[StoredEvent] = Field(description="Relevant existing events.")
124
+ task_id: str = Field(description="Reference to the background ingest task.")
upp/models/labels.py ADDED
@@ -0,0 +1,71 @@
1
+ """UPP Label Definition Model.
2
+
3
+ Defines the :class:`LabelDefinition` model — the fundamental unit of the
4
+ UPP ontology taxonomy. Labels categorize personal facts using the 5W+H
5
+ framework (Who, What, Where, When, Why, How) plus Preferences, Relationships,
6
+ and Meta categories.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from pydantic import BaseModel, Field
12
+
13
+ from upp.models.enums import Cardinality, Durability, SensitivityTier
14
+
15
+ __all__ = [
16
+ "LabelDefinition",
17
+ ]
18
+
19
+
20
+ class LabelDefinition(BaseModel):
21
+ """Schema definition for a single ontology label.
22
+
23
+ A ``LabelDefinition`` describes a category of personal fact in the
24
+ UPP taxonomy, including its privacy sensitivity, cardinality
25
+ (singular vs. plural), and expected durability.
26
+
27
+ Attributes:
28
+ name: Machine-readable label key (e.g., ``"who_name"``).
29
+ display_name: Human-readable name (e.g., ``"Name"``).
30
+ description: Concise description of what this label captures.
31
+ category: Top-level grouping (WHO, WHAT, WHERE, WHEN, WHY, HOW, PREF, REL, META).
32
+ sensitivity: Privacy sensitivity tier.
33
+ cardinality: Whether the label accepts one or many values.
34
+ durability: Expected lifespan of facts under this label.
35
+ examples: Optional example values to guide classification.
36
+ """
37
+
38
+ model_config = {"frozen": True}
39
+
40
+ name: str = Field(
41
+ description="Machine-readable label key (e.g., 'who_name').",
42
+ )
43
+ display_name: str = Field(
44
+ description="Human-readable name (e.g., 'Name').",
45
+ )
46
+ description: str = Field(
47
+ description="Concise description of what this label captures.",
48
+ )
49
+ classification_guidance: str | None = Field(
50
+ default=None,
51
+ description="Classification and disambiguation guidance for label extraction.",
52
+ )
53
+ category: str = Field(
54
+ description=("Top-level grouping defined by the ontology (e.g., user/v1 uses WHO, WHAT, WHERE, etc.)."),
55
+ )
56
+ sensitivity: SensitivityTier = Field(
57
+ description="Privacy sensitivity tier.",
58
+ )
59
+ cardinality: Cardinality = Field(
60
+ description="Whether the label accepts one value (singular) or many (plural).",
61
+ )
62
+ durability: Durability = Field(
63
+ description="Expected lifespan: permanent, transient, or ephemeral.",
64
+ )
65
+ examples: list[str] = Field(
66
+ description="Example values to guide classification and extraction.",
67
+ )
68
+ anti_examples: list[str] | None = Field(
69
+ default=None,
70
+ description="Counter-examples to clarify label boundaries and prevent misclassification.",
71
+ )
File without changes
@@ -0,0 +1,112 @@
1
+ """UPP user/v1 Ontology — Loader and Implementation.
2
+
3
+ Provides :class:`OntologyUserV1`, an implementation of
4
+ :class:`~upp.backends.ontology.OntologyBackend` backed by
5
+ ``ontologies/user/v1.json``.
6
+
7
+ Usage::
8
+
9
+ from upp.ontologies.user_v1 import OntologyUserV1
10
+
11
+ ontology = OntologyUserV1()
12
+ all_labels = ontology.get_labels()
13
+ label = ontology.get_label_by_name("who_name")
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ from pathlib import Path
20
+
21
+ from upp.backends.ontology import OntologyBackend
22
+ from upp.models.labels import LabelDefinition
23
+
24
+ __all__ = ["OntologyUserV1"]
25
+
26
+ #: Default path to the ontology file, resolved relative to this package.
27
+ _DEFAULT_ONTOLOGY_PATH = Path(__file__).resolve().parent.parent.parent.parent.parent.parent / "ontologies" / "user" / "v1.json"
28
+
29
+ # Module-level cache
30
+ _cached_labels: list[LabelDefinition] | None = None
31
+ _cached_labels_by_name: dict[str, LabelDefinition] | None = None
32
+
33
+
34
+ def _load_labels(path: Path | None = None) -> list[LabelDefinition]:
35
+ """Load label definitions from the ontology JSON file.
36
+
37
+ Args:
38
+ path: Optional path to the ontology file.
39
+
40
+ Returns:
41
+ A list of :class:`LabelDefinition` objects.
42
+
43
+ Raises:
44
+ FileNotFoundError: If the ontology file does not exist.
45
+ json.JSONDecodeError: If the file contains invalid JSON.
46
+ """
47
+ ontology_path = path or _DEFAULT_ONTOLOGY_PATH
48
+
49
+ if not ontology_path.exists():
50
+ raise FileNotFoundError(
51
+ f"Default ontology file not found at {ontology_path}. Ensure the ontologies/user/v1.json file exists in the UPP repository root."
52
+ )
53
+
54
+ raw = json.loads(ontology_path.read_text(encoding="utf-8"))
55
+ raw_labels = raw.get("labels", [])
56
+
57
+ labels: list[LabelDefinition] = []
58
+
59
+ # Support both array format and dict format
60
+ if isinstance(raw_labels, list):
61
+ for label_data in raw_labels:
62
+ labels.append(LabelDefinition.model_validate(label_data))
63
+ elif isinstance(raw_labels, dict):
64
+ for key, label_data in raw_labels.items():
65
+ if "name" not in label_data:
66
+ label_data["name"] = key
67
+ labels.append(LabelDefinition.model_validate(label_data))
68
+
69
+ return labels
70
+
71
+
72
+ def _ensure_loaded() -> tuple[list[LabelDefinition], dict[str, LabelDefinition]]:
73
+ """Ensure labels are loaded and cached.
74
+
75
+ Returns:
76
+ Tuple of (labels list, labels-by-name dict).
77
+ """
78
+ global _cached_labels, _cached_labels_by_name
79
+ if _cached_labels is None:
80
+ _cached_labels = _load_labels()
81
+ _cached_labels_by_name = {label.name: label for label in _cached_labels}
82
+ return _cached_labels, _cached_labels_by_name # type: ignore[return-value]
83
+
84
+
85
+ class OntologyUserV1(OntologyBackend):
86
+ """Ontology implementation backed by ontologies/user/v1.json."""
87
+
88
+ def get_labels(self) -> list[LabelDefinition]:
89
+ """Return all label definitions for the ontology."""
90
+ labels, _ = _ensure_loaded()
91
+ return list(labels)
92
+
93
+ def get_label_by_name(self, name: str) -> LabelDefinition:
94
+ """Get a label definition by its name.
95
+
96
+ Args:
97
+ name: The name of the label to retrieve.
98
+
99
+ Returns:
100
+ The :class:`LabelDefinition` with the specified name.
101
+
102
+ Raises:
103
+ KeyError: If no label with the given name exists.
104
+ """
105
+ _, labels_by_name = _ensure_loaded()
106
+ if name not in labels_by_name:
107
+ raise KeyError(f"Label with name '{name}' not found in ontology.")
108
+ return labels_by_name[name]
109
+
110
+ def get_version(self) -> str:
111
+ """Return the ontology identifier for this server instance."""
112
+ return "user/v1"
upp/py.typed ADDED
File without changes
upp/rpc/.gitkeep ADDED
File without changes
upp/rpc/__init__.py ADDED
@@ -0,0 +1,137 @@
1
+ """UPP JSON-RPC 2.0 Support.
2
+
3
+ This package provides JSON-RPC 2.0 message types, codec functions,
4
+ method constants, error definitions, and typed request/response models
5
+ for all ten UPP operations.
6
+
7
+ Message Types:
8
+ JsonRpcRequest, JsonRpcResponse, JsonRpcError, JsonRpcNotification
9
+
10
+ Operation Models:
11
+ IngestRequest/Response, RetrieveRequest/Response, EventsRequest/Response,
12
+ DeleteRequest/Response, InfoRequest/Response, LabelsRequest/Response,
13
+ ExportRequest/Response, ImportRequest/Response
14
+
15
+ Codec:
16
+ encode_request, decode_request, encode_response, decode_response
17
+
18
+ Methods:
19
+ UPP_INGEST, UPP_RETRIEVE, UPP_EVENTS, UPP_DELETE,
20
+ UPP_INFO, UPP_LABELS, UPP_EXPORT, UPP_IMPORT, ALL_METHODS
21
+
22
+ Errors:
23
+ UppError, standard and UPP-specific error code constants
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ from upp.rpc.codec import decode_request, decode_response, encode_request, encode_response
29
+ from upp.rpc.errors import (
30
+ EXTRACTION_FAILED,
31
+ INGEST_FAILED,
32
+ INTERNAL_ERROR,
33
+ INVALID_PARAMS,
34
+ INVALID_REQUEST,
35
+ METHOD_NOT_FOUND,
36
+ ONTOLOGY_NOT_FOUND,
37
+ PARSE_ERROR,
38
+ USER_NOT_FOUND,
39
+ UppError,
40
+ )
41
+ from upp.rpc.messages import (
42
+ ContextualizeRequest,
43
+ ContextualizeResponse,
44
+ DeleteRequest,
45
+ DeleteResponse,
46
+ EventsRequest,
47
+ EventsResponse,
48
+ ExportRequest,
49
+ ExportResponse,
50
+ GetTasksRequest,
51
+ GetTasksResponse,
52
+ ImportRequest,
53
+ ImportResponse,
54
+ InfoRequest,
55
+ InfoResponse,
56
+ IngestRequest,
57
+ IngestResponse,
58
+ JsonRpcError,
59
+ JsonRpcNotification,
60
+ JsonRpcRequest,
61
+ JsonRpcResponse,
62
+ LabelsRequest,
63
+ LabelsResponse,
64
+ RetrieveRequest,
65
+ RetrieveResponse,
66
+ )
67
+ from upp.rpc.methods import (
68
+ ALL_METHODS,
69
+ UPP_CONTEXTUALIZE,
70
+ UPP_DELETE,
71
+ UPP_EVENTS,
72
+ UPP_EXPORT,
73
+ UPP_GET_TASKS,
74
+ UPP_IMPORT,
75
+ UPP_INFO,
76
+ UPP_INGEST,
77
+ UPP_LABELS,
78
+ UPP_RETRIEVE,
79
+ )
80
+
81
+ __all__ = [
82
+ # Message types
83
+ "JsonRpcError",
84
+ "JsonRpcNotification",
85
+ "JsonRpcRequest",
86
+ "JsonRpcResponse",
87
+ # Operation request/response models
88
+ "ContextualizeRequest",
89
+ "ContextualizeResponse",
90
+ "DeleteRequest",
91
+ "DeleteResponse",
92
+ "EventsRequest",
93
+ "EventsResponse",
94
+ "ExportRequest",
95
+ "ExportResponse",
96
+ "GetTasksRequest",
97
+ "GetTasksResponse",
98
+ "ImportRequest",
99
+ "ImportResponse",
100
+ "InfoRequest",
101
+ "InfoResponse",
102
+ "LabelsRequest",
103
+ "LabelsResponse",
104
+ "IngestRequest",
105
+ "IngestResponse",
106
+ "RetrieveRequest",
107
+ "RetrieveResponse",
108
+ # Codec
109
+ "decode_request",
110
+ "decode_response",
111
+ "encode_request",
112
+ "encode_response",
113
+ # Method constants
114
+ "ALL_METHODS",
115
+ "UPP_CONTEXTUALIZE",
116
+ "UPP_DELETE",
117
+ "UPP_EVENTS",
118
+ "UPP_EXPORT",
119
+ "UPP_GET_TASKS",
120
+ "UPP_IMPORT",
121
+ "UPP_INFO",
122
+ "UPP_LABELS",
123
+ "UPP_INGEST",
124
+ "UPP_RETRIEVE",
125
+ # Error codes
126
+ "EXTRACTION_FAILED",
127
+ "INTERNAL_ERROR",
128
+ "INVALID_PARAMS",
129
+ "INVALID_REQUEST",
130
+ "METHOD_NOT_FOUND",
131
+ "ONTOLOGY_NOT_FOUND",
132
+ "INGEST_FAILED",
133
+ "PARSE_ERROR",
134
+ "USER_NOT_FOUND",
135
+ # Exception
136
+ "UppError",
137
+ ]