phalanx-cli 0.2.0__tar.gz → 0.2.2__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 (50) hide show
  1. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/PKG-INFO +1 -1
  2. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/README.md +41 -53
  3. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/__init__.py +1 -1
  4. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/cli.py +3 -1
  5. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/team/create.py +38 -0
  6. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/PKG-INFO +1 -1
  7. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/pyproject.toml +1 -1
  8. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/__main__.py +0 -0
  9. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/artifacts/__init__.py +0 -0
  10. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/artifacts/reader.py +0 -0
  11. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/artifacts/schema.py +0 -0
  12. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/artifacts/writer.py +0 -0
  13. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/__init__.py +0 -0
  14. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/base.py +0 -0
  15. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/claude.py +0 -0
  16. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/codex.py +0 -0
  17. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/cursor.py +0 -0
  18. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/gemini.py +0 -0
  19. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/model_router.py +0 -0
  20. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/backends/registry.py +0 -0
  21. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/comms/__init__.py +0 -0
  22. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/comms/file_lock.py +0 -0
  23. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/comms/messaging.py +0 -0
  24. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/config.py +0 -0
  25. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/db.py +0 -0
  26. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/defaults/config.toml +0 -0
  27. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/init_cmd.py +0 -0
  28. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/monitor/__init__.py +0 -0
  29. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/monitor/gc.py +0 -0
  30. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/monitor/heartbeat.py +0 -0
  31. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/monitor/lifecycle.py +0 -0
  32. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/monitor/stall.py +0 -0
  33. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/process/__init__.py +0 -0
  34. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/process/manager.py +0 -0
  35. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/process/pool.py +0 -0
  36. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/process/worktree.py +0 -0
  37. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/soul/__init__.py +0 -0
  38. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/soul/loader.py +0 -0
  39. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/soul/skill_body.md +0 -0
  40. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/soul/team_lead.md +0 -0
  41. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/soul/worker.md +0 -0
  42. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/team/__init__.py +0 -0
  43. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/team/orchestrator.py +0 -0
  44. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx/team/spawn.py +0 -0
  45. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/SOURCES.txt +0 -0
  46. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/dependency_links.txt +0 -0
  47. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/entry_points.txt +0 -0
  48. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/requires.txt +0 -0
  49. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/phalanx_cli.egg-info/top_level.txt +0 -0
  50. {phalanx_cli-0.2.0 → phalanx_cli-0.2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phalanx-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Open-source, vendor-agnostic multi-agent orchestration CLI
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.11
@@ -16,12 +16,16 @@ Requires: Python 3.11+, tmux.
16
16
 
17
17
  ## Quick Start
18
18
 
19
+ Initialize Phalanx in your workspace:
20
+
21
+ ```bash
22
+ phalanx init
23
+ ```
24
+
19
25
  Start an agent session and talk to it:
20
26
 
21
27
  ```bash
22
- phalanx # interactive session (auto-detects backend)
23
- phalanx -b gemini # use a specific backend
24
- phalanx run "fix the failing tests" # with an initial prompt
28
+ phalanx run-agent "fix the failing tests"
25
29
  ```
26
30
 
27
31
  Then just ask your agent to create teams:
@@ -79,12 +83,12 @@ phalanx models reset # restore defaults
79
83
 
80
84
  ## Architecture
81
85
 
82
- - **State**: SQLite (WAL mode) at `~/.phalanx/state.db`
83
- - **Process isolation**: tmux sessions per agent
84
- - **Artifacts**: Ephemeral JSON (deleted after 24h inactivity)
85
- - **File locking**: Advisory locks via SQLite
86
- - **Stall detection**: stream.log monitoring with exponential backoff retry
87
- - **GC**: Opportunistic, runs on every command
86
+ - **State**: SQLite (WAL mode) at `.phalanx/state.db`
87
+ - **TUI Process Isolation**: Agents run interactively inside background `tmux` sessions. Output is captured via `pipe-pane`, meaning Phalanx can screen-scrape and deterministically handle CLI prompts (like workspace trust or tool approval) without relying on fragile prompt engineering.
88
+ - **Real-Time Communication**: Because agents are running live in `tmux`, Phalanx can send them keystrokes or interrupt them (`Ctrl+C`) to deliver messages instantly, instead of relying on slow, costly session restarts via `--resume`.
89
+ - **Artifacts**: Ephemeral JSON storing structured outputs per agent.
90
+ - **Stall Detection**: `stream.log` (from `tmux`) is monitored via a Heartbeat system. If an agent hangs or crashes, Phalanx detects the lack of output, interrupts, and prompts the agent to continue or fail gracefully.
91
+ - **GC**: Opportunistic cleanup of dead teams, running on standard CLI commands.
88
92
 
89
93
  ## CLI Reference
90
94
 
@@ -92,72 +96,56 @@ phalanx models reset # restore defaults
92
96
 
93
97
  | Command | Description |
94
98
  |---------|-------------|
95
- | `phalanx` | Start interactive agent session |
96
- | `phalanx run "prompt"` | Single agent session with prompt |
97
- | `phalanx --auto-approve create-team` | Create agent team |
98
- | `phalanx team-status <id>` | Team status |
99
- | `phalanx team-result <id>` | Read team results |
100
- | `phalanx message <id> "msg"` | Message team lead |
101
- | `phalanx stop <id>` | Stop team |
102
- | `phalanx resume <id>` | Resume team |
103
- | `phalanx status` | List all teams |
104
- | `phalanx config show/set` | Configuration |
105
- | `phalanx models show/set/reset/update` | Model routing |
99
+ | `phalanx init` | Initialize `.phalanx` in workspace, generate skill files |
100
+ | `phalanx run-agent "task"` | Spawn a single interactive agent (no team lead) |
101
+ | `phalanx create-team "task"` | Create a team and start its team lead |
102
+ | `phalanx monitor <id>` | Attach a blocking DEM-style monitoring loop |
103
+ | `phalanx team-status [id]` | View team status summary |
104
+ | `phalanx agent-status [id]` | View specific agent status |
105
+ | `phalanx team-result <id>` | Read team lead's final artifact |
106
+ | `phalanx message <id> "msg"` | Message a team lead |
107
+ | `phalanx message-agent <id> "msg"` | Message a specific agent |
108
+ | `phalanx send-keys <id> <keys>` | Send raw keystrokes to an agent's `tmux` pane |
109
+ | `phalanx stop <id>` | Stop a team (kills processes) |
110
+ | `phalanx status` | List all running agents across all teams |
111
+ | `phalanx gc` | Clean up old data and dead teams |
106
112
 
107
113
  ### Agent Tools (used by spawned agents)
108
114
 
109
115
  | Command | Description |
110
116
  |---------|-------------|
111
- | `phalanx write-artifact` | Write structured result |
112
- | `phalanx agent-status` | Check peer status |
117
+ | `phalanx spawn-agent` | Spawn a sub-agent (used by team lead) |
118
+ | `phalanx write-artifact` | Write structured result (success/failure/escalation) |
113
119
  | `phalanx agent-result <id>` | Read peer artifact |
114
- | `phalanx message <team-id> "msg"` | Message team lead |
115
- | `phalanx message-agent <id> "msg"` | Message a specific worker |
116
- | `phalanx lock/unlock <path>` | File locking |
120
+ | `phalanx lock/unlock <path>` | Advisory file locking to prevent collisions |
117
121
 
118
122
  ## Develop Locally
119
123
 
120
124
  ```bash
121
125
  git clone https://github.com/creynir/phalanx.git
122
126
  cd phalanx
123
- pip install -e ".[dev]"
127
+ uv sync
128
+ uv pip install -e ".[dev]"
124
129
  ```
125
130
 
126
131
  Run tests:
127
132
 
128
133
  ```bash
129
- pytest tests/unit/ # unit tests
130
- pytest tests/integration/ # integration tests (requires tmux)
131
- pytest tests/e2e/ # end-to-end tests
132
- pytest tests/ # all 211 tests
133
- ```
134
-
135
- Pre-commit hooks (ruff lint + format) are configured — install with:
136
-
137
- ```bash
138
- pip install pre-commit
139
- pre-commit install
134
+ uv run pytest tests/
140
135
  ```
141
136
 
142
137
  ## Configuration
143
138
 
144
- Global: `~/.phalanx/config.toml`
145
- Workspace override: `.phalanx/config.toml`
146
-
147
- ```toml
148
- [defaults]
149
- backend = "cursor"
150
-
151
- [timeouts]
152
- agent_inactivity_minutes = 30
153
- team_gc_hours = 24
154
- stall_seconds = 180
139
+ Workspace overrides can be edited at `.phalanx/config.json`:
155
140
 
156
- [models.cursor]
157
- orchestrator = "sonnet-4.6"
158
- coder = "sonnet-4.6"
159
- researcher = "gemini-3.1-pro"
160
- default = "gemini-3.1-pro"
141
+ ```json
142
+ {
143
+ "default_backend": "cursor",
144
+ "idle_timeout_seconds": 1800,
145
+ "max_runtime_seconds": 1800,
146
+ "stall_check_interval": 20,
147
+ "auto_approve": true
148
+ }
161
149
  ```
162
150
 
163
151
  ## License
@@ -1,3 +1,3 @@
1
1
  """Phalanx — Multi-Agent Orchestration System."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.2"
@@ -181,11 +181,12 @@ def run_agent(ctx, task, backend, model, auto_approve):
181
181
 
182
182
  @cli.command("create-team")
183
183
  @click.argument("task")
184
+ @click.option("--agents", "-a", default="coder", help="Agent spec: role[:count],...")
184
185
  @click.option("--backend", "-b", default=None, help="Backend")
185
186
  @click.option("--model", "-m", default=None, help="Model")
186
187
  @click.option("--auto-approve/--no-auto-approve", default=True)
187
188
  @click.pass_context
188
- def create_team_cmd(ctx, task, backend, model, auto_approve):
189
+ def create_team_cmd(ctx, task, agents, backend, model, auto_approve):
189
190
  """Create a team and start its team lead."""
190
191
  from phalanx.monitor.heartbeat import HeartbeatMonitor
191
192
  from phalanx.process.manager import ProcessManager
@@ -204,6 +205,7 @@ def create_team_cmd(ctx, task, backend, model, auto_approve):
204
205
  process_manager=pm,
205
206
  heartbeat_monitor=hb,
206
207
  task=task,
208
+ agents_spec=agents,
207
209
  backend_name=backend or config.default_backend,
208
210
  model=model or config.default_model,
209
211
  auto_approve=auto_approve,
@@ -15,12 +15,28 @@ from phalanx.team.spawn import spawn_agent
15
15
  logger = logging.getLogger(__name__)
16
16
 
17
17
 
18
+ def parse_agents_spec(spec: str) -> list[tuple[str, int]]:
19
+ """Parse agent spec like 'researcher,coder:2,reviewer' into [(role, count)]."""
20
+ agents = []
21
+ if not spec:
22
+ return agents
23
+ for part in spec.split(","):
24
+ part = part.strip()
25
+ if ":" in part:
26
+ role, count_str = part.split(":", 1)
27
+ agents.append((role.strip(), int(count_str)))
28
+ else:
29
+ agents.append((part, 1))
30
+ return agents
31
+
32
+
18
33
  def create_team(
19
34
  phalanx_root: Path,
20
35
  db: StateDB,
21
36
  process_manager: ProcessManager,
22
37
  heartbeat_monitor: HeartbeatMonitor,
23
38
  task: str,
39
+ agents_spec: str = "coder",
24
40
  backend_name: str = "cursor",
25
41
  model: str | None = None,
26
42
  auto_approve: bool = True,
@@ -43,6 +59,28 @@ def create_team(
43
59
  team_dir = phalanx_root / "teams" / team_id
44
60
  team_dir.mkdir(parents=True, exist_ok=True)
45
61
 
62
+ # Spawn workers first
63
+ worker_specs = parse_agents_spec(agents_spec)
64
+ worker_index = 0
65
+ for role, count in worker_specs:
66
+ for _ in range(count):
67
+ worker_id = f"w{worker_index}-{role}"
68
+ spawn_agent(
69
+ phalanx_root=phalanx_root,
70
+ db=db,
71
+ process_manager=process_manager,
72
+ heartbeat_monitor=heartbeat_monitor,
73
+ team_id=team_id,
74
+ task=task,
75
+ role=role,
76
+ agent_id=worker_id,
77
+ backend_name=backend_name,
78
+ model=None, # let router decide based on role
79
+ auto_approve=auto_approve,
80
+ config=config,
81
+ )
82
+ worker_index += 1
83
+
46
84
  # Spawn team lead
47
85
  spawn_agent(
48
86
  phalanx_root=phalanx_root,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: phalanx-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Open-source, vendor-agnostic multi-agent orchestration CLI
5
5
  License-Expression: MIT
6
6
  Requires-Python: >=3.11
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "phalanx-cli"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Open-source, vendor-agnostic multi-agent orchestration CLI"
9
9
  requires-python = ">=3.11"
10
10
  license = "MIT"
File without changes
File without changes