agent-toggle 0.7.2__tar.gz → 0.7.3__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 (85) hide show
  1. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/PKG-INFO +5 -1
  2. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/README.md +4 -0
  3. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/__init__.py +1 -1
  4. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/backends/plugin_cli.py +2 -1
  5. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/picker.py +21 -12
  6. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/PKG-INFO +5 -1
  7. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_picker.py +13 -0
  8. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_platform.py +12 -0
  9. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/LICENSE +0 -0
  10. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/__main__.py +0 -0
  11. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/backends/__init__.py +0 -0
  12. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/backends/flag_json.py +0 -0
  13. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/backends/mcp_json.py +0 -0
  14. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/backends/mcp_toml.py +0 -0
  15. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/cli.py +0 -0
  16. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/companions.py +0 -0
  17. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/config.py +0 -0
  18. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/cost.py +0 -0
  19. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/doctor.py +0 -0
  20. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/fs.py +0 -0
  21. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/harnesses.py +0 -0
  22. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/help.py +0 -0
  23. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/i18n.py +0 -0
  24. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/locales/__init__.py +0 -0
  25. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/locales/zh_tw_cli.py +0 -0
  26. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/locales/zh_tw_common.py +0 -0
  27. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/locales/zh_tw_config.py +0 -0
  28. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/locales/zh_tw_picker.py +0 -0
  29. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/mechanisms.py +0 -0
  30. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ops.py +0 -0
  31. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/output.py +0 -0
  32. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/profiles.py +0 -0
  33. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/settings.py +0 -0
  34. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/shims/claude.md.tmpl +0 -0
  35. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/shims/generic.md.tmpl +0 -0
  36. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/spinner.py +0 -0
  37. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/store.py +0 -0
  38. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/toml_check.py +0 -0
  39. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/__init__.py +0 -0
  40. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/config_menu.py +0 -0
  41. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/menu.py +0 -0
  42. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/model.py +0 -0
  43. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/ui/theme.py +0 -0
  44. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/undo.py +0 -0
  45. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/update_check.py +0 -0
  46. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle/update_prompt.py +0 -0
  47. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/SOURCES.txt +0 -0
  48. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/dependency_links.txt +0 -0
  49. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/entry_points.txt +0 -0
  50. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/requires.txt +0 -0
  51. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/agent_toggle.egg-info/top_level.txt +0 -0
  52. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/pyproject.toml +0 -0
  53. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/setup.cfg +0 -0
  54. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_alias.py +0 -0
  55. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_backends.py +0 -0
  56. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_cli.py +0 -0
  57. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_cli_surface.py +0 -0
  58. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_color.py +0 -0
  59. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_companions.py +0 -0
  60. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_completions.py +0 -0
  61. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_config.py +0 -0
  62. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_config_menu.py +0 -0
  63. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_conformance.py +0 -0
  64. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_containment.py +0 -0
  65. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_cost.py +0 -0
  66. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_crash.py +0 -0
  67. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_doctor.py +0 -0
  68. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_encoding.py +0 -0
  69. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_fs.py +0 -0
  70. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_harnesses.py +0 -0
  71. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_help.py +0 -0
  72. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_i18n.py +0 -0
  73. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_install.py +0 -0
  74. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_mechanisms.py +0 -0
  75. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_menu.py +0 -0
  76. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_profiles.py +0 -0
  77. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_project.py +0 -0
  78. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_safety.py +0 -0
  79. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_secret_audit.py +0 -0
  80. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_settings.py +0 -0
  81. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_store.py +0 -0
  82. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_theme.py +0 -0
  83. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_undo.py +0 -0
  84. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_update_check.py +0 -0
  85. {agent_toggle-0.7.2 → agent_toggle-0.7.3}/tests/test_update_prompt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-toggle
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: Temporarily disable / re-enable AI-agent skills, agents, commands, rules, plugins and MCP servers across harnesses (Claude Code, Codex, Grok, OpenCode, OpenClaw, Copilot, Vibe, Devin, Antigravity)
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/weskao/agent-toggle
@@ -855,6 +855,10 @@ ruff check .
855
855
  stdlib `unittest`, no fixtures, no network. Every test runs against a
856
856
  throwaway temp `HOME` and a stubbed `claude` CLI.
857
857
 
858
+ `python3 tools/wheel_smoke.py` builds the wheel, installs it without extras into a
859
+ fresh venv (what a PyPI user gets) and runs the CLI against a temp `HOME`; CI runs
860
+ it on macOS, Linux and Windows.
861
+
858
862
  ## CI notifications
859
863
 
860
864
  `.github/workflows/ci.yml` can send a Telegram message when the test matrix fails on a
@@ -823,6 +823,10 @@ ruff check .
823
823
  stdlib `unittest`, no fixtures, no network. Every test runs against a
824
824
  throwaway temp `HOME` and a stubbed `claude` CLI.
825
825
 
826
+ `python3 tools/wheel_smoke.py` builds the wheel, installs it without extras into a
827
+ fresh venv (what a PyPI user gets) and runs the CLI against a temp `HOME`; CI runs
828
+ it on macOS, Linux and Windows.
829
+
826
830
  ## CI notifications
827
831
 
828
832
  `.github/workflows/ci.yml` can send a Telegram message when the test matrix fails on a
@@ -1,3 +1,3 @@
1
1
  """agent-toggle: temporarily disable / re-enable AI-agent resources."""
2
2
 
3
- __version__ = "0.7.2"
3
+ __version__ = "0.7.3"
@@ -28,7 +28,8 @@ def claude_bin() -> str | None:
28
28
  if found:
29
29
  return found
30
30
  home = fs.home()
31
- for cand in (home / ".local/bin/claude", home / ".claude/local/claude"):
31
+ for cand in (home / ".local/bin/claude", home / ".local/bin/claude.exe", # .exe: Windows
32
+ home / ".claude/local/claude"):
32
33
  if cand.is_file() and os.access(cand, os.X_OK):
33
34
  return str(cand)
34
35
  return None
@@ -201,22 +201,18 @@ def heading(type_: str, count: int, width: int, g: theme.Glyphs) -> list[theme.S
201
201
  return [(label, "title"), (str(count), "muted"), (" " + g.h * max(0, rest), "muted")]
202
202
 
203
203
 
204
- def detail_lines(r: Row, width: int, g: theme.Glyphs) -> list[list[theme.Segment]]:
205
- """The detail pane for the cursor row: one segment list per screen line."""
204
+ def detail_lines(r: Row, width: int, g: theme.Glyphs,
205
+ height: int | None = None) -> list[list[theme.Segment]]:
206
+ """The detail pane for the cursor row: one segment list per screen line. With `height`,
207
+ the description is cut (with an ellipsis) so the fields below it still fit."""
206
208
  lab = 12 # "description" is 11 cells; leave a gap
207
209
  val = max(1, width - lab)
208
210
  out = [[(theme.truncate(r.name, width, g.ellipsis), "title")], []]
211
+ rest: list[list[theme.Segment]] = []
209
212
 
210
213
  def field(label: str, text: str, role: str = "text") -> None:
211
214
  for n in range(0, max(1, len(text)), val): # a long path wraps
212
- out.append([(pad(label if n == 0 else "", lab), "muted"), (text[n:n + val], role)])
213
-
214
- if r.description: # frontmatter prose, not a path
215
- chunks = wrap_cells(r.description, val)
216
- label = t("picker.d.description", "description")
217
- for n, chunk in enumerate(chunks):
218
- out.append([(pad(label if n == 0 else "", lab), "muted"), (chunk, "text")])
219
- out.append([])
215
+ rest.append([(pad(label if n == 0 else "", lab), "muted"), (text[n:n + val], role)])
220
216
 
221
217
  state = t("picker.state.live", "live") if r.enabled else t("picker.state.parked", "parked")
222
218
  field(t("picker.d.harness", "harness"), r.harness, theme.harness_role(r.harness))
@@ -242,7 +238,20 @@ def detail_lines(r: Row, width: int, g: theme.Glyphs) -> list[list[theme.Segment
242
238
  field(t("picker.d.since", "since"), r.since[:19].replace("T", " "))
243
239
  if r.mechanism:
244
240
  field(t("picker.d.mechanism", "mechanism"), r.mechanism)
245
- return out
241
+
242
+ if r.description: # frontmatter prose, not a path
243
+ chunks = wrap_cells(r.description, val)
244
+ # the "staged" line comes and goes with Space; reserving it keeps the text from jumping
245
+ spare = len(rest) + (not r.changed)
246
+ room = len(chunks) if height is None else max(1, height - len(out) - spare - 1)
247
+ if len(chunks) > room:
248
+ chunks = chunks[:room - 1] + [theme.truncate(" ".join(chunks[room - 1:]), val,
249
+ g.ellipsis)]
250
+ label = t("picker.d.description", "description")
251
+ for n, chunk in enumerate(chunks):
252
+ out.append([(pad(label if n == 0 else "", lab), "muted"), (chunk, "text")])
253
+ out.append([])
254
+ return out + rest
246
255
 
247
256
 
248
257
  def chips(v: View, g: theme.Glyphs) -> list[tuple[str, str]]:
@@ -322,7 +331,7 @@ def draw(win, v: View, shown: list[Row], pal: theme.Palette, g: theme.Glyphs,
322
331
  else:
323
332
  put(y, row_segments(line[1], lw, v, g, line[1] is cursor_row, any_shared))
324
333
  if dw:
325
- pane = detail_lines(cursor_row, dw - 2, g) if cursor_row else []
334
+ pane = detail_lines(cursor_row, dw - 2, g, body) if cursor_row else []
326
335
  for i in range(body):
327
336
  put(BODY_TOP + i, [(g.v, "muted"), (" ", "text"), *(pane[i] if i < len(pane) else [])],
328
337
  lw)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-toggle
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: Temporarily disable / re-enable AI-agent skills, agents, commands, rules, plugins and MCP servers across harnesses (Claude Code, Codex, Grok, OpenCode, OpenClaw, Copilot, Vibe, Devin, Antigravity)
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/weskao/agent-toggle
@@ -855,6 +855,10 @@ ruff check .
855
855
  stdlib `unittest`, no fixtures, no network. Every test runs against a
856
856
  throwaway temp `HOME` and a stubbed `claude` CLI.
857
857
 
858
+ `python3 tools/wheel_smoke.py` builds the wheel, installs it without extras into a
859
+ fresh venv (what a PyPI user gets) and runs the CLI against a temp `HOME`; CI runs
860
+ it on macOS, Linux and Windows.
861
+
858
862
  ## CI notifications
859
863
 
860
864
  `.github/workflows/ci.yml` can send a Telegram message when the test matrix fails on a
@@ -465,6 +465,19 @@ class LayoutTest(ScreenCase):
465
465
  self.assertIn("alpha beta", body)
466
466
  self.assertIn("gamma delta", body)
467
467
 
468
+ def test_long_description_is_cut_so_the_fields_still_show(self) -> None:
469
+ r = model.Row("claude", "skill", "solo", True, description="word " * 200,
470
+ mechanism="move")
471
+ lines = picker.detail_lines(r, 30, theme.ASCII, height=12)
472
+ self.assertLessEqual(len(lines), 12)
473
+ flat = ["".join(s for s, _ in line) for line in lines]
474
+ self.assertTrue(any(line.rstrip().endswith("...") for line in flat))
475
+ self.assertTrue(any(line.startswith("mechanism") for line in flat))
476
+ r.staged = False # toggling adds the "staged" line, not a cut
477
+ toggled = picker.detail_lines(r, 30, theme.ASCII, height=12)
478
+ self.assertLessEqual(len(toggled), 12)
479
+ self.assertEqual(lines[:8], toggled[:8])
480
+
468
481
  def test_detail_pane_description_is_translated(self) -> None:
469
482
  self.addCleanup(i18n.set_language, i18n.LANGUAGE)
470
483
  i18n.set_language("zh-TW")
@@ -11,6 +11,7 @@ from base import SandboxCase
11
11
 
12
12
  from agent_toggle import fs
13
13
  from agent_toggle import mechanisms as mech
14
+ from agent_toggle.backends import plugin_cli
14
15
 
15
16
 
16
17
  class PluginIdTest(SandboxCase):
@@ -103,5 +104,16 @@ class CaseRulesTest(SandboxCase):
103
104
  self.assertEqual(mech.live_names(self.home / "commands", "command"), ["group:sub:tool"])
104
105
 
105
106
 
107
+ class ClaudeBinTest(SandboxCase):
108
+ def test_off_path_windows_install_is_found_by_its_exe_name(self) -> None:
109
+ """The native Windows installer writes ~/.local/bin/claude.exe; PATH may lack it."""
110
+ plugin_cli.which = lambda name: None
111
+ exe = self.tmp / ".local" / "bin" / "claude.exe"
112
+ exe.parent.mkdir(parents=True)
113
+ exe.touch()
114
+ exe.chmod(0o755)
115
+ self.assertEqual(plugin_cli.claude_bin(), str(exe))
116
+
117
+
106
118
  if __name__ == "__main__":
107
119
  unittest.main()
File without changes
File without changes