batchwork-ai 0.2.0__tar.gz → 0.2.2__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.
Files changed (59) hide show
  1. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/PKG-INFO +1 -1
  2. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/pyproject.toml +1 -1
  3. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_human.py +23 -8
  4. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/shared.py +6 -1
  5. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/LICENSE +0 -0
  6. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/README.md +0 -0
  7. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/__init__.py +0 -0
  8. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_anthropic_serialization.py +0 -0
  9. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_bounded_json.py +0 -0
  10. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_compatible_media.py +0 -0
  11. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_google_schema.py +0 -0
  12. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_google_serialization.py +0 -0
  13. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_limits.py +0 -0
  14. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_network.py +0 -0
  15. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_provider_failure.py +0 -0
  16. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_serialization.py +0 -0
  17. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_text_validation.py +0 -0
  18. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/_typing.py +0 -0
  19. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/body.py +0 -0
  20. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/__init__.py +0 -0
  21. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_commands.py +0 -0
  22. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_config.py +0 -0
  23. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_contract.py +0 -0
  24. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_failures.py +0 -0
  25. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_input.py +0 -0
  26. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_lifecycle.py +0 -0
  27. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_materialize.py +0 -0
  28. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_output.py +0 -0
  29. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_registry.py +0 -0
  30. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_state.py +0 -0
  31. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_submit_text.py +0 -0
  32. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/cli/_volume.py +0 -0
  33. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/client.py +0 -0
  34. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/errors.py +0 -0
  35. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/job.py +0 -0
  36. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/media.py +0 -0
  37. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/__init__.py +0 -0
  38. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/_image.py +0 -0
  39. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/adapter.py +0 -0
  40. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/anthropic.py +0 -0
  41. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/google.py +0 -0
  42. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/groq.py +0 -0
  43. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/ids.py +0 -0
  44. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/mistral.py +0 -0
  45. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/openai.py +0 -0
  46. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/openai_compatible.py +0 -0
  47. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/together.py +0 -0
  48. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/providers/xai.py +0 -0
  49. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/py.typed +0 -0
  50. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/server/__init__.py +0 -0
  51. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/server/models.py +0 -0
  52. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/server/poller.py +0 -0
  53. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/server/signing.py +0 -0
  54. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/server/transport.py +0 -0
  55. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/stores/__init__.py +0 -0
  56. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/stores/base.py +0 -0
  57. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/stores/memory.py +0 -0
  58. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/stores/redis.py +0 -0
  59. {batchwork_ai-0.2.0 → batchwork_ai-0.2.2}/src/batchwork/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batchwork-ai
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Unified async batch API for AI providers
5
5
  Keywords: ai,anthropic,batch,gemini,llm,openai
6
6
  Author: Ajanraj
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "batchwork-ai"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Unified async batch API for AI providers"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -7,6 +7,7 @@ import re
7
7
  import shutil
8
8
  import sys
9
9
  from collections.abc import Sequence
10
+ from datetime import UTC, datetime
10
11
  from pathlib import Path
11
12
  from typing import TYPE_CHECKING, TextIO
12
13
  from urllib.parse import urlsplit, urlunsplit
@@ -287,6 +288,12 @@ def human_error(error: ErrorDetail) -> str:
287
288
  return f"Error [{error.code}]\n {message}{guidance}{recovery}\n"
288
289
 
289
290
 
291
+ def _table_time(value: datetime | None) -> str:
292
+ if value is None:
293
+ return "-"
294
+ return value.astimezone(UTC).strftime("%Y-%m-%d %H:%MZ")
295
+
296
+
290
297
  def human_table(records: Sequence[RegistryJob], *, width: int | None = None) -> str:
291
298
  if not records:
292
299
  return "No local jobs.\n"
@@ -298,11 +305,13 @@ def human_table(records: Sequence[RegistryJob], *, width: int | None = None) ->
298
305
  blocks.append(
299
306
  "\n".join(
300
307
  (
301
- f"Selector {job.name or job.record_id}",
302
- f"Record {job.record_id or '-'}",
303
- f"Provider {job.provider.value}",
304
- f"Status {job.status.value if job.status else '-'}",
305
- f"Direct {job.provider_reference}",
308
+ f"Selector {job.name or job.record_id}",
309
+ f"Record {job.record_id or '-'}",
310
+ f"Provider {job.provider.value}",
311
+ f"Status {job.status.value if job.status else '-'}",
312
+ f"Submitted {_table_time(job.provider_created_at or job.registered_at)}",
313
+ f"Completed {_table_time(job.completed_at or job.terminal_at)}",
314
+ f"Direct {job.provider_reference}",
306
315
  )
307
316
  )
308
317
  )
@@ -312,8 +321,11 @@ def human_table(records: Sequence[RegistryJob], *, width: int | None = None) ->
312
321
  len("SELECTOR"),
313
322
  *(len(record.job.name or record.job.record_id or "") for record in records),
314
323
  )
315
- selector_width = min(selector_width, max(16, terminal_width - 82))
316
- lines = [f"{'SELECTOR':<{selector_width}} {'RECORD':<35} PROVIDER STATUS DIRECT"]
324
+ selector_width = min(selector_width, max(16, terminal_width - 120))
325
+ lines = [
326
+ f"{'SELECTOR':<{selector_width}} {'RECORD':<35} PROVIDER STATUS "
327
+ f"{'SUBMITTED':<17} {'COMPLETED':<17} DIRECT"
328
+ ]
317
329
  for record in records:
318
330
  job = record.job
319
331
  selector = job.name or job.record_id or job.provider_reference
@@ -321,7 +333,10 @@ def human_table(records: Sequence[RegistryJob], *, width: int | None = None) ->
321
333
  lines.append(
322
334
  f"{selector:<{selector_width}} {(job.record_id or '-'):<35} "
323
335
  f"{job.provider.value:<9} "
324
- f"{(job.status.value if job.status else '-'):<11} {job.provider_reference}"
336
+ f"{(job.status.value if job.status else '-'):<11} "
337
+ f"{_table_time(job.provider_created_at or job.registered_at):<17} "
338
+ f"{_table_time(job.completed_at or job.terminal_at):<17} "
339
+ f"{job.provider_reference}"
325
340
  )
326
341
  return "\n".join(lines) + "\n"
327
342
 
@@ -164,9 +164,14 @@ async def _bounded_response(response: httpx.Response, method: str, url: str) ->
164
164
  protocol_failure(response),
165
165
  )
166
166
  content.extend(chunk)
167
+ # aiter_bytes() already decoded any content-encoding, so the rebuilt
168
+ # response must not advertise the original encoding or stale length.
169
+ headers = httpx.Headers(response.headers)
170
+ headers.pop("content-encoding", None)
171
+ headers.pop("content-length", None)
167
172
  return httpx.Response(
168
173
  response.status_code,
169
- headers=response.headers,
174
+ headers=headers,
170
175
  content=bytes(content),
171
176
  request=response.request,
172
177
  extensions=response.extensions,
File without changes
File without changes