llama-deploy-appserver 0.3.26__py3-none-any.whl → 0.4.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.
@@ -426,7 +426,7 @@ def export_json_graph(
426
426
  This follows the same initialization path as preflight validation and writes
427
427
  a workflows.json-style structure compatible with the CLI expectations.
428
428
  """
429
- from workflows.representation_utils import extract_workflow_structure
429
+ from workflows.representation.build import get_workflow_representation
430
430
 
431
431
  configure_settings(
432
432
  app_root=cwd,
@@ -439,9 +439,7 @@ def export_json_graph(
439
439
 
440
440
  graph: dict[str, dict[str, Any]] = {}
441
441
  for name, workflow in workflows.items():
442
- wf_repr_dict = (
443
- extract_workflow_structure(workflow).to_response_model().model_dump()
444
- )
442
+ wf_repr_dict = get_workflow_representation(workflow).model_dump()
445
443
  graph[name] = wf_repr_dict
446
444
 
447
445
  output_path = output or (Path.cwd() / "workflows.json")
@@ -2,10 +2,9 @@ import asyncio
2
2
  import logging
3
3
  import os
4
4
  import sys
5
- from typing import Any, List, cast
5
+ from typing import Any, List
6
6
 
7
- from llama_cloud.client import AsyncLlamaCloud, httpx
8
- from llama_cloud_services.beta.agent_data import AsyncAgentDataClient
7
+ import httpx
9
8
  from llama_deploy.appserver.settings import ApiserverSettings
10
9
  from llama_deploy.core.client.ssl_util import get_httpx_verify_param
11
10
  from llama_deploy.core.deployment_config import DeploymentConfig
@@ -21,8 +20,12 @@ else:
21
20
 
22
21
  logger = logging.getLogger(__name__)
23
22
 
23
+ DEFAULT_BASE_URL = "https://api.cloud.llamaindex.ai"
24
+
24
25
 
25
26
  class AgentDataStore(AbstractWorkflowStore):
27
+ """Workflow store backed by LlamaCloud Agent Data API using raw httpx."""
28
+
26
29
  def __init__(
27
30
  self, settings: DeploymentConfig, server_settings: ApiserverSettings
28
31
  ) -> None:
@@ -37,71 +40,149 @@ class AgentDataStore(AbstractWorkflowStore):
37
40
  agent_url_id = settings.name
38
41
 
39
42
  self.settings = settings
40
- project_id = os.getenv("LLAMA_DEPLOY_PROJECT_ID")
41
- self.client = AsyncAgentDataClient(
42
- type=PersistentHandler,
43
- collection=collection,
44
- agent_url_id=agent_url_id,
45
- client=AsyncLlamaCloud(
46
- base_url=os.getenv("LLAMA_CLOUD_BASE_URL"),
47
- token=os.getenv("LLAMA_CLOUD_API_KEY"),
48
- httpx_client=httpx.AsyncClient(
49
- headers={"Project-Id": project_id} if project_id else None,
50
- verify=get_httpx_verify_param(),
51
- ),
52
- ),
53
- )
43
+ self.collection = collection
44
+ self.deployment_name = agent_url_id
45
+
46
+ self.base_url = os.getenv("LLAMA_CLOUD_BASE_URL", DEFAULT_BASE_URL).rstrip("/")
47
+ self.api_key = os.getenv("LLAMA_CLOUD_API_KEY")
48
+ self.project_id = os.getenv("LLAMA_DEPLOY_PROJECT_ID")
49
+
54
50
  self.lock = AsyncKeyedLock()
55
51
  # workflow id -> agent data id
56
52
  self.cache = LRUCache[str, str](maxsize=1024)
57
53
 
54
+ def _get_headers(self) -> dict[str, str]:
55
+ """Build HTTP headers for API requests."""
56
+ headers = {
57
+ "Content-Type": "application/json",
58
+ }
59
+ if self.api_key:
60
+ headers["Authorization"] = f"Bearer {self.api_key}"
61
+ if self.project_id:
62
+ headers["Project-Id"] = self.project_id
63
+ return headers
64
+
65
+ def _get_client(self) -> httpx.AsyncClient:
66
+ """Create a new httpx client."""
67
+ return httpx.AsyncClient(
68
+ headers=self._get_headers(),
69
+ verify=get_httpx_verify_param(),
70
+ )
71
+
58
72
  @override
59
73
  async def query(self, query: HandlerQuery) -> List[PersistentHandler]:
60
74
  filters = self._build_filters(query)
61
- results = await self.client.search(
62
- filter=filters,
63
- page_size=1000,
64
- )
65
- return [x.data for x in results.items]
75
+ search_request = {
76
+ "deployment_name": self.deployment_name,
77
+ "collection": self.collection,
78
+ "filter": filters,
79
+ "page_size": 1000,
80
+ }
81
+ async with self._get_client() as client:
82
+ response = await client.post(
83
+ f"{self.base_url}/api/v1/beta/agent-data/:search",
84
+ json=search_request,
85
+ )
86
+ response.raise_for_status()
87
+ data = response.json()
88
+
89
+ items = data.get("items", [])
90
+ return [PersistentHandler(**item["data"]) for item in items]
66
91
 
67
92
  @override
68
93
  async def update(self, handler: PersistentHandler) -> None:
69
94
  async with self.lock.acquire(handler.handler_id):
70
95
  id = await self._get_item_id(handler)
71
96
  if id is None:
72
- item = await self.client.create_item(
73
- data=handler,
74
- )
75
- if item.id is None:
97
+ item = await self._create_item(handler)
98
+ item_id = item.get("id")
99
+ if item_id is None:
76
100
  raise ValueError(f"Failed to create handler {handler.handler_id}")
77
- self.cache.set(handler.handler_id, item.id)
101
+ self.cache.set(handler.handler_id, item_id)
78
102
  else:
79
- await self.client.update_item(
80
- item_id=id,
81
- data=handler,
82
- )
103
+ await self._update_item(id, handler)
83
104
 
84
105
  @override
85
106
  async def delete(self, query: HandlerQuery) -> int:
86
107
  filters = self._build_filters(query)
87
- results = await self.client.search(filter=filters, page_size=1000)
108
+ search_request = {
109
+ "deployment_name": self.deployment_name,
110
+ "collection": self.collection,
111
+ "filter": filters,
112
+ "page_size": 1000,
113
+ }
114
+ async with self._get_client() as client:
115
+ response = await client.post(
116
+ f"{self.base_url}/api/v1/beta/agent-data/:search",
117
+ json=search_request,
118
+ )
119
+ response.raise_for_status()
120
+ data = response.json()
121
+
122
+ items = data.get("items", [])
88
123
  await asyncio.gather(
89
- *[self.client.delete_item(item_id=x.id) for x in results.items if x.id]
124
+ *[self._delete_item(item["id"]) for item in items if item.get("id")]
90
125
  )
91
- return len(results.items)
126
+ return len(items)
127
+
128
+ async def _create_item(self, handler: PersistentHandler) -> dict[str, Any]:
129
+ """Create a new agent data item."""
130
+ create_request = {
131
+ "deployment_name": self.deployment_name,
132
+ "collection": self.collection,
133
+ "data": handler.model_dump(mode="json"),
134
+ }
135
+ async with self._get_client() as client:
136
+ response = await client.post(
137
+ f"{self.base_url}/api/v1/beta/agent-data",
138
+ json=create_request,
139
+ )
140
+ response.raise_for_status()
141
+ return response.json()
142
+
143
+ async def _update_item(self, item_id: str, handler: PersistentHandler) -> None:
144
+ """Update an existing agent data item."""
145
+ update_request = {
146
+ "data": handler.model_dump(mode="json"),
147
+ }
148
+ async with self._get_client() as client:
149
+ response = await client.put(
150
+ f"{self.base_url}/api/v1/beta/agent-data/{item_id}",
151
+ json=update_request,
152
+ )
153
+ response.raise_for_status()
154
+
155
+ async def _delete_item(self, item_id: str) -> None:
156
+ """Delete an agent data item."""
157
+ async with self._get_client() as client:
158
+ response = await client.delete(
159
+ f"{self.base_url}/api/v1/beta/agent-data/{item_id}",
160
+ )
161
+ response.raise_for_status()
92
162
 
93
163
  async def _get_item_id(self, handler: PersistentHandler) -> str | None:
94
164
  cached_id = self.cache.get(handler.handler_id)
95
165
  if cached_id is not None:
96
166
  return cached_id
97
167
  search_filter = {"handler_id": {"eq": handler.handler_id}}
98
- results = await self.client.search(
99
- filter=cast(Any, search_filter),
100
- page_size=1,
101
- )
102
- if not results.items:
168
+ search_request = {
169
+ "deployment_name": self.deployment_name,
170
+ "collection": self.collection,
171
+ "filter": search_filter,
172
+ "page_size": 1,
173
+ }
174
+ async with self._get_client() as client:
175
+ response = await client.post(
176
+ f"{self.base_url}/api/v1/beta/agent-data/:search",
177
+ json=search_request,
178
+ )
179
+ response.raise_for_status()
180
+ data = response.json()
181
+
182
+ items = data.get("items", [])
183
+ if not items:
103
184
  return None
104
- id = results.items[0].id
185
+ id = items[0].get("id")
105
186
  if id is None:
106
187
  return None
107
188
  self.cache.set(handler.handler_id, id)
@@ -121,4 +202,15 @@ class AgentDataStore(AbstractWorkflowStore):
121
202
  filters["status"] = {
122
203
  "includes": query.status_in,
123
204
  }
205
+ if query.is_idle is not None:
206
+ if query.is_idle:
207
+ # Filter for handlers where idle_since is set (any valid datetime)
208
+ filters["idle_since"] = {
209
+ "gte": "1970-01-01T00:00:00Z",
210
+ }
211
+ else:
212
+ # Filter for handlers where idle_since is not set (null)
213
+ filters["idle_since"] = {
214
+ "eq": None,
215
+ }
124
216
  return filters
@@ -1,22 +1,21 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: llama-deploy-appserver
3
- Version: 0.3.26
3
+ Version: 0.4.0
4
4
  Summary: Application server components for LlamaDeploy
5
5
  Author: Massimiliano Pippi, Adrian Lyjak
6
6
  Author-email: Massimiliano Pippi <mpippi@gmail.com>, Adrian Lyjak <adrianlyjak@gmail.com>
7
7
  License: MIT
8
- Requires-Dist: llama-index-workflows[server]>=2.11.3
8
+ Requires-Dist: llama-index-workflows[server]>=2.12.0,<2.13.0
9
9
  Requires-Dist: pydantic-settings>=2.10.1
10
10
  Requires-Dist: fastapi>=0.100.0
11
11
  Requires-Dist: websockets>=12.0
12
- Requires-Dist: llama-deploy-core>=0.3.26,<0.4.0
12
+ Requires-Dist: llama-deploy-core>=0.4.0,<0.5.0
13
13
  Requires-Dist: httpx>=0.24.0,<1.0.0
14
14
  Requires-Dist: prometheus-fastapi-instrumentator>=7.1.0
15
15
  Requires-Dist: packaging>=25.0
16
16
  Requires-Dist: structlog>=25.4.0
17
17
  Requires-Dist: rich>=14.1.0
18
18
  Requires-Dist: pyyaml>=6.0.2
19
- Requires-Dist: llama-cloud-services>=0.6.60
20
19
  Requires-Dist: watchfiles>=1.1.0
21
20
  Requires-Dist: uvicorn>=0.35.0
22
21
  Requires-Dist: typing-extensions>=4.15.0 ; python_full_version < '3.12'
@@ -1,5 +1,5 @@
1
1
  llama_deploy/appserver/__init__.py,sha256=e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855,0
2
- llama_deploy/appserver/app.py,sha256=d0eae058032e0fc86bdc8d778afa58fa49b62835291857e49356362d74d62895,15288
2
+ llama_deploy/appserver/app.py,sha256=d1fedfca2b8755f2356d718c5e6cd5be2307954bf967f569a3ab5cd160fdf47d,15246
3
3
  llama_deploy/appserver/bootstrap.py,sha256=34724cf3056b653b71d1bedab64dbde221d7c47443a2a41032e767d50168a24b,2581
4
4
  llama_deploy/appserver/configure_logging.py,sha256=2431fda77c47d0aef783992b0f01978a3a643768a2e82f10f3c263538f23d800,6361
5
5
  llama_deploy/appserver/correlation_id.py,sha256=8ac5bc6160c707b93a9fb818b64dd369a4ef7a53f9f91a6b3d90c4cf446f7327,572
@@ -16,9 +16,9 @@ llama_deploy/appserver/settings.py,sha256=aa4512d2f1f28b8ee7d3fedc8c61f77bce9f80
16
16
  llama_deploy/appserver/stats.py,sha256=1f3989f6705a6de3e4d61ee8cdd189fbe04a2c53ec5e720b2e5168acc331427f,691
17
17
  llama_deploy/appserver/types.py,sha256=4edc991aafb6b8497f068d12387455df292da3ff8440223637641ab1632553ec,2133
18
18
  llama_deploy/appserver/workflow_loader.py,sha256=c1422bda79423528f1f22fe793c9c43cb411dd883a05a80c5a161f04efd9489e,15713
19
- llama_deploy/appserver/workflow_store/agent_data_store.py,sha256=ecf11a1454b13b7d618e720c8ba3be41833f322fdddfacc8356dfe34858d3a30,4421
19
+ llama_deploy/appserver/workflow_store/agent_data_store.py,sha256=816710c9957c37792ce38e97a2c57cd8079953d55489b445675646ff74b4e13e,7710
20
20
  llama_deploy/appserver/workflow_store/keyed_lock.py,sha256=72bcfafbce56d5b36d53aff764b573c2dca2b3f5bc59f2d8baa80be0e4db6e34,1037
21
21
  llama_deploy/appserver/workflow_store/lru_cache.py,sha256=10b7d69e4be7d929d9dac009b59635b20fbed4603fb004bc35cbdc3ce538af8b,1454
22
- llama_deploy_appserver-0.3.26.dist-info/WHEEL,sha256=66530aef82d5020ef5af27ae0123c71abb9261377c5bc519376c671346b12918,79
23
- llama_deploy_appserver-0.3.26.dist-info/METADATA,sha256=b8715d0a53f227482f01698eb1a45dfbad3e4c1ef379af2d75f592ffa6d4fc41,1155
24
- llama_deploy_appserver-0.3.26.dist-info/RECORD,,
22
+ llama_deploy_appserver-0.4.0.dist-info/WHEEL,sha256=66530aef82d5020ef5af27ae0123c71abb9261377c5bc519376c671346b12918,79
23
+ llama_deploy_appserver-0.4.0.dist-info/METADATA,sha256=41f69121b36ccb0494337a86cf0b83ec247e69ce5c39235cc7c9af0609fff919,1117
24
+ llama_deploy_appserver-0.4.0.dist-info/RECORD,,