workstreams-cli 0.6.0__tar.gz → 0.6.1__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 (31) hide show
  1. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/PKG-INFO +2 -2
  2. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/README.md +1 -1
  3. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/pyproject.toml +1 -1
  4. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/__init__.py +1 -1
  5. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/config.py +15 -6
  6. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/multiplexer/tmux.py +6 -0
  7. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/PKG-INFO +2 -2
  8. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/tests/test_config.py +34 -0
  9. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/setup.cfg +0 -0
  10. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/cli.py +0 -0
  11. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/confidence.py +0 -0
  12. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/dashboard.py +0 -0
  13. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/event_log.py +0 -0
  14. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/manager.py +0 -0
  15. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/models.py +0 -0
  16. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/multiplexer/__init__.py +0 -0
  17. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/multiplexer/base.py +0 -0
  18. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/multiplexer/tmux_compatible.py +0 -0
  19. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/multiplexer/zellij.py +0 -0
  20. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/notifier.py +0 -0
  21. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/py.typed +0 -0
  22. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams/subagent_client.py +0 -0
  23. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/SOURCES.txt +0 -0
  24. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/dependency_links.txt +0 -0
  25. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/entry_points.txt +0 -0
  26. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/requires.txt +0 -0
  27. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/src/workstreams_cli.egg-info/top_level.txt +0 -0
  28. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/tests/test_confidence.py +0 -0
  29. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/tests/test_event_log.py +0 -0
  30. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/tests/test_models.py +0 -0
  31. {workstreams_cli-0.6.0 → workstreams_cli-0.6.1}/tests/test_notifier.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workstreams-cli
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Visually dispatch coding-agent work to subagents in real terminal windows and monitor it in one dashboard - for any coding agent (Claude Code, Codex, OpenCode, Qwen Code, Hermes, Cline, and more).
5
5
  Author: Dream-Pixels-Forge
6
6
  License: MIT
@@ -114,7 +114,7 @@ pip install -e ".[yaml,dev]" # dev extras add pytest
114
114
  Verify:
115
115
 
116
116
  ```bash
117
- workstreams --version # -> workstreams 0.6.0
117
+ workstreams --version # -> workstreams 0.6.1
118
118
  ```
119
119
 
120
120
  > **Note:** every command also accepts `--json` to emit machine-readable output (where supported), which coding agents can parse. All read-side commands work without a multiplexer installed; only `start`/`dispatch`/`work`/`attach` need one.
@@ -84,7 +84,7 @@ pip install -e ".[yaml,dev]" # dev extras add pytest
84
84
  Verify:
85
85
 
86
86
  ```bash
87
- workstreams --version # -> workstreams 0.6.0
87
+ workstreams --version # -> workstreams 0.6.1
88
88
  ```
89
89
 
90
90
  > **Note:** every command also accepts `--json` to emit machine-readable output (where supported), which coding agents can parse. All read-side commands work without a multiplexer installed; only `start`/`dispatch`/`work`/`attach` need one.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "workstreams-cli"
7
- version = "0.6.0"
7
+ version = "0.6.1"
8
8
  description = "Visually dispatch coding-agent work to subagents in real terminal windows and monitor it in one dashboard - for any coding agent (Claude Code, Codex, OpenCode, Qwen Code, Hermes, Cline, and more)."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -42,7 +42,7 @@ from .confidence import (
42
42
  extract_score,
43
43
  )
44
44
 
45
- __version__ = "0.6.0"
45
+ __version__ = "0.6.1"
46
46
 
47
47
  __all__ = [
48
48
  # models
@@ -47,19 +47,28 @@ def load_config(
47
47
  """
48
48
  base_path = (base_path or Path.cwd()).resolve()
49
49
  config_file = config_path_in(base_path)
50
+ # Fall back to the JSON config if YAML is not present (no-pyyaml installs)
51
+ if not config_file.exists():
52
+ json_fallback = config_file.with_suffix(".json")
53
+ if json_fallback.exists():
54
+ config_file = json_fallback
50
55
  data: Dict[str, Any] = {}
51
56
  if config_file.exists():
52
57
  try:
53
58
  text = config_file.read_text()
54
- parsed = _yaml_load(text)
55
- if parsed is not None:
56
- data = parsed
59
+ if config_file.suffix == ".json":
60
+ parsed = json.loads(text)
61
+ data = parsed if isinstance(parsed, dict) else {}
57
62
  else:
58
- # Fallback parser for simple YAML (no pyyaml installed)
59
- parsed = _simple_yaml_load(text)
63
+ parsed = _yaml_load(text)
60
64
  if parsed is not None:
61
65
  data = parsed
62
- except OSError:
66
+ else:
67
+ # Fallback parser for simple YAML (no pyyaml installed)
68
+ parsed = _simple_yaml_load(text)
69
+ if parsed is not None:
70
+ data = parsed
71
+ except (OSError, json.JSONDecodeError):
63
72
  data = {}
64
73
 
65
74
  workstreams = [
@@ -180,7 +180,13 @@ class TmuxMultiplexer(MultiplexerBase):
180
180
  flush=True,
181
181
  )
182
182
  return False
183
+ # Try the named window first; if tmux can't resolve that target
184
+ # (stale name, or a session created outside workstreams), fall back
185
+ # to the numeric window index so dispatches don't silently no-op.
183
186
  result = self._tmux("send-keys", "-t", target, command, "Enter")
187
+ if result.returncode != 0:
188
+ fallback = f"{self.session}:{workstream_id - 1}"
189
+ result = self._tmux("send-keys", "-t", fallback, command, "Enter")
184
190
  return result.returncode == 0
185
191
 
186
192
  def capture(self, workstream_id: int, lines: int = 20) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workstreams-cli
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Visually dispatch coding-agent work to subagents in real terminal windows and monitor it in one dashboard - for any coding agent (Claude Code, Codex, OpenCode, Qwen Code, Hermes, Cline, and more).
5
5
  Author: Dream-Pixels-Forge
6
6
  License: MIT
@@ -114,7 +114,7 @@ pip install -e ".[yaml,dev]" # dev extras add pytest
114
114
  Verify:
115
115
 
116
116
  ```bash
117
- workstreams --version # -> workstreams 0.6.0
117
+ workstreams --version # -> workstreams 0.6.1
118
118
  ```
119
119
 
120
120
  > **Note:** every command also accepts `--json` to emit machine-readable output (where supported), which coding agents can parse. All read-side commands work without a multiplexer installed; only `start`/`dispatch`/`work`/`attach` need one.
@@ -67,6 +67,40 @@ def test_load_nonexistent_returns_default_project(tmp_path):
67
67
  assert loaded.multiplexer == "tmux"
68
68
 
69
69
 
70
+ def test_load_json_when_no_yaml_present(tmp_path):
71
+ """Regression: when the on-disk config is .json (no pyyaml), load_config
72
+ must still read it back instead of silently defaulting to 0 workstreams.
73
+
74
+ This is the path that caused `start` to create a misnamed session with a
75
+ `wsNone` window: the workstream list was empty because the JSON file was
76
+ never consulted."""
77
+ cfg = _make_config(n=2)
78
+ project_dir = tmp_path / "jsonproj"
79
+ project_dir.mkdir()
80
+ # Save with pyyaml (writes .yaml), then remove the .yaml so only .json
81
+ # semantics remain — emulate an install without pyyaml.
82
+ saved = save_config(cfg, project_dir)
83
+ json_fallback = project_dir / ".workstreams.json"
84
+ if saved.suffix == ".yaml":
85
+ # Convert: write the equivalent JSON and drop the YAML so the loader
86
+ # is forced down the .json branch.
87
+ import json as _json
88
+ data = _json.loads(_json.dumps(cfg.to_dict()))
89
+ json_fallback.write_text(_json.dumps(data, indent=2) + "\n")
90
+ saved.unlink()
91
+ else:
92
+ json_fallback = saved
93
+
94
+ loaded = load_config(project_dir, "testproj")
95
+ assert loaded is not None
96
+ assert loaded.project == "testproj"
97
+ assert len(loaded.workstreams) == 2, (
98
+ f"expected 2 workstreams from JSON config, got {len(loaded.workstreams)}"
99
+ )
100
+ assert loaded.workstreams[0].name == "ws1"
101
+ assert loaded.workstreams[1].branch == "ws/2"
102
+
103
+
70
104
  def test_load_from_json_fallback(tmp_path):
71
105
  """When pyyaml is unavailable the config is saved as .json and must still load."""
72
106
  cfg = _make_config(n=1)