llama-deploy-appserver 0.2.7a1__py3-none-any.whl → 0.3.0a1__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 (29) hide show
  1. llama_deploy/appserver/__main__.py +0 -4
  2. llama_deploy/appserver/app.py +105 -25
  3. llama_deploy/appserver/bootstrap.py +76 -24
  4. llama_deploy/appserver/deployment.py +7 -421
  5. llama_deploy/appserver/deployment_config_parser.py +35 -59
  6. llama_deploy/appserver/routers/__init__.py +4 -3
  7. llama_deploy/appserver/routers/deployments.py +162 -385
  8. llama_deploy/appserver/routers/status.py +4 -31
  9. llama_deploy/appserver/routers/ui_proxy.py +213 -0
  10. llama_deploy/appserver/settings.py +57 -55
  11. llama_deploy/appserver/types.py +0 -3
  12. llama_deploy/appserver/workflow_loader.py +383 -0
  13. {llama_deploy_appserver-0.2.7a1.dist-info → llama_deploy_appserver-0.3.0a1.dist-info}/METADATA +3 -6
  14. llama_deploy_appserver-0.3.0a1.dist-info/RECORD +17 -0
  15. {llama_deploy_appserver-0.2.7a1.dist-info → llama_deploy_appserver-0.3.0a1.dist-info}/WHEEL +1 -1
  16. llama_deploy/appserver/client/__init__.py +0 -3
  17. llama_deploy/appserver/client/base.py +0 -30
  18. llama_deploy/appserver/client/client.py +0 -49
  19. llama_deploy/appserver/client/models/__init__.py +0 -4
  20. llama_deploy/appserver/client/models/apiserver.py +0 -356
  21. llama_deploy/appserver/client/models/model.py +0 -82
  22. llama_deploy/appserver/run_autodeploy.py +0 -141
  23. llama_deploy/appserver/server.py +0 -60
  24. llama_deploy/appserver/source_managers/__init__.py +0 -5
  25. llama_deploy/appserver/source_managers/base.py +0 -33
  26. llama_deploy/appserver/source_managers/git.py +0 -48
  27. llama_deploy/appserver/source_managers/local.py +0 -51
  28. llama_deploy/appserver/tracing.py +0 -237
  29. llama_deploy_appserver-0.2.7a1.dist-info/RECORD +0 -28
@@ -1,48 +0,0 @@
1
- import shutil
2
- from pathlib import Path
3
- from typing import Any
4
-
5
- from git import Repo
6
-
7
- from .base import SourceManager, SyncPolicy
8
-
9
-
10
- class GitSourceManager(SourceManager):
11
- """A SourceManager specialized for sources of type `git`."""
12
-
13
- def sync(
14
- self,
15
- source: str,
16
- destination: str | None = None,
17
- sync_policy: SyncPolicy = SyncPolicy.REPLACE,
18
- ) -> None:
19
- """Clones the repository at URL `source` into a local path `destination`.
20
-
21
- Args:
22
- source: The URL of the git repository. It can optionally contain a branch target using the name convention
23
- `git_repo_url@branch_name`. For example, "https://example.com/llama_deploy.git@branch_name".
24
- destination: The path in the local filesystem where to clone the git repository.
25
- """
26
- if not destination:
27
- raise ValueError("Destination cannot be empty")
28
-
29
- if Path(destination).exists():
30
- # FIXME: pull when SyncPolicy is MERGE
31
- shutil.rmtree(destination)
32
-
33
- url, branch_name = self._parse_source(source)
34
- kwargs: dict[str, Any] = {"url": url, "to_path": destination}
35
- if branch_name:
36
- kwargs["multi_options"] = [f"-b {branch_name}", "--single-branch"]
37
-
38
- Repo.clone_from(**kwargs) # type: ignore
39
-
40
- @staticmethod
41
- def _parse_source(source: str) -> tuple[str, str | None]:
42
- branch_name = None
43
- toks = source.split("@")
44
- url = toks[0]
45
- if len(toks) > 1:
46
- branch_name = toks[1]
47
-
48
- return url, branch_name
@@ -1,51 +0,0 @@
1
- import shutil
2
- from pathlib import Path
3
-
4
- from .base import SourceManager, SyncPolicy
5
-
6
-
7
- class LocalSourceManager(SourceManager):
8
- """A SourceManager specialized for sources of type `local`."""
9
-
10
- def sync(
11
- self,
12
- source: str,
13
- destination: str | None = None,
14
- sync_policy: SyncPolicy = SyncPolicy.REPLACE,
15
- ) -> None:
16
- """Copies the folder with path `source` into a local path `destination`.
17
-
18
- Args:
19
- source: The filesystem path to the folder containing the source code.
20
- destination: The path in the local filesystem where to copy the source directory.
21
- """
22
- if sync_policy == SyncPolicy.SKIP:
23
- return
24
-
25
- if not destination:
26
- raise ValueError("Destination cannot be empty")
27
-
28
- if Path(source).is_absolute():
29
- raise ValueError("Source path must be relative to the deployment file")
30
-
31
- base = self._base_path or Path()
32
- final_path = base / source
33
- destination_path = Path(destination)
34
- dirs_exist_ok: bool = False
35
- if destination_path.exists():
36
- # Path is a non-empty directory
37
- if sync_policy == SyncPolicy.REPLACE:
38
- shutil.rmtree(destination_path)
39
- elif sync_policy == SyncPolicy.MERGE:
40
- dirs_exist_ok = True
41
-
42
- try:
43
- shutil.copytree(
44
- final_path, destination_path / source, dirs_exist_ok=dirs_exist_ok
45
- )
46
- except Exception as e:
47
- msg = f"Unable to copy {source} into {destination}: {e}"
48
- raise ValueError(msg) from e
49
-
50
- def relative_path(self, source: str) -> str:
51
- return source
@@ -1,237 +0,0 @@
1
- """Tracing utilities for llama_deploy."""
2
-
3
- import logging
4
- from contextlib import contextmanager, nullcontext
5
- from functools import wraps
6
- from typing import TYPE_CHECKING, Any, Callable, Generator, TypeVar
7
-
8
- if TYPE_CHECKING:
9
- from llama_deploy.appserver.settings import ApiserverSettings
10
-
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- # Since opentelemetry is optional, we have to use Any to type the tracer
15
- _tracer: Any | None = None
16
- _tracing_enabled = False
17
- _null_context = nullcontext()
18
-
19
- F = TypeVar("F", bound=Callable[..., Any])
20
-
21
-
22
- def configure_tracing(settings: "ApiserverSettings") -> None:
23
- """Configure OpenTelemetry tracing based on the provided configuration."""
24
- global _tracer, _tracing_enabled
25
-
26
- if not settings.tracing_enabled:
27
- logger.debug("Tracing is disabled")
28
- _tracing_enabled = False
29
- return
30
-
31
- try:
32
- from opentelemetry import trace # type: ignore[import]
33
- from opentelemetry.instrumentation.asyncio import AsyncioInstrumentor # type: ignore[import]
34
- from opentelemetry.sdk.resources import SERVICE_NAME, Resource # type: ignore[import]
35
- from opentelemetry.sdk.trace import TracerProvider # type: ignore[import]
36
- from opentelemetry.sdk.trace.export import BatchSpanProcessor # type: ignore[import]
37
- from opentelemetry.sdk.trace.sampling import TraceIdRatioBased # type: ignore[import]
38
-
39
- # Create resource with service name
40
- resource = Resource.create({SERVICE_NAME: settings.tracing_service_name})
41
-
42
- # Create tracer provider with sampling
43
- tracer_provider = TracerProvider(
44
- resource=resource, sampler=TraceIdRatioBased(settings.tracing_sample_rate)
45
- )
46
-
47
- # Configure exporter based on config
48
- if settings.tracing_exporter == "console":
49
- from opentelemetry.sdk.trace.export import ConsoleSpanExporter # type: ignore[import]
50
-
51
- exporter = ConsoleSpanExporter()
52
-
53
- elif settings.tracing_exporter == "otlp":
54
- from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( # type: ignore[import]
55
- OTLPSpanExporter,
56
- )
57
-
58
- if not settings.tracing_endpoint:
59
- raise ValueError("OTLP exporter requires an endpoint")
60
- exporter = OTLPSpanExporter(
61
- endpoint=f"{settings.tracing_endpoint}/v1/traces",
62
- insecure=settings.tracing_insecure,
63
- timeout=settings.tracing_timeout,
64
- )
65
- else:
66
- raise ValueError(f"Unsupported exporter: {settings.tracing_exporter}")
67
-
68
- # Add span processor
69
- span_processor = BatchSpanProcessor(exporter)
70
- tracer_provider.add_span_processor(span_processor)
71
-
72
- # Set the global tracer provider
73
- trace.set_tracer_provider(tracer_provider)
74
-
75
- # Initialize global tracer
76
- _tracer = trace.get_tracer(__name__)
77
- _tracing_enabled = True
78
-
79
- # Setup auto-instrumentation
80
- AsyncioInstrumentor().instrument()
81
-
82
- logger.info(
83
- f"Tracing configured with {settings.tracing_exporter} exporter, service: {settings.tracing_service_name}"
84
- )
85
-
86
- except ImportError as e:
87
- msg = (
88
- f"Tracing is enabled but OpenTelemetry instrumentation packages are missing: {e}. "
89
- "Run `pip install llama_deploy[observability]`"
90
- )
91
- logger.warning(msg)
92
- _tracing_enabled = False
93
- except Exception as e:
94
- logger.error(f"Failed to configure tracing: {e}")
95
- _tracing_enabled = False
96
-
97
-
98
- def get_tracer() -> Any | None:
99
- """Get the configured tracer instance."""
100
- return _tracer if _tracing_enabled else None
101
-
102
-
103
- def is_tracing_enabled() -> bool:
104
- """Check if tracing is enabled."""
105
- return _tracing_enabled
106
-
107
-
108
- def trace_method(
109
- span_name: str | None = None, attributes: dict | None = None
110
- ) -> Callable[[F], F]:
111
- """Decorator to add tracing to synchronous methods."""
112
-
113
- def decorator(func: F) -> F:
114
- if not _tracing_enabled:
115
- return func
116
-
117
- @wraps(func)
118
- def wrapper(*args, **kwargs): # type: ignore
119
- tracer = get_tracer()
120
- if not tracer:
121
- return func(*args, **kwargs)
122
-
123
- name = span_name or f"{func.__module__}.{func.__qualname__}" # type: ignore
124
- with tracer.start_as_current_span(name) as span:
125
- if attributes:
126
- span.set_attributes(attributes)
127
-
128
- if hasattr(func, "__annotations__"):
129
- for i, (param_name, _) in enumerate(func.__annotations__.items()):
130
- if i < len(args) and param_name not in {"self", "cls"}:
131
- span.set_attribute(
132
- f"arg.{param_name}", str(args[i])[:100]
133
- ) # Truncate long values
134
-
135
- try:
136
- result = func(*args, **kwargs)
137
- span.set_attribute("success", True)
138
- return result
139
- except Exception as e:
140
- span.set_attribute("success", False)
141
- span.set_attribute("error.type", type(e).__name__)
142
- span.set_attribute("error.message", str(e))
143
- raise
144
-
145
- return wrapper # type: ignore
146
-
147
- return decorator
148
-
149
-
150
- def trace_async_method(
151
- span_name: str | None = None, attributes: dict | None = None
152
- ) -> Callable[[F], F]:
153
- """Decorator to add tracing to asynchronous methods."""
154
-
155
- def decorator(func: F) -> F:
156
- if not _tracing_enabled:
157
- return func
158
-
159
- @wraps(func)
160
- async def wrapper(*args, **kwargs): # type: ignore
161
- tracer = get_tracer()
162
- if not tracer:
163
- return await func(*args, **kwargs)
164
-
165
- name = span_name or f"{func.__module__}.{func.__qualname__}" # type: ignore
166
- with tracer.start_as_current_span(name) as span:
167
- if attributes:
168
- span.set_attributes(attributes)
169
-
170
- if hasattr(func, "__annotations__"):
171
- for i, (param_name, _) in enumerate(func.__annotations__.items()):
172
- if i < len(args) and param_name not in {"self", "cls"}:
173
- span.set_attribute(
174
- f"arg.{param_name}", str(args[i])[:100]
175
- ) # Truncate long values
176
-
177
- try:
178
- result = await func(*args, **kwargs)
179
- span.set_attribute("success", True)
180
- return result
181
- except Exception as e:
182
- span.set_attribute("success", False)
183
- span.set_attribute("error.type", type(e).__name__)
184
- span.set_attribute("error.message", str(e))
185
- raise
186
-
187
- return wrapper # type: ignore
188
-
189
- return decorator
190
-
191
-
192
- @contextmanager
193
- def create_span(
194
- name: str, attributes: dict | None = None
195
- ) -> Generator[Any, None, None]:
196
- tracer = get_tracer()
197
- if tracer is None:
198
- yield
199
- return
200
-
201
- with tracer.start_as_current_span(name) as span:
202
- if attributes:
203
- for k, v in attributes.items():
204
- span.set_attribute(k, v)
205
- yield span
206
-
207
-
208
- def add_span_attribute(key: str, value: Any) -> None:
209
- """Add an attribute to the current span if tracing is enabled."""
210
- if not _tracing_enabled:
211
- return
212
-
213
- try:
214
- from opentelemetry import trace # type: ignore[import]
215
-
216
- current_span = trace.get_current_span()
217
- if current_span:
218
- current_span.set_attribute(key, str(value))
219
- except Exception:
220
- # Silently ignore tracing errors
221
- pass
222
-
223
-
224
- def add_span_event(name: str, attributes: dict | None = None) -> None:
225
- """Add an event to the current span if tracing is enabled."""
226
- if not _tracing_enabled:
227
- return
228
-
229
- try:
230
- from opentelemetry import trace # type: ignore[import]
231
-
232
- current_span = trace.get_current_span()
233
- if current_span:
234
- current_span.add_event(name, attributes or {})
235
- except Exception:
236
- # Silently ignore tracing errors
237
- pass
@@ -1,28 +0,0 @@
1
- llama_deploy/appserver/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
2
- llama_deploy/appserver/__main__.py,sha256=2dd2fe1f9ceff01038198515f30c107a82dc83ffd8c038d123f41893bf7fe4cb,333
3
- llama_deploy/appserver/app.py,sha256=fbe5fa15e7dbb1ab4b98e29f838434023894b6adac8e099bc42ea9c4df990867,1506
4
- llama_deploy/appserver/bootstrap.py,sha256=13b332df52ef763e20fe2ff9bcc20917508fee8153fae80569d942dc6be03793,1505
5
- llama_deploy/appserver/client/__init__.py,sha256=1675fd1c7fb675700396e35fb9c83df093cc7ebb8ca01a4df4447d95991542f4,49
6
- llama_deploy/appserver/client/base.py,sha256=2d6e5b263b55b393bc3ff383109d868e3c7a1e298388958476ec028c810004cf,1137
7
- llama_deploy/appserver/client/client.py,sha256=7af5ab5359ed4cd8802749461f213b7b646984108023592eb15a04904dd96211,1312
8
- llama_deploy/appserver/client/models/__init__.py,sha256=d1cb7f4948b34831f88951d51b2bd63699ae60bee07dbcfe8d20c4c77719e213,142
9
- llama_deploy/appserver/client/models/apiserver.py,sha256=f258710196b55b5dd3d157a4d112d98947932314e6024019919749dced063a19,12511
10
- llama_deploy/appserver/client/models/model.py,sha256=1f81dff71866610735f30efa978182f568e6fec5eff262a73ad526ecf3ffba6b,2655
11
- llama_deploy/appserver/deployment.py,sha256=184dfe95476dd8eea8d3d63b9fed60ed37136f6f38ffa8d8fa66be107ded4e31,19207
12
- llama_deploy/appserver/deployment_config_parser.py,sha256=4b4e2f20336c3b46db5ae64fccb663a8f1c4f970d24daebc8362809ab665ff80,4032
13
- llama_deploy/appserver/routers/__init__.py,sha256=f882ea036d83f8239de66b6a17ae0a51865402e115310960680adff8ded49dab,129
14
- llama_deploy/appserver/routers/deployments.py,sha256=7839423ea6c4621ddf5e18d91394cf0caecb0f099779b79f8f199dfd8f2e7583,14570
15
- llama_deploy/appserver/routers/status.py,sha256=17b12f37ac92092fa5494b0ea3477f512972c05fc23c5fa56dc498e8e6120c75,1400
16
- llama_deploy/appserver/run_autodeploy.py,sha256=36316cbe2df413d374dcef013f90ed5774a02a2012576356160e22397ae91bed,5000
17
- llama_deploy/appserver/server.py,sha256=68b8db645e3b7323c140d12607812d9d21382aef5a5a1609d3cf30429440eddf,1991
18
- llama_deploy/appserver/settings.py,sha256=1f0bbc8e69edd4007b6be3988b3576699470a1fb06fd3a38d977ef45be1e688b,2891
19
- llama_deploy/appserver/source_managers/__init__.py,sha256=d52f325a4c84f16cfb220337afddcc6145dcfebc44564dc665d33442480e8f84,175
20
- llama_deploy/appserver/source_managers/base.py,sha256=f8ef6f6b851b39d37e7f5ddd631656a8d0e1015470adfc59a53699e83b33e533,1400
21
- llama_deploy/appserver/source_managers/git.py,sha256=ba197235f18297a29895f23a2534040337eddd0c2046fed88ac7f2d0a3038415,1577
22
- llama_deploy/appserver/source_managers/local.py,sha256=9e80d5f2a2247779e15c6a7b19ceef75dec7e9b0877ac350530d0f5d81ac2d3f,1690
23
- llama_deploy/appserver/stats.py,sha256=1f3989f6705a6de3e4d61ee8cdd189fbe04a2c53ec5e720b2e5168acc331427f,691
24
- llama_deploy/appserver/tracing.py,sha256=211e0695041f2ebf3a05471035fdcff582263b8150df2a459b54932bed9a9194,8199
25
- llama_deploy/appserver/types.py,sha256=f9e1e037f196d7a55af06095404ed33c8620d5c95f61c8bc87df75b6e714897f,2237
26
- llama_deploy_appserver-0.2.7a1.dist-info/WHEEL,sha256=cc8ae5806c5874a696cde0fcf78fdf73db4982e7c824f3ceab35e2b65182fa1a,79
27
- llama_deploy_appserver-0.2.7a1.dist-info/METADATA,sha256=7b2c8925c464b72bf518926eb786afff346ff5bb1dad7caf254802ecf8350dd2,845
28
- llama_deploy_appserver-0.2.7a1.dist-info/RECORD,,