divi 0.0.1.dev0__py3-none-any.whl → 0.0.1.dev14__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.
Files changed (48) hide show
  1. divi/__init__.py +13 -3
  2. divi/config/config.py +0 -0
  3. divi/decorators/__init__.py +4 -0
  4. divi/decorators/obs_openai.py +33 -0
  5. divi/decorators/observable.py +137 -0
  6. divi/proto/common/v1/common.proto +49 -0
  7. divi/proto/common/v1/common_pb2.py +43 -0
  8. divi/proto/common/v1/common_pb2.pyi +44 -0
  9. divi/proto/core/health/v1/health_service.proto +17 -0
  10. divi/proto/core/health/v1/health_service_pb2.py +41 -0
  11. divi/proto/core/health/v1/health_service_pb2.pyi +19 -0
  12. divi/proto/core/health/v1/health_service_pb2_grpc.py +100 -0
  13. divi/proto/metric/v1/metric.proto +26 -0
  14. divi/proto/metric/v1/metric_pb2.py +40 -0
  15. divi/proto/metric/v1/metric_pb2.pyi +25 -0
  16. divi/proto/trace/v1/trace.proto +47 -0
  17. divi/proto/trace/v1/trace_pb2.py +44 -0
  18. divi/proto/trace/v1/trace_pb2.pyi +52 -0
  19. divi/services/__init__.py +7 -0
  20. divi/services/auth/__init__.py +4 -0
  21. divi/services/auth/auth.py +21 -0
  22. divi/services/auth/init.py +21 -0
  23. divi/services/auth/tokman.py +42 -0
  24. divi/services/core/__init__.py +5 -0
  25. divi/services/core/core.py +35 -0
  26. divi/services/core/finish.py +15 -0
  27. divi/services/core/init.py +74 -0
  28. divi/services/datapark/__init__.py +4 -0
  29. divi/services/datapark/datapark.py +63 -0
  30. divi/services/datapark/init.py +5 -0
  31. divi/services/finish.py +9 -0
  32. divi/services/init.py +14 -0
  33. divi/services/service.py +11 -0
  34. divi/session/__init__.py +3 -0
  35. divi/session/session.py +40 -0
  36. divi/session/setup.py +62 -0
  37. divi/session/teardown.py +7 -0
  38. divi/signals/__init__.py +3 -0
  39. divi/signals/trace/__init__.py +3 -0
  40. divi/signals/trace/trace.py +151 -0
  41. divi/utils.py +22 -0
  42. divi-0.0.1.dev14.dist-info/METADATA +17 -0
  43. divi-0.0.1.dev14.dist-info/RECORD +45 -0
  44. divi-0.0.1.dev14.dist-info/licenses/LICENSE +21 -0
  45. divi/hello.py +0 -6
  46. divi-0.0.1.dev0.dist-info/METADATA +0 -19
  47. divi-0.0.1.dev0.dist-info/RECORD +0 -5
  48. {divi-0.0.1.dev0.dist-info → divi-0.0.1.dev14.dist-info}/WHEEL +0 -0
@@ -0,0 +1,151 @@
1
+ import os
2
+ import time
3
+ from datetime import UTC, datetime
4
+ from typing import Any, Mapping, Optional
5
+ from uuid import uuid4
6
+
7
+ from pydantic import UUID4
8
+ from typing_extensions import TypedDict
9
+
10
+ from divi.proto.common.v1.common_pb2 import KeyValue
11
+ from divi.proto.trace.v1.trace_pb2 import Span as SpanProto
12
+
13
+
14
+ class NullTime(TypedDict, total=False):
15
+ """Null time"""
16
+
17
+ Time: str
18
+ """Time in iso format"""
19
+ Valid: bool
20
+ """Valid"""
21
+
22
+
23
+ class TraceSignal(TypedDict, total=False):
24
+ """Trace request"""
25
+
26
+ id: str
27
+ """Trace ID UUID4"""
28
+ start_time: str
29
+ """Start time in iso format"""
30
+ end_time: NullTime
31
+ """End time in iso format"""
32
+
33
+
34
+ class Trace:
35
+ def __init__(self, session_id: UUID4):
36
+ self.trace_id: UUID4 = uuid4()
37
+ self.start_time: str | None = None
38
+ self.end_time: str | None = None
39
+ self.session_id: UUID4 = session_id
40
+
41
+ @property
42
+ def signal(self) -> TraceSignal:
43
+ if self.start_time is None:
44
+ raise ValueError("Trace must be started.")
45
+ signal = TraceSignal(
46
+ id=str(self.trace_id),
47
+ start_time=self.start_time,
48
+ )
49
+ if self.end_time is not None:
50
+ signal["end_time"] = NullTime(
51
+ Time=self.end_time,
52
+ Valid=True,
53
+ )
54
+ return signal
55
+
56
+ @staticmethod
57
+ def unix_nano_to_iso(unix_nano: int) -> str:
58
+ return datetime.utcfromtimestamp(unix_nano / 1e9).isoformat()
59
+
60
+ def start(self):
61
+ """Start the trace by recording the current time in nanoseconds."""
62
+ self.start_time = datetime.now(UTC).isoformat()
63
+
64
+ def end(self):
65
+ """End the trace by recording the end time in nanoseconds."""
66
+ if self.start_time is None:
67
+ raise ValueError("Span must be started before ending.")
68
+ self.end_time = datetime.now(UTC).isoformat()
69
+
70
+
71
+ class Span:
72
+ KIND_MAP = {
73
+ "function": SpanProto.SpanKind.SPAN_KIND_FUNCTION,
74
+ "llm": SpanProto.SpanKind.SPAN_KIND_LLM,
75
+ }
76
+
77
+ def __init__(
78
+ self,
79
+ kind: str = "function",
80
+ name: Optional[str] = None,
81
+ metadata: Optional[Mapping[str, Any]] = None,
82
+ ):
83
+ # span_id is a FixedString(8)
84
+ self.span_id: bytes = self._generate_span_id()
85
+ self.name = name
86
+ self.kind = kind
87
+ self.metadata = metadata
88
+ self.start_time_unix_nano: int | None = None
89
+ self.end_time_unix_nano: int | None = None
90
+
91
+ self.trace_id: UUID4 | None = None
92
+ self.parent_span_id: bytes | None = None
93
+
94
+ @property
95
+ def signal(self) -> SpanProto:
96
+ signal: SpanProto = SpanProto(
97
+ name=self.name,
98
+ span_id=self.span_id,
99
+ kind=self._get_kind(self.kind),
100
+ start_time_unix_nano=self.start_time_unix_nano,
101
+ end_time_unix_nano=self.end_time_unix_nano,
102
+ trace_id=self.trace_id.bytes if self.trace_id else None,
103
+ parent_span_id=self.parent_span_id,
104
+ )
105
+ print(self.kind)
106
+ signal.metadata.extend(
107
+ KeyValue(key=k, value=v)
108
+ for k, v in (self.metadata or dict()).items()
109
+ )
110
+ return signal
111
+
112
+ @classmethod
113
+ def _get_kind(cls, kind: str) -> SpanProto.SpanKind:
114
+ if (k := cls.KIND_MAP.get(kind)) is None:
115
+ raise ValueError(
116
+ f"Unknown kind: {kind}. Now allowed: {cls.KIND_MAP.keys()}"
117
+ )
118
+ return k
119
+
120
+ @classmethod
121
+ def _generate_span_id(cls) -> bytes:
122
+ return os.urandom(8)
123
+
124
+ def start(self):
125
+ """Start the span by recording the current time in nanoseconds."""
126
+ self.start_time_unix_nano = time.time_ns()
127
+
128
+ def end(self):
129
+ """End the span by recording the end time in nanoseconds."""
130
+ if self.start_time_unix_nano is None:
131
+ raise ValueError("Span must be started before ending.")
132
+ self.end_time_unix_nano = time.time_ns()
133
+
134
+ def _as_root(self, trace_id: UUID4):
135
+ """Set the span as a root span."""
136
+ self.trace_id = trace_id
137
+ print("as root")
138
+ print(f"name: {self.name}")
139
+ print(f"trace_id: {self.trace_id}")
140
+ print(f"span_id: {self.span_id}")
141
+
142
+ def _add_parent(self, trace_id: UUID4, parent_id: bytes):
143
+ """Set the parent span ID."""
144
+ self.trace_id = trace_id
145
+ self.parent_span_id = parent_id
146
+
147
+ print("add parent")
148
+ print(f"name: {self.name}")
149
+ print(f"trace_id: {trace_id}")
150
+ print(f"span_id: {self.span_id}")
151
+ print(f"parent_span_id: {parent_id}")
divi/utils.py ADDED
@@ -0,0 +1,22 @@
1
+ import inspect
2
+ import pathlib
3
+ from typing import Callable
4
+
5
+
6
+ def get_server_path() -> str:
7
+ """Get the path to the server binary."""
8
+ path = pathlib.Path(__file__).parent / "bin" / "core"
9
+ if not path.exists():
10
+ raise FileNotFoundError(f"Server binary not found: {path}")
11
+
12
+ return str(path)
13
+
14
+
15
+ def is_async(func: Callable) -> bool:
16
+ """Inspect function or wrapped function to see if it is async."""
17
+ unwrapped_func = inspect.unwrap(func)
18
+ return inspect.iscoroutinefunction(unwrapped_func)
19
+
20
+
21
+ if __name__ == "__main__":
22
+ print(get_server_path())
@@ -0,0 +1,17 @@
1
+ Metadata-Version: 2.4
2
+ Name: divi
3
+ Version: 0.0.1.dev14
4
+ Summary: The Agent Platform for Observability & Evaluation
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.11
7
+ Requires-Dist: grpcio>=1.69.0
8
+ Requires-Dist: protobuf>=5.29.3
9
+ Requires-Dist: pyjwt>=2.10.1
10
+ Requires-Dist: requests>=2.32.3
11
+ Description-Content-Type: text/markdown
12
+
13
+ # Divine Agent
14
+
15
+ Agent Platform for Observability • Evaluation • Playground
16
+
17
+ > The project is still in the development stage. 😇
@@ -0,0 +1,45 @@
1
+ divi/__init__.py,sha256=RnfnWUt0BjmN6ngPQQrUIY6TGJX20NtgbB7fsq2elnQ,396
2
+ divi/utils.py,sha256=3iVDogCjqQg0jEjhUKEuQ6vHPFp9w7kXNjSVwXt8KmI,574
3
+ divi/config/config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ divi/decorators/__init__.py,sha256=HkyWdC1ctTsVFucCWCkj57JB4NmwONus1d2S2dUbvs4,110
5
+ divi/decorators/obs_openai.py,sha256=4LtQPRgJPPyTOw1318Fi04WYqjIwGX8EP0YiWrTW0dk,1003
6
+ divi/decorators/observable.py,sha256=N_MCX_HbMGpD7v_dxnK6ewhgONGxH4XBO-i-6ybGpkc,4038
7
+ divi/proto/common/v1/common.proto,sha256=Rx8wr0_tOtQ1NseTMnsav4ApD1MDALzQDBA2IvLRTU0,1775
8
+ divi/proto/common/v1/common_pb2.py,sha256=br61OHQVAi6SI3baFcb5xJv2Xd-AZ04A19xeSjLNMXo,2442
9
+ divi/proto/common/v1/common_pb2.pyi,sha256=LmTpFFLxHg2a_qPIdNXXwGEMkbiDcTJdarR9eC-6Fq8,2133
10
+ divi/proto/core/health/v1/health_service.proto,sha256=y39MNiwYiSqxb_JPQI7AmPfNNtP6pbX-WKTseMkjWUM,369
11
+ divi/proto/core/health/v1/health_service_pb2.py,sha256=PKAxy_z7lU1HrwDNIa7AFHha9i8gICCVrcEhpOM79E0,1999
12
+ divi/proto/core/health/v1/health_service_pb2.pyi,sha256=VbYHHTcp3epUVg0lTSxo3xpG52ZGhA7KKMRL5LR5e1c,691
13
+ divi/proto/core/health/v1/health_service_pb2_grpc.py,sha256=6owvQ41KPqSOQ8WjXDjYsunoDVydJfP93vZ4uVSG59s,3953
14
+ divi/proto/metric/v1/metric.proto,sha256=YHRMLUW-MtakHuibR3PJ0s2w5KgV12kc4737iHw0DTk,585
15
+ divi/proto/metric/v1/metric_pb2.py,sha256=uvBhyy8QpaES3Jl82yVfsGazW5654XpRnsdGlpVgIRE,1974
16
+ divi/proto/metric/v1/metric_pb2.pyi,sha256=S7ipsojkD7QZAYefDE4b3PO99Yzc6mOdtSLxH3-b67A,1304
17
+ divi/proto/trace/v1/trace.proto,sha256=mh1nzEgufzRTJx3p8NNute-ozEwEYwClWJTdWUGGVA8,1284
18
+ divi/proto/trace/v1/trace_pb2.py,sha256=N2sVI20CP2NtJLiNt376bxyYrwiqhQwGHO0hJKciUTo,2650
19
+ divi/proto/trace/v1/trace_pb2.pyi,sha256=aTkzh1Txje5ghuAjYpowDLWz8LTNBrJZej5tUHfVIow,2805
20
+ divi/services/__init__.py,sha256=TcVJ_gKxyPIcwhT9GgttqHeyk0icW44uE285KmUiyh4,185
21
+ divi/services/finish.py,sha256=XKPKGJ5cWd5H95G_VpIOlOZOLrcf9StoTs7ayRic2jY,173
22
+ divi/services/init.py,sha256=JVzRQ1m1DTHXFVGUMYnsv-vRvzCO8XFdR6MjIwOL_NY,433
23
+ divi/services/service.py,sha256=1c7JQ49BSdBipGLfVIxTHaNxTuyvVAgrvxV7lyYv_68,285
24
+ divi/services/auth/__init__.py,sha256=PIQ9rQ0jcRqcy03a3BOY7wbzwluIRG_4kI_H4J4mRFk,74
25
+ divi/services/auth/auth.py,sha256=dTpFnNhxbEjzOkBLPQvRblFSO5tedJsdObWTXt84MaE,631
26
+ divi/services/auth/init.py,sha256=UXsOweatrWnuFO9ivSjEsJnHrK9YtStKYX2Nup64KEU,477
27
+ divi/services/auth/tokman.py,sha256=V03wcV6TEy1k9o55teDVB9JZ3Ve2cJdwzWstQhWx4BQ,1070
28
+ divi/services/core/__init__.py,sha256=FWl4ShX0AEnOyL24NEc9mNIVoQOeYO4q0qYX27L_Yyw,111
29
+ divi/services/core/core.py,sha256=PRwPtLgrgmCrejUfKf7HJNrAhGS0paFNZ7JwDToEUAk,1264
30
+ divi/services/core/finish.py,sha256=dIGQpVXcJY4-tKe7A1_VV3yoSHNCDPfOlUltvzvk6VI,231
31
+ divi/services/core/init.py,sha256=e7-fgpOPglBXyEoPkgOAnpJk2ApdFbo7LPupxOb8N-w,1966
32
+ divi/services/datapark/__init__.py,sha256=GbV1mwHE07yutgOlCIYHykSEL5KJ-ApgLutGMzu2eUE,86
33
+ divi/services/datapark/datapark.py,sha256=J96C-K9RCaLT7oWXnMQOM1g7btfIlU7BMWReF3ePOlc,2055
34
+ divi/services/datapark/init.py,sha256=C32f9t3eLsxcYNqEyheh6nW455G2oR0YhhdqBcbN3ec,92
35
+ divi/session/__init__.py,sha256=6lYemv21VQCIHx-xIdi7BxXcPNxVdvE60--8ArReUew,82
36
+ divi/session/session.py,sha256=ID7bQ4CuRPUcZ9S-DSjndiduslYFJukRLuCtChYm3wk,838
37
+ divi/session/setup.py,sha256=jlc3ICR5hRDdrcxoSxi66FYS2TYxqrIJOMgI4i1tEJs,1972
38
+ divi/session/teardown.py,sha256=YiBz_3yCiljMFEofZ60VmRL5sb8WA5GT7EYF8nFznZ4,133
39
+ divi/signals/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
40
+ divi/signals/trace/__init__.py,sha256=K1PaTAMwyBDsK6jJUg4QWy0xVJ_5MA6dlWiUyJeiSQA,44
41
+ divi/signals/trace/trace.py,sha256=y8Xio8Tp_e1tO8l_DAkUuzMrmENNKfIdklF0iWrjGYk,4547
42
+ divi-0.0.1.dev14.dist-info/METADATA,sha256=SPHVAVGgsvGorPvooFCb2MiHdMP2leko0X17Vzvy8xU,457
43
+ divi-0.0.1.dev14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ divi-0.0.1.dev14.dist-info/licenses/LICENSE,sha256=5OJuZ4wMMEV0DgF0tofhAlS_KLkaUsZwwwDS2U_GwQ0,1063
45
+ divi-0.0.1.dev14.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Kaikai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
divi/hello.py DELETED
@@ -1,6 +0,0 @@
1
- def hello():
2
- print("Hello from divine-agent!")
3
-
4
-
5
- if __name__ == "__main__":
6
- hello()
@@ -1,19 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: divi
3
- Version: 0.0.1.dev0
4
- Summary: The Agent Platform for Observability & Evaluation
5
- Requires-Python: >=3.11
6
- Description-Content-Type: text/markdown
7
-
8
- # SDK
9
-
10
- > Python SDK for Divine Agent
11
-
12
- ## Version
13
-
14
- Use `hatch` to manage the version of the SDK, follow the progression in [supported segments](https://hatch.pypa.io/latest/version/#supported-segments)
15
-
16
- ## Thanks
17
-
18
- 1. [uv](https://github.com/astral-sh/uv): An extremely fast Python package and project manager, written in Rust.
19
- 2. [hatch](https://github.com/pypa/hatch): Hatch is a modern, extensible Python project manager.
@@ -1,5 +0,0 @@
1
- divi/__init__.py,sha256=q0MFp_9IarnNwKmPXqIsym2glyxwDg_KrcgOEMpxpYQ,93
2
- divi/hello.py,sha256=wMV7kaInsn9slGGrsuRhV_b1Xd7-ey53ZOY4vyIQuAw,92
3
- divi-0.0.1.dev0.dist-info/METADATA,sha256=ptw3iXFWm9HBgG0aQgh-rotFdVqNBxJPifCpnoUnC9o,600
4
- divi-0.0.1.dev0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
- divi-0.0.1.dev0.dist-info/RECORD,,