pocketshell 0.4.11__tar.gz → 0.4.13__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 (57) hide show
  1. {pocketshell-0.4.11 → pocketshell-0.4.13}/PKG-INFO +1 -1
  2. {pocketshell-0.4.11 → pocketshell-0.4.13}/pyproject.toml +1 -1
  3. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/agents.py +47 -15
  4. pocketshell-0.4.13/src/pocketshell/cards.py +663 -0
  5. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/cli.py +5 -0
  6. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/tree.py +23 -0
  7. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_agents.py +166 -2
  8. pocketshell-0.4.13/tests/test_cards.py +391 -0
  9. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_tree.py +31 -1
  10. {pocketshell-0.4.11 → pocketshell-0.4.13}/uv.lock +2 -2
  11. {pocketshell-0.4.11 → pocketshell-0.4.13}/.gitignore +0 -0
  12. {pocketshell-0.4.11 → pocketshell-0.4.13}/README.md +0 -0
  13. {pocketshell-0.4.11 → pocketshell-0.4.13}/scheduler/README.md +0 -0
  14. {pocketshell-0.4.11 → pocketshell-0.4.13}/scheduler/pocketshell-usage-capture.service +0 -0
  15. {pocketshell-0.4.11 → pocketshell-0.4.13}/scheduler/pocketshell-usage-capture.timer +0 -0
  16. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/__init__.py +0 -0
  17. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/__main__.py +0 -0
  18. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/agent_log.py +0 -0
  19. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/agents_kind.py +0 -0
  20. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/cgroup_agents.py +0 -0
  21. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/daemon.py +0 -0
  22. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/env.py +0 -0
  23. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/github.py +0 -0
  24. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/hooks.py +0 -0
  25. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/jobs.py +0 -0
  26. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/logs.py +0 -0
  27. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/profiles.py +0 -0
  28. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/prune_attachments.py +0 -0
  29. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/push.py +0 -0
  30. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/qr_share.py +0 -0
  31. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/repos.py +0 -0
  32. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/resume.py +0 -0
  33. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/sessions.py +0 -0
  34. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/usage.py +0 -0
  35. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/usage_capture.py +0 -0
  36. {pocketshell-0.4.11 → pocketshell-0.4.13}/src/pocketshell/usage_reset.py +0 -0
  37. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/__init__.py +0 -0
  38. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_agent_log.py +0 -0
  39. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_agents_kind.py +0 -0
  40. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_cgroup_agents.py +0 -0
  41. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_cli.py +0 -0
  42. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_daemon.py +0 -0
  43. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_env.py +0 -0
  44. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_github.py +0 -0
  45. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_hooks.py +0 -0
  46. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_jobs.py +0 -0
  47. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_logs.py +0 -0
  48. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_profiles.py +0 -0
  49. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_prune_attachments.py +0 -0
  50. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_push.py +0 -0
  51. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_qr_share.py +0 -0
  52. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_repos.py +0 -0
  53. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_resume.py +0 -0
  54. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_sessions.py +0 -0
  55. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_usage.py +0 -0
  56. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_usage_capture.py +0 -0
  57. {pocketshell-0.4.11 → pocketshell-0.4.13}/tests/test_usage_reset.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pocketshell
3
- Version: 0.4.11
3
+ Version: 0.4.13
4
4
  Summary: Unified server-side Python utility for the PocketShell Android client.
5
5
  Project-URL: Homepage, https://github.com/alexeygrigorev/pocketshell
6
6
  Project-URL: Issues, https://github.com/alexeygrigorev/pocketshell/issues
@@ -8,7 +8,7 @@ name = "pocketshell"
8
8
  # scripts/check-pypi-version.sh enforces this; .github/workflows/build.yml
9
9
  # runs that check before publishing to PyPI. See
10
10
  # tools/pocketshell/README.md ("Release flow") for the bump procedure.
11
- version = "0.4.11"
11
+ version = "0.4.13"
12
12
  description = "Unified server-side Python utility for the PocketShell Android client."
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.11"
@@ -359,6 +359,7 @@ def record_agent_kind(
359
359
  kind: str,
360
360
  env: Optional[dict[str, str]] = None,
361
361
  runner=None,
362
+ profile: Optional[str] = None,
362
363
  ) -> bool:
363
364
  """Record the launched agent ``kind`` as a per-session tmux user option.
364
365
 
@@ -371,10 +372,20 @@ def record_agent_kind(
371
372
  change. The client reads it back through its session enumeration
372
373
  (``tmux list-sessions -F '…#{@ps_agent_kind}'``).
373
374
 
374
- The option is session-scoped (not global): ``tmux set-option`` without
375
+ ``profile`` (issue #858) is the human label of the *non-default* profile
376
+ the agent was launched with — e.g. ``"Claude (Z.AI)"`` for a z.ai Claude
377
+ session, so the tree can distinguish it from a default Anthropic Claude.
378
+ It is the same launch-time-recordable dimension as the kind (the selected
379
+ profile name is known here, before ``os.execvpe``; #826 record-at-start
380
+ hard-cut — no detection/parse path). When set, it is written as the
381
+ per-session ``@ps_agent_profile`` user option alongside ``@ps_agent_kind``.
382
+ A default / no-profile launch passes ``None`` and writes NO profile
383
+ option, so a default session carries no spurious profile label.
384
+
385
+ The options are session-scoped (not global): ``tmux set-option`` without
375
386
  ``-g`` sets it on the current session, which is the session the agent
376
387
  was launched into. tmux session options persist for the life of the
377
- session, so the recorded kind survives reconnect / app restart /
388
+ session, so the recorded kind/profile survives reconnect / app restart /
378
389
  app-kill / reinstall — exactly the durability the epic requires.
379
390
 
380
391
  No-op (returns ``False``) when not running inside tmux (``$TMUX``
@@ -399,6 +410,13 @@ def record_agent_kind(
399
410
  ["tmux", "set-option", "@ps_agent_kind", kind],
400
411
  check=False,
401
412
  )
413
+ if profile:
414
+ # Only a non-default profile is recorded; a default/no-profile
415
+ # launch writes no option so the tree shows the plain kind.
416
+ runner(
417
+ ["tmux", "set-option", "@ps_agent_profile", profile],
418
+ check=False,
419
+ )
402
420
  except Exception:
403
421
  # Recording the kind is best-effort; never block the launch on it.
404
422
  return False
@@ -413,6 +431,7 @@ def launch_agent(
413
431
  skip_permissions: bool,
414
432
  config_dir: Optional[str],
415
433
  extra_env: Optional[dict[str, str]] = None,
434
+ profile: Optional[str] = None,
416
435
  execvpe=None,
417
436
  record_kind=None,
418
437
  ) -> None:
@@ -422,6 +441,11 @@ def launch_agent(
422
441
  #732); it layers onto the launch environment under the #703 provider
423
442
  strip (see :func:`build_env`).
424
443
 
444
+ ``profile`` (issue #858) is the human label of the *non-default* profile
445
+ the launch used (``None`` for the engine default). It is recorded
446
+ alongside the kind as the ``@ps_agent_profile`` tmux user option so the
447
+ session tree can distinguish e.g. a z.ai Claude from a default Claude.
448
+
425
449
  ``execvpe`` is injected so tests can assert the exact call without
426
450
  actually replacing the process. When ``None`` (production) it resolves
427
451
  to :func:`os.execvpe` *at call time* — looking it up on the module's
@@ -473,7 +497,7 @@ def launch_agent(
473
497
  # this process (epic #821 Workstream A). Use this wrapper's own
474
498
  # environment (os.environ) for the TMUX detection — `env` is the
475
499
  # provider-stripped launch env that does not necessarily carry $TMUX.
476
- record_kind(kind, dict(os.environ))
500
+ record_kind(kind, dict(os.environ), profile=profile)
477
501
 
478
502
  # Replace this process with the agent so it owns the pty cleanly.
479
503
  execvpe(argv[0], argv, env)
@@ -484,17 +508,21 @@ def _resolve_config_dir(
484
508
  kind: str,
485
509
  config_dir: Optional[str],
486
510
  profile: Optional[str],
487
- ) -> tuple[Optional[str], dict[str, str]]:
488
- """Resolve config dir + extra env from ``--config-dir`` / ``--profile``.
511
+ ) -> tuple[Optional[str], dict[str, str], Optional[str]]:
512
+ """Resolve config dir + extra env + profile label from the launch flags.
489
513
 
490
- Returns ``(config_dir, extra_env)``. ``--config-dir`` and ``--profile``
491
- are mutually exclusive (passing both is an error). When ``--profile`` is
492
- given, it resolves the named host profile (via
514
+ Returns ``(config_dir, extra_env, profile_label)``. ``--config-dir`` and
515
+ ``--profile`` are mutually exclusive (passing both is an error). When
516
+ ``--profile`` is given, it resolves the named host profile (via
493
517
  :func:`pocketshell.profiles.resolve_profile`) to its ``config_dir`` AND
494
- its ``env:`` block (issue #732) — an unknown profile is a clear error. A
495
- default profile resolves to ``None`` config dir (the engine's built-in
496
- location); ``--config-dir`` carries no profile env. Omitting both flags
497
- returns ``(None, {})``.
518
+ its ``env:`` block (issue #732) — an unknown profile is a clear error.
519
+
520
+ ``profile_label`` (issue #858) is the resolved profile's human ``name``
521
+ for a *non-default* profile (e.g. ``"Claude (Z.AI)"``), so the session
522
+ tree can tell a z.ai Claude apart from a default Claude. The engine's
523
+ default profile, ``--config-dir`` (which carries no named profile), and
524
+ omitting both flags all resolve ``profile_label`` to ``None`` — so a
525
+ default session records no ``@ps_agent_profile`` option.
498
526
  """
499
527
  if config_dir is not None and profile is not None:
500
528
  click.echo(
@@ -504,7 +532,7 @@ def _resolve_config_dir(
504
532
  )
505
533
  ctx.exit(2)
506
534
  if profile is None:
507
- return config_dir, {}
535
+ return config_dir, {}, None
508
536
 
509
537
  # Lazy import keeps the agent launch path from importing yaml unless a
510
538
  # profile is actually requested.
@@ -519,7 +547,10 @@ def _resolve_config_dir(
519
547
  err=True,
520
548
  )
521
549
  ctx.exit(2)
522
- return resolved.config_dir, dict(resolved.env)
550
+ # Only a non-default profile is surfaced as a label; the default profile
551
+ # is the plain kind (no spurious chip in the tree).
552
+ label = None if resolved.default else resolved.name
553
+ return resolved.config_dir, dict(resolved.env), label
523
554
 
524
555
 
525
556
  def _make_agent_command(kind: str):
@@ -575,7 +606,7 @@ def _make_agent_command(kind: str):
575
606
  config_dir: Optional[str],
576
607
  profile: Optional[str],
577
608
  ) -> None:
578
- config_dir, extra_env = _resolve_config_dir(
609
+ config_dir, extra_env, profile_label = _resolve_config_dir(
579
610
  ctx, kind, config_dir, profile
580
611
  )
581
612
  launch_agent(
@@ -585,6 +616,7 @@ def _make_agent_command(kind: str):
585
616
  skip_permissions=skip_permissions,
586
617
  config_dir=config_dir,
587
618
  extra_env=extra_env,
619
+ profile=profile_label,
588
620
  )
589
621
 
590
622
  return _cmd