zeno-cli 0.3.7__tar.gz → 0.3.8__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 (72) hide show
  1. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/PKG-INFO +1 -1
  2. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_generated/client.py +14 -0
  3. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/pyproject.toml +1 -1
  4. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/_hooks/cc_bridge.py +14 -7
  5. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/login.py +11 -11
  6. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/.gitignore +0 -0
  7. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/README.md +0 -0
  8. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/__init__.py +0 -0
  9. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/_common.py +0 -0
  10. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/anthropic.py +0 -0
  11. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/claude_code.py +0 -0
  12. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/crewai.py +0 -0
  13. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/langgraph.py +0 -0
  14. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_adapters/openai.py +0 -0
  15. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_core/__init__.py +0 -0
  16. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_core/analytics.py +0 -0
  17. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_core/rtlx_s.py +0 -0
  18. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_core/streak.py +0 -0
  19. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_core/tlx_s.py +0 -0
  20. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/__init__.py +0 -0
  21. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_generated/__init__.py +0 -0
  22. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/env.py +0 -0
  23. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/script.py.mako +0 -0
  24. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0001_initial.py +0 -0
  25. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0002_cognition_samples.py +0 -0
  26. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0003_cognition_drivers.py +0 -0
  27. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0004_transcript_intelligence.py +0 -0
  28. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_migrations/alembic.ini +0 -0
  29. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/_runtime.py +0 -0
  30. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/__init__.py +0 -0
  31. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/anthropic.py +0 -0
  32. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/claude_code.py +0 -0
  33. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/crewai.py +0 -0
  34. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/langgraph.py +0 -0
  35. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/adapters/openai.py +0 -0
  36. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/auth.py +0 -0
  37. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/client.py +0 -0
  38. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/config.py +0 -0
  39. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/daemon.py +0 -0
  40. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/privacy.py +0 -0
  41. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/session.py +0 -0
  42. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/storage.py +0 -0
  43. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_sdk/types/__init__.py +0 -0
  44. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/__init__.py +0 -0
  45. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/analytics.py +0 -0
  46. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/compression.py +0 -0
  47. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/ingest.py +0 -0
  48. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/model.py +0 -0
  49. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/parsers/__init__.py +0 -0
  50. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/parsers/claude_code.py +0 -0
  51. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/parsers/codex.py +0 -0
  52. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/parsers/cursor.py +0 -0
  53. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/prices.py +0 -0
  54. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/schema.py +0 -0
  55. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/signals.py +0 -0
  56. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/_vendor_build/zeno_session_intel/taxonomy.py +0 -0
  57. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/data/outreach_suppression.txt +0 -0
  58. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/hatch_build.py +0 -0
  59. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/scripts/install-smoke.sh +0 -0
  60. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/__init__.py +0 -0
  61. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/doctor.py +0 -0
  62. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hook_install.py +0 -0
  63. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hud/__init__.py +0 -0
  64. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hud/hud_install.py +0 -0
  65. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hud/zeno_attention.py +0 -0
  66. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hud/zeno_cognition.py +0 -0
  67. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/hud/zeno_hud.py +0 -0
  68. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/interview_invites.py +0 -0
  69. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/main.py +0 -0
  70. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/onboard.py +0 -0
  71. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/outreach.py +0 -0
  72. {zeno_cli-0.3.7 → zeno_cli-0.3.8}/src/zeno_cli/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zeno-cli
3
- Version: 0.3.7
3
+ Version: 0.3.8
4
4
  Summary: Zeno CLI - measure the supervision cost of AI-assisted work
5
5
  Project-URL: Homepage, https://zeno.center
6
6
  Project-URL: Repository, https://github.com/Marwan01/zeno
@@ -574,6 +574,20 @@ class ZenoApiClient:
574
574
  headers=headers,
575
575
  )
576
576
 
577
+ def capture_recent(self, *, limit: str | None = None) -> dict[str, Any]:
578
+ """GET /v1/capture/recent"""
579
+ query: dict[str, str] | None = None
580
+ headers: dict[str, str] | None = None
581
+ query = {}
582
+ if limit is not None:
583
+ query["limit"] = str(limit)
584
+ return self._request(
585
+ "GET",
586
+ "/v1/capture/recent",
587
+ query=query,
588
+ headers=headers,
589
+ )
590
+
577
591
  def capture_stream(self) -> dict[str, Any]:
578
592
  """GET /v1/capture/stream"""
579
593
  query: dict[str, str] | None = None
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "zeno-cli"
3
- version = "0.3.7"
3
+ version = "0.3.8"
4
4
  description = "Zeno CLI - measure the supervision cost of AI-assisted work"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -279,13 +279,21 @@ def _idempotency_key(body: dict) -> str:
279
279
  return f"{body['device_id']}:{body['session_id']}:{entity}"
280
280
 
281
281
 
282
- def _post_ingest(body: dict, timeout_s: float, token: str | None = None) -> bool:
282
+ # Sentinel for "token not supplied -> resolve it here", distinct from a resolved
283
+ # None ("no token, tailnet path"). Lets _maybe_push pass the once-resolved value
284
+ # (str OR None) down so neither the public nor the Mini path re-reads the keyring
285
+ # per drained line.
286
+ _UNSET = object()
287
+
288
+
289
+ def _post_ingest(body: dict, timeout_s: float, token=_UNSET) -> bool:
283
290
  """POST one ingest body. Returns True on a 2xx, False on any failure. Never
284
291
  raises (all exceptions -> False). urllib + an explicit socket timeout only.
285
292
 
286
293
  ``token`` is the pre-resolved bearer (see _maybe_push); pass it so a drain of
287
294
  many spooled lines does not re-read the OS keyring per line. When omitted
288
- (direct callers/tests) it is resolved once here.
295
+ (_UNSET; direct callers/tests) it is resolved once here. An explicit None means
296
+ "no token" (tailnet path) and is used as-is without re-resolving.
289
297
  """
290
298
  url = _api_base_url() + SYNC_PATH
291
299
  data = json.dumps(body).encode("utf-8")
@@ -296,10 +304,9 @@ def _post_ingest(body: dict, timeout_s: float, token: str | None = None) -> bool
296
304
  # Attach the Clerk bearer token when one is available so the push authenticates
297
305
  # against a public API (Cloud Run). Absent it (tailnet Mini), the push relies on
298
306
  # the identity header the `tailscale serve` proxy injects - unchanged behavior.
299
- if token is None:
300
- token = _api_token()
301
- if token:
302
- headers["Authorization"] = "Bearer " + token
307
+ resolved = _api_token() if token is _UNSET else token
308
+ if resolved:
309
+ headers["Authorization"] = "Bearer " + resolved
303
310
  req = urllib.request.Request(
304
311
  url,
305
312
  data=data,
@@ -348,7 +355,7 @@ def _trim_outbox(path: Path) -> None:
348
355
  _debug(f"trim_outbox failed: {exc}")
349
356
 
350
357
 
351
- def _drain_outbox(timeout_s: float, token: str | None = None) -> None:
358
+ def _drain_outbox(timeout_s: float, token=_UNSET) -> None:
352
359
  """After a live push, best-effort + time-boxed drain of a few spooled lines.
353
360
  Pushes oldest-first; stops at the budget, the line cap, or the first failure
354
361
  (so an offline window doesn't re-spin). Rewrites the outbox with the remainder.
@@ -18,17 +18,17 @@ apps/api/src/zeno_api/auth.py).
18
18
 
19
19
  The security control on the callback today is the CSRF `state` token (browser +
20
20
  loopback, state-CSRF) - NOT PKCE. The bridge returns the token directly in the
21
- redirect; there is no authorization-code-for-token exchange, so a PKCE verifier
22
- would be unused theater. TODO: when the dashboard `/cli/authorize` bridge ships,
23
- implement a real OAuth code-for-token exchange (PKCE S256: send a code_challenge,
24
- receive a short-lived auth code on the callback, then POST code + code_verifier
25
- to the bridge to redeem the JWT) instead of receiving the token in the URL.
26
-
27
- OUT OF SCOPE / FOLLOW-UP: the dashboard `/cli/authorize` bridge page and the
28
- Clerk `zeno-api` JWT template do NOT exist yet. They are the only missing
29
- pieces for an end-to-end login. This module is fully unit-testable without them
30
- because `authorize_url` is injectable (env `ZENO_LOGIN_AUTHORIZE_URL`, flag
31
- `--authorize-url`) and the loopback leg is driven by a fake "browser" in tests.
21
+ redirect to the localhost loopback; there is no authorization-code-for-token
22
+ exchange, so a PKCE verifier would be unused theater. FOLLOW-UP (hardening): a
23
+ real OAuth code-for-token exchange (PKCE S256: send a code_challenge, receive a
24
+ short-lived auth code on the callback, then POST code + code_verifier to the
25
+ bridge to redeem the JWT) instead of receiving the token in the URL.
26
+
27
+ LIVE: the dashboard `/cli/authorize` bridge page (apps/cognition-dashboard) and
28
+ the Clerk `zeno-api` JWT template both exist; `DEFAULT_AUTHORIZE_URL` points at
29
+ the deployed bridge. The module stays fully unit-testable because `authorize_url`
30
+ is injectable (env `ZENO_LOGIN_AUTHORIZE_URL`, flag `--authorize-url`) and the
31
+ loopback leg is driven by a fake "browser" in tests.
32
32
  """
33
33
 
34
34
  from __future__ import annotations
File without changes
File without changes
File without changes
File without changes