zeno-cli 0.3.5__tar.gz → 0.3.7__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.
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/PKG-INFO +1 -1
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/pyproject.toml +1 -1
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/_hooks/cc_bridge.py +21 -10
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/login.py +1 -1
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/main.py +2 -2
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/.gitignore +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/README.md +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/_common.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/anthropic.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/claude_code.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/crewai.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/langgraph.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_adapters/openai.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_core/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_core/analytics.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_core/rtlx_s.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_core/streak.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_core/tlx_s.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_generated/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_generated/client.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/env.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/script.py.mako +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0001_initial.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0002_cognition_samples.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0003_cognition_drivers.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic/versions/0004_transcript_intelligence.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_migrations/alembic.ini +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/_runtime.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/anthropic.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/claude_code.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/crewai.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/langgraph.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/adapters/openai.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/auth.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/client.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/config.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/daemon.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/privacy.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/session.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/storage.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_sdk/types/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/analytics.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/compression.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/ingest.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/model.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/parsers/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/parsers/claude_code.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/parsers/codex.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/parsers/cursor.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/prices.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/schema.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/signals.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/_vendor_build/zeno_session_intel/taxonomy.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/data/outreach_suppression.txt +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/hatch_build.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/scripts/install-smoke.sh +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/doctor.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hook_install.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hud/__init__.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hud/hud_install.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hud/zeno_attention.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hud/zeno_cognition.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/hud/zeno_hud.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/interview_invites.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/onboard.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/outreach.py +0 -0
- {zeno_cli-0.3.5 → zeno_cli-0.3.7}/src/zeno_cli/version.py +0 -0
|
@@ -197,8 +197,8 @@ def _api_base_url() -> str:
|
|
|
197
197
|
def _api_token() -> str | None:
|
|
198
198
|
"""Bearer token for the capture push, when one is available.
|
|
199
199
|
|
|
200
|
-
Checks the explicit env var first (
|
|
201
|
-
|
|
200
|
+
Checks the explicit env var first (same precedence as the CLI's
|
|
201
|
+
resolve_api_token), then the keyring slot `zeno login` writes (service "zeno-sdk",
|
|
202
202
|
key "clerk_jwt"). The keyring lookup is best-effort: keyring is an optional
|
|
203
203
|
dependency and may be absent under the system python the hook runs on.
|
|
204
204
|
Returns None on the tailnet Mini, where identity comes from a header the
|
|
@@ -279,9 +279,14 @@ 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) -> bool:
|
|
282
|
+
def _post_ingest(body: dict, timeout_s: float, token: str | None = None) -> bool:
|
|
283
283
|
"""POST one ingest body. Returns True on a 2xx, False on any failure. Never
|
|
284
|
-
raises (all exceptions -> False). urllib + an explicit socket timeout only.
|
|
284
|
+
raises (all exceptions -> False). urllib + an explicit socket timeout only.
|
|
285
|
+
|
|
286
|
+
``token`` is the pre-resolved bearer (see _maybe_push); pass it so a drain of
|
|
287
|
+
many spooled lines does not re-read the OS keyring per line. When omitted
|
|
288
|
+
(direct callers/tests) it is resolved once here.
|
|
289
|
+
"""
|
|
285
290
|
url = _api_base_url() + SYNC_PATH
|
|
286
291
|
data = json.dumps(body).encode("utf-8")
|
|
287
292
|
headers = {
|
|
@@ -291,7 +296,8 @@ def _post_ingest(body: dict, timeout_s: float) -> bool:
|
|
|
291
296
|
# Attach the Clerk bearer token when one is available so the push authenticates
|
|
292
297
|
# against a public API (Cloud Run). Absent it (tailnet Mini), the push relies on
|
|
293
298
|
# the identity header the `tailscale serve` proxy injects - unchanged behavior.
|
|
294
|
-
token
|
|
299
|
+
if token is None:
|
|
300
|
+
token = _api_token()
|
|
295
301
|
if token:
|
|
296
302
|
headers["Authorization"] = "Bearer " + token
|
|
297
303
|
req = urllib.request.Request(
|
|
@@ -342,10 +348,11 @@ def _trim_outbox(path: Path) -> None:
|
|
|
342
348
|
_debug(f"trim_outbox failed: {exc}")
|
|
343
349
|
|
|
344
350
|
|
|
345
|
-
def _drain_outbox(timeout_s: float) -> None:
|
|
351
|
+
def _drain_outbox(timeout_s: float, token: str | None = None) -> None:
|
|
346
352
|
"""After a live push, best-effort + time-boxed drain of a few spooled lines.
|
|
347
353
|
Pushes oldest-first; stops at the budget, the line cap, or the first failure
|
|
348
|
-
(so an offline window doesn't re-spin). Rewrites the outbox with the remainder.
|
|
354
|
+
(so an offline window doesn't re-spin). Rewrites the outbox with the remainder.
|
|
355
|
+
``token`` is threaded to _post_ingest so the keyring is read once per drain."""
|
|
349
356
|
path = _outbox_path()
|
|
350
357
|
try:
|
|
351
358
|
if not path.exists():
|
|
@@ -367,7 +374,7 @@ def _drain_outbox(timeout_s: float) -> None:
|
|
|
367
374
|
except Exception:
|
|
368
375
|
consumed += 1 # unparseable - drop it, keep draining
|
|
369
376
|
continue
|
|
370
|
-
if not _post_ingest(body, timeout_s):
|
|
377
|
+
if not _post_ingest(body, timeout_s, token):
|
|
371
378
|
break # stop on first failure; leave this line + the rest spooled
|
|
372
379
|
consumed += 1
|
|
373
380
|
if consumed == 0:
|
|
@@ -403,8 +410,12 @@ def _maybe_push(event: str, payload: dict) -> None:
|
|
|
403
410
|
if body is None:
|
|
404
411
|
return
|
|
405
412
|
timeout_s = _sync_timeout_s()
|
|
406
|
-
|
|
407
|
-
|
|
413
|
+
# Resolve the bearer ONCE per hook invocation (an OS keyring read is not
|
|
414
|
+
# bounded by the socket timeout); thread it through the drain so a
|
|
415
|
+
# multi-line drain never re-reads the keyring on the hot Stop path.
|
|
416
|
+
token = _api_token()
|
|
417
|
+
if _post_ingest(body, timeout_s, token):
|
|
418
|
+
_drain_outbox(timeout_s, token)
|
|
408
419
|
else:
|
|
409
420
|
_spool(body)
|
|
410
421
|
except Exception as exc: # network/build path must never break the hook
|
|
@@ -49,7 +49,7 @@ from zeno_sdk import auth
|
|
|
49
49
|
# default for the argparse default (so the hot `zeno status` path does not
|
|
50
50
|
# import this module just to build the parser).
|
|
51
51
|
DEFAULT_AUTHORIZE_URL = os.environ.get(
|
|
52
|
-
"ZENO_LOGIN_AUTHORIZE_URL", "https://
|
|
52
|
+
"ZENO_LOGIN_AUTHORIZE_URL", "https://demo.zeno.center/cli/authorize"
|
|
53
53
|
)
|
|
54
54
|
|
|
55
55
|
|
|
@@ -46,7 +46,7 @@ DEFAULT_API_BASE_URL = os.environ.get(
|
|
|
46
46
|
# hot `zeno status` path - which builds the full parser - does not have to
|
|
47
47
|
# import the login module (http.server / webbrowser) just to set a default.
|
|
48
48
|
DEFAULT_AUTHORIZE_URL = os.environ.get(
|
|
49
|
-
"ZENO_LOGIN_AUTHORIZE_URL", "https://
|
|
49
|
+
"ZENO_LOGIN_AUTHORIZE_URL", "https://demo.zeno.center/cli/authorize"
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
|
|
@@ -345,7 +345,7 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
345
345
|
default=DEFAULT_AUTHORIZE_URL,
|
|
346
346
|
help=(
|
|
347
347
|
"Dashboard CLI-authorize bridge URL (default: ZENO_LOGIN_AUTHORIZE_URL "
|
|
348
|
-
"or https://
|
|
348
|
+
"or https://demo.zeno.center/cli/authorize)."
|
|
349
349
|
),
|
|
350
350
|
)
|
|
351
351
|
login_p.add_argument(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|