langgraph-api 0.2.69__tar.gz → 0.2.70__tar.gz

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.

Potentially problematic release.


This version of langgraph-api might be problematic. Click here for more details.

Files changed (104) hide show
  1. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/PKG-INFO +1 -1
  2. langgraph_api-0.2.70/langgraph_api/__init__.py +1 -0
  3. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/errors.py +6 -0
  4. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/worker.py +60 -86
  5. langgraph_api-0.2.69/langgraph_api/__init__.py +0 -1
  6. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/.gitignore +0 -0
  7. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/LICENSE +0 -0
  8. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/Makefile +0 -0
  9. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/README.md +0 -0
  10. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/benchmark/.gitignore +0 -0
  11. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/benchmark/Makefile +0 -0
  12. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/benchmark/README.md +0 -0
  13. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/benchmark/burst.js +0 -0
  14. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/benchmark/weather.js +0 -0
  15. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/constraints.txt +0 -0
  16. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/forbidden.txt +0 -0
  17. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/healthcheck.py +0 -0
  18. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/__init__.py +0 -0
  19. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/assistants.py +0 -0
  20. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/mcp.py +0 -0
  21. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/meta.py +0 -0
  22. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/openapi.py +0 -0
  23. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/runs.py +0 -0
  24. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/store.py +0 -0
  25. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/threads.py +0 -0
  26. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/api/ui.py +0 -0
  27. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/asgi_transport.py +0 -0
  28. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/asyncio.py +0 -0
  29. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/__init__.py +0 -0
  30. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/custom.py +0 -0
  31. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/langsmith/__init__.py +0 -0
  32. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/langsmith/backend.py +0 -0
  33. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/langsmith/client.py +0 -0
  34. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/middleware.py +0 -0
  35. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/noop.py +0 -0
  36. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/auth/studio_user.py +0 -0
  37. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/cli.py +0 -0
  38. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/command.py +0 -0
  39. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/config.py +0 -0
  40. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/cron_scheduler.py +0 -0
  41. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/graph.py +0 -0
  42. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/http.py +0 -0
  43. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/.gitignore +0 -0
  44. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/.prettierrc +0 -0
  45. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/__init__.py +0 -0
  46. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/base.py +0 -0
  47. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/build.mts +0 -0
  48. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/client.http.mts +0 -0
  49. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/client.mts +0 -0
  50. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/errors.py +0 -0
  51. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/global.d.ts +0 -0
  52. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/package.json +0 -0
  53. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/remote.py +0 -0
  54. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/schema.py +0 -0
  55. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/graph.mts +0 -0
  56. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/load.hooks.mjs +0 -0
  57. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/preload.mjs +0 -0
  58. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/utils/files.mts +0 -0
  59. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/utils/importMap.mts +0 -0
  60. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/utils/pythonSchemas.mts +0 -0
  61. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/src/utils/serde.mts +0 -0
  62. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/sse.py +0 -0
  63. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/tsconfig.json +0 -0
  64. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/ui.py +0 -0
  65. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/js/yarn.lock +0 -0
  66. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/logging.py +0 -0
  67. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/metadata.py +0 -0
  68. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/middleware/__init__.py +0 -0
  69. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/middleware/http_logger.py +0 -0
  70. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/middleware/private_network.py +0 -0
  71. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/middleware/request_id.py +0 -0
  72. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/models/__init__.py +0 -0
  73. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/models/run.py +0 -0
  74. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/patch.py +0 -0
  75. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/queue_entrypoint.py +0 -0
  76. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/route.py +0 -0
  77. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/schema.py +0 -0
  78. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/serde.py +0 -0
  79. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/server.py +0 -0
  80. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/sse.py +0 -0
  81. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/state.py +0 -0
  82. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/store.py +0 -0
  83. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/stream.py +0 -0
  84. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/thread_ttl.py +0 -0
  85. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/tunneling/cloudflare.py +0 -0
  86. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/utils.py +0 -0
  87. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/validation.py +0 -0
  88. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_api/webhook.py +0 -0
  89. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_license/__init__.py +0 -0
  90. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_license/validation.py +0 -0
  91. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/__init__.py +0 -0
  92. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/checkpoint.py +0 -0
  93. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/database.py +0 -0
  94. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/lifespan.py +0 -0
  95. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/metrics.py +0 -0
  96. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/ops.py +0 -0
  97. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/queue.py +0 -0
  98. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/retry.py +0 -0
  99. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/langgraph_runtime/store.py +0 -0
  100. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/logging.json +0 -0
  101. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/openapi.json +0 -0
  102. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/pyproject.toml +0 -0
  103. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/scripts/create_license.py +0 -0
  104. {langgraph_api-0.2.69 → langgraph_api-0.2.70}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langgraph-api
3
- Version: 0.2.69
3
+ Version: 0.2.70
4
4
  Author-email: Nuno Campos <nuno@langchain.dev>, Will Fu-Hinthorn <will@langchain.dev>
5
5
  License: Elastic-2.0
6
6
  License-File: LICENSE
@@ -0,0 +1 @@
1
+ __version__ = "0.2.70"
@@ -50,3 +50,9 @@ class UserInterrupt(Exception):
50
50
  class UserRollback(UserInterrupt):
51
51
  def __init__(self):
52
52
  super().__init__("User requested rollback of the run")
53
+
54
+
55
+ class UserTimeout(Exception):
56
+ def __init__(self, timeout_error: TimeoutError):
57
+ super().__init__(timeout_error)
58
+ self.timeout_error = timeout_error
@@ -16,12 +16,12 @@ from langgraph_api.config import (
16
16
  BG_JOB_MAX_RETRIES,
17
17
  BG_JOB_TIMEOUT_SECS,
18
18
  )
19
- from langgraph_api.errors import UserInterrupt, UserRollback
19
+ from langgraph_api.errors import UserInterrupt, UserRollback, UserTimeout
20
20
  from langgraph_api.js.errors import RemoteException
21
21
  from langgraph_api.metadata import incr_runs
22
22
  from langgraph_api.schema import Run
23
23
  from langgraph_api.state import state_snapshot_to_thread_state
24
- from langgraph_api.stream import astream_state, consume
24
+ from langgraph_api.stream import AnyStream, astream_state, consume
25
25
  from langgraph_api.utils import with_user
26
26
  from langgraph_runtime.database import connect
27
27
  from langgraph_runtime.ops import Runs, Threads
@@ -79,8 +79,11 @@ async def worker(
79
79
  "__request_start_time_ms__"
80
80
  )
81
81
  after_seconds = run["kwargs"]["config"]["configurable"].get("__after_seconds__", 0)
82
+ run_started_at_dt = datetime.now(UTC)
83
+ run_started_at = run_started_at_dt.isoformat()
84
+ run_ended_at_dt: datetime | None = None
82
85
  run_ended_at: str | None = None
83
- run_started_at = datetime.now(UTC)
86
+
84
87
  # Note that "created_at" is inclusive of the `after_seconds`
85
88
  run_creation_ms = (
86
89
  int(
@@ -103,13 +106,13 @@ async def worker(
103
106
  "request_id": _get_request_id(run),
104
107
  }
105
108
  )
106
- run_stream_started_at = datetime.now(UTC)
109
+ run_stream_started_at_dt = datetime.now(UTC)
107
110
  await logger.ainfo(
108
111
  "Starting background run",
109
- run_started_at=run_started_at.isoformat(),
112
+ run_started_at=run_started_at,
110
113
  run_creation_ms=run_creation_ms,
111
- run_queue_ms=ms(run_started_at, run["created_at"]),
112
- run_stream_start_ms=ms(run_stream_started_at, run_started_at),
114
+ run_queue_ms=ms(run_started_at_dt, run["created_at"]),
115
+ run_stream_start_ms=ms(run_stream_started_at_dt, run_started_at_dt),
113
116
  )
114
117
 
115
118
  def on_checkpoint(checkpoint_arg: CheckpointPayload):
@@ -123,6 +126,21 @@ async def worker(
123
126
  task.update(task_result)
124
127
  break
125
128
 
129
+ # Wrap the graph execution to separate user errors from server errors
130
+ async def wrap_user_errors(stream: AnyStream, run_id: str, resumable: bool):
131
+ try:
132
+ await consume(stream, run_id, resumable)
133
+ except Exception as e:
134
+ logger.info(
135
+ f"Run encountered an error in graph: {type(e)}({e})",
136
+ exc_info=e,
137
+ )
138
+ # TimeoutError is a special case where we rely on asyncio.wait_for to timeout runs
139
+ # Convert user TimeoutErrors to a custom class so we can distinguish and later convert back
140
+ if isinstance(e, TimeoutError):
141
+ raise UserTimeout(e) from e
142
+ raise
143
+
126
144
  async with Runs.enter(run_id, main_loop) as done:
127
145
  # attempt the run
128
146
  try:
@@ -163,25 +181,9 @@ async def worker(
163
181
  on_task_result=on_task_result,
164
182
  )
165
183
  await asyncio.wait_for(
166
- consume(stream, run_id, resumable),
184
+ wrap_user_errors(stream, run_id, resumable),
167
185
  BG_JOB_TIMEOUT_SECS,
168
186
  )
169
- run_ended_at_dt = datetime.now(UTC)
170
- run_ended_at = run_ended_at_dt.isoformat()
171
- await logger.ainfo(
172
- "Background run succeeded",
173
- run_id=str(run_id),
174
- run_attempt=attempt,
175
- run_created_at=run_created_at,
176
- run_started_at=run_started_at.isoformat(),
177
- run_ended_at=run_ended_at,
178
- run_exec_ms=ms(run_ended_at_dt, run_started_at),
179
- run_completed_in_ms=(
180
- int((run_ended_at_dt.timestamp() * 1_000) - request_created_at)
181
- if request_created_at is not None
182
- else None
183
- ),
184
- )
185
187
  except (Exception, asyncio.CancelledError) as ee:
186
188
  exception = ee
187
189
  except BaseException as eee:
@@ -192,11 +194,33 @@ async def worker(
192
194
  exception=str(eee),
193
195
  )
194
196
  raise
197
+ finally:
198
+ run_ended_at_dt = datetime.now(UTC)
199
+ run_ended_at = run_ended_at_dt.isoformat()
195
200
 
196
201
  # handle exceptions and set status
197
202
  async with connect() as conn:
203
+ log_info = {
204
+ "run_id": str(run_id),
205
+ "run_attempt": attempt,
206
+ "run_created_at": run_created_at,
207
+ "run_started_at": run_started_at,
208
+ "run_ended_at": run_ended_at,
209
+ "run_exec_ms": ms(run_ended_at_dt, run_started_at_dt),
210
+ "run_completed_in_ms": (
211
+ int((run_ended_at_dt.timestamp() * 1_000) - request_created_at)
212
+ if request_created_at is not None
213
+ else None
214
+ ),
215
+ }
216
+
198
217
  if exception is None:
199
218
  status = "success"
219
+
220
+ await logger.ainfo(
221
+ "Background run succeeded",
222
+ **log_info,
223
+ )
200
224
  # If a stateful run succeeded but no checkpoint was returned, likely
201
225
  # there was a retriable exception that resumed right at the end
202
226
  if checkpoint is None and not temporary:
@@ -222,56 +246,28 @@ async def worker(
222
246
  )
223
247
  elif isinstance(exception, TimeoutError):
224
248
  status = "timeout"
225
- run_ended_at = datetime.now(UTC).isoformat()
226
249
  await logger.awarning(
227
250
  "Background run timed out",
228
- run_id=str(run_id),
229
- run_attempt=attempt,
230
- run_created_at=run_created_at,
231
- run_started_at=run_started_at.isoformat(),
232
- run_ended_at=run_ended_at,
233
- run_exec_ms=ms(datetime.now(UTC), run_started_at),
234
- run_completed_in_ms=(
235
- int((run_ended_at_dt.timestamp() * 1_000) - request_created_at)
236
- if request_created_at is not None
237
- else None
238
- ),
251
+ **log_info,
239
252
  )
240
253
  await Threads.set_joint_status(
241
254
  conn, run["thread_id"], run_id, status, checkpoint=checkpoint
242
255
  )
243
256
  elif isinstance(exception, UserRollback):
244
257
  status = "rollback"
245
- run_ended_at_dt = datetime.now(UTC)
246
- run_ended_at = run_ended_at_dt.isoformat()
247
258
  try:
248
259
  await Threads.set_joint_status(
249
260
  conn, run["thread_id"], run_id, status, checkpoint=checkpoint
250
261
  )
251
262
  await logger.ainfo(
252
263
  "Background run rolled back",
253
- run_id=str(run_id),
254
- run_attempt=attempt,
255
- run_created_at=run_created_at,
256
- run_started_at=run_started_at.isoformat(),
257
- run_ended_at=run_ended_at,
258
- run_exec_ms=ms(run_ended_at_dt, run_started_at),
259
- run_completed_in_ms=(
260
- int(
261
- (run_ended_at_dt.timestamp() * 1_000)
262
- - request_created_at
263
- )
264
- if request_created_at is not None
265
- else None
266
- ),
264
+ **log_info,
267
265
  )
268
266
  except HTTPException as e:
269
267
  if e.status_code == 404:
270
268
  await logger.ainfo(
271
269
  "Ignoring rollback error for missing run",
272
- run_id=str(run_id),
273
- run_attempt=attempt,
274
- run_created_at=run_created_at,
270
+ **log_info,
275
271
  )
276
272
  else:
277
273
  raise
@@ -279,54 +275,32 @@ async def worker(
279
275
  checkpoint = None # reset the checkpoint
280
276
  elif isinstance(exception, UserInterrupt):
281
277
  status = "interrupted"
282
- run_ended_at_dt = datetime.now(UTC)
283
- run_ended_at = run_ended_at_dt.isoformat()
284
278
  await logger.ainfo(
285
279
  "Background run interrupted",
286
- run_id=str(run_id),
287
- run_attempt=attempt,
288
- run_created_at=run_created_at,
289
- run_started_at=run_started_at.isoformat(),
290
- run_ended_at=run_ended_at,
291
- run_exec_ms=ms(run_ended_at_dt, run_started_at),
292
- run_completed_in_ms=(
293
- int((run_ended_at_dt.timestamp() * 1_000) - request_created_at)
294
- if request_created_at is not None
295
- else None
296
- ),
280
+ **log_info,
297
281
  )
298
282
  await Threads.set_joint_status(
299
283
  conn, run["thread_id"], run_id, status, checkpoint, exception
300
284
  )
301
285
  elif isinstance(exception, ALL_RETRIABLE_EXCEPTIONS):
302
286
  status = "retry"
303
- run_ended_at_dt = datetime.now(UTC)
304
- run_ended_at = run_ended_at_dt.isoformat()
305
287
  await logger.awarning(
306
288
  f"Background run failed, will retry. Exception: {type(exception)}({exception})",
307
- exc_info=True,
308
- run_id=str(run_id),
309
- run_attempt=attempt,
310
- run_created_at=run_created_at,
311
- run_started_at=run_started_at.isoformat(),
312
- run_ended_at=run_ended_at,
313
- run_exec_ms=ms(run_ended_at_dt, run_started_at),
289
+ **log_info,
314
290
  )
315
291
  # Don't update thread status yet.
316
292
  await Runs.set_status(conn, run_id, "pending")
317
293
  else:
318
294
  status = "error"
319
- run_ended_at_dt = datetime.now(UTC)
320
- run_ended_at = run_ended_at_dt.isoformat()
295
+
296
+ # Convert UserTimeout to TimeoutError for customers
297
+ if isinstance(exception, UserTimeout):
298
+ exception = exception.timeout_error
299
+
321
300
  await logger.aexception(
322
301
  f"Background run failed. Exception: {type(exception)}({exception})",
323
302
  exc_info=not isinstance(exception, RemoteException),
324
- run_id=str(run_id),
325
- run_attempt=attempt,
326
- run_created_at=run_created_at,
327
- run_started_at=run_started_at.isoformat(),
328
- run_ended_at=run_ended_at,
329
- run_exec_ms=ms(run_ended_at_dt, run_started_at),
303
+ **log_info,
330
304
  )
331
305
  await Threads.set_joint_status(
332
306
  conn, run["thread_id"], run_id, status, checkpoint, exception
@@ -363,7 +337,7 @@ async def worker(
363
337
  exception=exception,
364
338
  run=run,
365
339
  webhook=webhook,
366
- run_started_at=run_started_at.isoformat(),
340
+ run_started_at=run_started_at,
367
341
  run_ended_at=run_ended_at,
368
342
  )
369
343
 
@@ -1 +0,0 @@
1
- __version__ = "0.2.69"
File without changes
File without changes
File without changes
File without changes