Merge pull request 'refactor: kill→stop across API surface, CLI, TUI, and docs' (#215) from refactor/kill-to-stop into main
Reviewed-on: #215
This commit is contained in:
commit
9a04b94712
22 changed files with 64 additions and 63 deletions
|
|
@ -22,7 +22,7 @@ enum Command {
|
|||
system_prompt: Option<String>,
|
||||
jail: Option<colibri_client::JailConfig>,
|
||||
},
|
||||
KillAgent {
|
||||
StopAgent {
|
||||
agent_id: String,
|
||||
},
|
||||
GetSession {
|
||||
|
|
@ -84,7 +84,7 @@ fn usage() -> &'static str {
|
|||
colibri [--socket PATH] list-sessions
|
||||
colibri [--socket PATH] spawn-local EXECUTABLE [--session-id ID] [--system-prompt TEXT] [--jail-name NAME [--jail-root PATH]]
|
||||
colibri [--socket PATH] spawn-agent PROVIDER MODEL [--session-id ID] [--system-prompt TEXT] [--jail-name NAME [--jail-root PATH]]
|
||||
colibri [--socket PATH] kill AGENT_ID
|
||||
colibri [--socket PATH] stop AGENT_ID
|
||||
colibri [--socket PATH] get-session SESSION_ID
|
||||
colibri [--socket PATH] compact-session SESSION_ID
|
||||
colibri [--socket PATH] list-tasks [--status STATUS]
|
||||
|
|
@ -190,7 +190,7 @@ where
|
|||
})
|
||||
}
|
||||
}
|
||||
"kill" | "kill-agent" => expect_arity(&args, 2).map(|()| Command::KillAgent {
|
||||
"stop" | "stop-agent" => expect_arity(&args, 2).map(|()| Command::StopAgent {
|
||||
agent_id: args[1].clone(),
|
||||
}),
|
||||
"get-session" => expect_arity(&args, 2).map(|()| Command::GetSession {
|
||||
|
|
@ -604,7 +604,7 @@ async fn run(options: Options) -> Result<(), ClientError> {
|
|||
.spawn_agent_with(provider, model, session_id, system_prompt, jail)
|
||||
.await?,
|
||||
),
|
||||
Command::KillAgent { agent_id } => print_json(&client.kill_agent(agent_id).await?),
|
||||
Command::StopAgent { agent_id } => print_json(&client.stop_agent(agent_id).await?),
|
||||
Command::GetSession { session_id } => print_json(&client.get_session(session_id).await?),
|
||||
Command::CompactSession { session_id } => {
|
||||
print_json(&client.compact_session(session_id).await?)
|
||||
|
|
|
|||
|
|
@ -133,11 +133,11 @@ impl DaemonClient {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn kill_agent(
|
||||
pub async fn stop_agent(
|
||||
&self,
|
||||
agent_id: impl Into<String>,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
self.request(&ColibriCommand::KillAgent {
|
||||
self.request(&ColibriCommand::StopAgent {
|
||||
agent_id: agent_id.into(),
|
||||
})
|
||||
.await
|
||||
|
|
|
|||
|
|
@ -143,8 +143,8 @@ async fn daemon_client_live_socket_check_with_local_sample_agent() {
|
|||
assert_eq!(pane.session_id.as_deref(), Some("manual-test"));
|
||||
assert!(pane.cwd.is_some());
|
||||
|
||||
let kill = client.kill_agent(agent_id).await.unwrap();
|
||||
assert_eq!(kill["status"], "stopped");
|
||||
let stop = client.stop_agent(agent_id).await.unwrap();
|
||||
assert_eq!(stop["status"], "stopped");
|
||||
|
||||
let _ = state.shutdown_tx.send(());
|
||||
server.await.unwrap();
|
||||
|
|
@ -382,9 +382,9 @@ async fn harness_double_spawn_session_isolation() {
|
|||
// Verify session isolation: both share the same session_id (test agent default)
|
||||
assert_eq!(pane_a.session_id, pane_b.session_id);
|
||||
|
||||
// Kill one agent — snapshot may still include stopped panes briefly
|
||||
let kill = client.kill_agent(&pane_a.id).await.unwrap();
|
||||
assert_eq!(kill["status"], "stopped");
|
||||
// Stop one agent — snapshot may still include stopped panes briefly
|
||||
let stop = client.stop_agent(&pane_a.id).await.unwrap();
|
||||
assert_eq!(stop["status"], "stopped");
|
||||
|
||||
let _ = state.shutdown_tx.send(());
|
||||
server.await.unwrap();
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ pub enum ColibriCommand {
|
|||
#[serde(default)]
|
||||
jail: Option<crate::spawner::JailConfig>,
|
||||
},
|
||||
#[serde(rename = "kill-agent")]
|
||||
KillAgent { agent_id: String },
|
||||
#[serde(rename = "stop-agent")]
|
||||
StopAgent { agent_id: String },
|
||||
#[serde(rename = "get-session")]
|
||||
GetSession { session_id: String },
|
||||
#[serde(rename = "compact-session")]
|
||||
|
|
|
|||
|
|
@ -102,10 +102,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
// Give sub-tasks a moment to clean up
|
||||
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
|
||||
|
||||
// Kill any running agent subprocesses
|
||||
// Stop any running agent subprocesses
|
||||
for entry in shutdown_state.agents.iter() {
|
||||
let handle = entry.value();
|
||||
info!(agent_id = %handle.id, "killing agent");
|
||||
info!(agent_id = %handle.id, "stopping agent");
|
||||
let _ = handle.kill().await;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -215,10 +215,11 @@ impl Scheduler {
|
|||
store.list_agents().unwrap_or_default()
|
||||
};
|
||||
if let Some(agent) = pick_agent(&req.required_capabilities, &agents) {
|
||||
match {
|
||||
let res = {
|
||||
let store = state.store.lock().unwrap();
|
||||
store.claim_task(&req.task_id, &agent.id)
|
||||
} {
|
||||
};
|
||||
match res {
|
||||
Ok(_) => info!(
|
||||
task_id = %req.task_id,
|
||||
agent_id = %agent.id,
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ async fn dispatch(cmd: ColibriCommand, state: &SharedState) -> ColibriResponse {
|
|||
)
|
||||
.await
|
||||
}
|
||||
ColibriCommand::KillAgent { agent_id } => cmd_kill_agent(state, agent_id).await,
|
||||
ColibriCommand::StopAgent { agent_id } => cmd_stop_agent(state, agent_id).await,
|
||||
ColibriCommand::GetSession { session_id } => cmd_get_session(state, session_id).await,
|
||||
ColibriCommand::CompactSession { session_id } => {
|
||||
cmd_compact_session(state, session_id).await
|
||||
|
|
@ -1028,7 +1028,7 @@ async fn cmd_spawn_agent(
|
|||
}
|
||||
}
|
||||
|
||||
async fn cmd_kill_agent(state: &SharedState, agent_id: String) -> ColibriResponse {
|
||||
async fn cmd_stop_agent(state: &SharedState, agent_id: String) -> ColibriResponse {
|
||||
match state.agents.remove(&agent_id) {
|
||||
Some((_id, handle)) => match handle.kill().await {
|
||||
Ok(()) => {
|
||||
|
|
@ -1042,7 +1042,7 @@ async fn cmd_kill_agent(state: &SharedState, agent_id: String) -> ColibriRespons
|
|||
"status": "stopped",
|
||||
}))
|
||||
}
|
||||
Err(e) => ColibriResponse::err(format!("kill failed: {e}")),
|
||||
Err(e) => ColibriResponse::err(format!("stop failed: {e}")),
|
||||
},
|
||||
None => ColibriResponse::err(format!("agent not found: {agent_id}")),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -719,12 +719,12 @@ impl AgentHandle {
|
|||
}
|
||||
}
|
||||
|
||||
/// Kill the agent subprocess.
|
||||
/// Stop the agent subprocess (sends SIGKILL to the tracked child).
|
||||
///
|
||||
/// For a jailed agent the tracked child is the wrapper (`mdo`/`jexec`/
|
||||
/// `jail`); killing it removes a `jail -c command=` ephemeral jail (the jail
|
||||
/// `jail`); stopping it removes a `jail -c command=` ephemeral jail (the jail
|
||||
/// is torn down when its command process dies). Reaping a deeply nested
|
||||
/// in-jail process tree may need a process-group kill — tracked as a
|
||||
/// in-jail process tree may need a process-group stop — tracked as a
|
||||
/// follow-up; see `docs/COLIBRI-JAILED-AGENT-SPAWN-DESIGN.md`.
|
||||
pub async fn kill(&self) -> Result<(), SpawnerError> {
|
||||
let mut child = self.child.lock().await;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// colibri-harness — Colibri-native supervision TUI built on Colibri primitives.
|
||||
//
|
||||
// Connects to a colibri-daemon Unix socket, polls GlasspaneSnapshot every 2s,
|
||||
// lets the operator spawn/kill agents, drill into pane details, and cycle
|
||||
// lets the operator spawn/stop agents, drill into pane details, and cycle
|
||||
// through sessions — all from a color-coded ratatui dashboard.
|
||||
//
|
||||
// Usage:
|
||||
|
|
@ -254,7 +254,7 @@ impl App {
|
|||
}
|
||||
}
|
||||
|
||||
async fn kill_selected(&mut self) {
|
||||
async fn stop_selected(&mut self) {
|
||||
let id = match self.selected_pane_id().map(String::from) {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
|
|
@ -262,9 +262,9 @@ impl App {
|
|||
return;
|
||||
}
|
||||
};
|
||||
match self.client.kill_agent(&id).await {
|
||||
Ok(_) => self.set_status(format!("killed {id}")),
|
||||
Err(e) => self.set_status(format!("kill failed: {e}")),
|
||||
match self.client.stop_agent(&id).await {
|
||||
Ok(_) => self.set_status(format!("stopped {id}")),
|
||||
Err(e) => self.set_status(format!("stop failed: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -592,7 +592,7 @@ impl App {
|
|||
key("s"),
|
||||
Span::raw(" spawn "),
|
||||
key("x"),
|
||||
Span::raw(" kill "),
|
||||
Span::raw(" stop "),
|
||||
key("enter"),
|
||||
Span::raw(" detail "),
|
||||
key("tab"),
|
||||
|
|
@ -640,7 +640,7 @@ async fn run(socket_path: PathBuf) -> io::Result<()> {
|
|||
}
|
||||
KeyCode::Char('r') => app.refresh().await,
|
||||
KeyCode::Char('s') => app.spawn_agent().await,
|
||||
KeyCode::Char('x') => app.kill_selected().await,
|
||||
KeyCode::Char('x') => app.stop_selected().await,
|
||||
KeyCode::Enter => {
|
||||
let idx = app.table_state.selected().unwrap_or(0);
|
||||
let count = app.filtered_panes().len();
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ Default ISO posture should be **read-only**. Mutating tools require:
|
|||
COLIBRI_MCP_WRITE=1
|
||||
```
|
||||
|
||||
Agent spawn/kill tools are stronger than normal writes and should require a separate guard plus allowlist:
|
||||
Agent spawn/stop tools are stronger than normal writes and should require a separate guard plus allowlist:
|
||||
|
||||
```sh
|
||||
COLIBRI_MCP_SPAWN=1
|
||||
|
|
@ -167,7 +167,7 @@ Phase 2 MCP tools (after basics proven):
|
|||
| Tool | Description |
|
||||
| ------------------------- | ------------------------------------------------ |
|
||||
| `colibri_spawn_agent` | Spawn an agent with provider/model config |
|
||||
| `colibri_kill_agent` | Kill a running agent |
|
||||
| `colibri_stop_agent` | Stop a running agent |
|
||||
| `colibri_session_summary` | Summarize an active session |
|
||||
| `colibri_schedule_job` | Add a cron/interval/one-shot job |
|
||||
| `colibri_search_skills` | Search built-in knowledge (via `colibri-skills`) |
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ own (no external code, no dependency).
|
|||
| `q` / `Esc` | Quit, or close detail pane if open |
|
||||
| `r` | Refresh snapshot now |
|
||||
| `s` | Spawn a local `colibri-test-agent` |
|
||||
| `x` | Kill the selected pane |
|
||||
| `x` | Stop the selected pane |
|
||||
| `Enter` | Open/close the detail pane for the selected row |
|
||||
| `Tab` / `Shift-Tab` | Cycle through distinct sessions |
|
||||
| `j` / `k` or `↓` / `↑` | Navigate the pane table |
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ The multi-host stack lives **outside the Rust daemon**:
|
|||
| -------------- | --------------------------------------------------------------------------- |
|
||||
| Daemon | `status`, `glasspane-snapshot`, `set-cost-mode` |
|
||||
| Session | `list-sessions`, `get-session`, `compact-session` |
|
||||
| Agent process | `spawn-agent`, `kill-agent` |
|
||||
| Agent process | `spawn-agent`, `stop-agent` |
|
||||
| Board | `list-tasks`, `create-task`, `transition-task`, `claim-task`, `intake-task` |
|
||||
| Agent registry | `register-agent`, `list-agents` |
|
||||
| Tenant | `register-tenant`, `list-tenants` |
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ clawdie.si → landing (unchanged)
|
|||
|
||||
## What needs building
|
||||
|
||||
| Layer | Task |
|
||||
|---|---|
|
||||
| DNS | `wiki.clawdie.si` A/AAAA → same host |
|
||||
| TLS | New Let's Encrypt cert (acme.sh auto-renew) |
|
||||
| Nginx | New vhost for wiki.clawdie.si |
|
||||
| Layer | Task |
|
||||
| ----- | -------------------------------------------------- |
|
||||
| DNS | `wiki.clawdie.si` A/AAAA → same host |
|
||||
| TLS | New Let's Encrypt cert (acme.sh auto-renew) |
|
||||
| Nginx | New vhost for wiki.clawdie.si |
|
||||
| Astro | Two Starlight configs from one colibri source tree |
|
||||
| Build | `build-docs.sh` → dist-guide/ + dist-wiki/ |
|
||||
| ISO | `FEATURE_DOCS` / `FEATURE_WIKI` toggle knobs |
|
||||
| Build | `build-docs.sh` → dist-guide/ + dist-wiki/ |
|
||||
| ISO | `FEATURE_DOCS` / `FEATURE_WIKI` toggle knobs |
|
||||
|
||||
## Two Starlight configs
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ input chain); under ufw it is redundant.
|
|||
|
||||
The control-plane socket has **no authentication of its own**. Once it is
|
||||
bridged, any peer that can reach the host over the tailnet can issue the full
|
||||
command set (`spawn-agent`, `kill-agent`, `intake-task`, `terminal-*`, …). That
|
||||
command set (`spawn-agent`, `stop-agent`, `intake-task`, `terminal-*`, …). That
|
||||
makes the **Tailscale boundary the access control**:
|
||||
|
||||
- Scope the port to named peers with a **Tailscale ACL** on `:9190` rather than
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ poganjajo ufw (privzeto sprejemajoča vhodna veriga); pod ufw je odveč.
|
|||
|
||||
Vtičnica krmilne ravnine **nima lastne avtentikacije**. Ko je enkrat
|
||||
premoščena, lahko vsak soležnik, ki gostitelja doseže prek omrežja Tailscale,
|
||||
izda celoten nabor ukazov (`spawn-agent`, `kill-agent`, `intake-task`,
|
||||
izda celoten nabor ukazov (`spawn-agent`, `stop-agent`, `intake-task`,
|
||||
`terminal-*`, …). Zato je **meja Tailscale nadzor dostopa**:
|
||||
|
||||
- vrata omejite na poimenovane soležnike s **politiko [ACL](../reference/okrajsave/#acl) v Tailscale** na
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ Bastille za izolacijo agentov in zunanjih MCP strežnikov. Glej tudi:
|
|||
### jailed
|
||||
|
||||
**Zaprt v ječi** — stanje procesa, ki teče znotraj ječe. Proces, ki je
|
||||
*zaprt v ječi*, nima dostopa do gostitelja. Nasprotje je *na prostosti*
|
||||
_zaprt v ječi_, nima dostopa do gostitelja. Nasprotje je _na prostosti_
|
||||
(teče na gostitelju brez izolacije).
|
||||
|
||||
### mother (mother node)
|
||||
|
|
@ -225,5 +225,5 @@ najemnikov.
|
|||
|
||||
**Paznik** — upravljalec ječ. Na FreeBSD je to `jail(8)` ali `warden0`
|
||||
(omrežni most ječ Bastille). Na matičnem vozlišču je to `colibri-mcp-ssh`,
|
||||
ki nadzoruje, kateri ukazi so dovoljeni čez SSH. *Paznik* je slovenski izraz
|
||||
ki nadzoruje, kateri ukazi so dovoljeni čez SSH. _Paznik_ je slovenski izraz
|
||||
za paznika v zaporu — čuva ječo in njene zapornike.
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ new subsystem.
|
|||
|
||||
The snapshot API is read-heavy by design. A future write path — "send input to
|
||||
pane N" over the daemon socket — would let the operator **respond** to a blocked
|
||||
agent from `colibri-tui`, not just observe/spawn/kill. This is direction, not a
|
||||
agent from `colibri-tui`, not just observe/spawn/stop. This is direction, not a
|
||||
quick win; it changes the socket from read-only supervision to interactive
|
||||
control and needs its own design pass.
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ and operator muscle memory apply to every client.
|
|||
|
||||
### No write-gating inside the CLI itself
|
||||
|
||||
Commands that mutate state (`create-task`, `kill-agent`, `set-cost-mode`,
|
||||
Commands that mutate state (`create-task`, `stop-agent`, `set-cost-mode`,
|
||||
`register-tenant`) are not blocked by CLI flags. The gate is the Unix socket
|
||||
itself: the daemon is configured to listen on a unix socket with operator-only
|
||||
permissions, and the daemon validates each command. This avoids two parallel
|
||||
|
|
@ -107,7 +107,7 @@ sample close to its primary caller without adding a new crate.
|
|||
| `snapshot` / `glasspane-snapshot` | current pane radar view |
|
||||
| `list-sessions` | active agent sessions |
|
||||
| `spawn-local` / `spawn-agent` | start an agent, optionally jailed |
|
||||
| `kill AGENT_ID` | terminate a pane/agent |
|
||||
| `stop AGENT_ID` | terminate a pane/agent |
|
||||
| `create-task` / `intake-task` / `claim-task` / `transition-task` | task-board workflow |
|
||||
| `set-cost-mode MODE` | acknowledge/toggle cost mode |
|
||||
| `register-tenant` / `list-tenants` | vault provisioning bookkeeping |
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ podpira. Prav tako se izogne potrebi po odprtju drugega omrežnega vmesnika.
|
|||
|
||||
Strežnik MCP izpostavlja tri orodja:
|
||||
|
||||
| Orodje | Ukaz ozadnjega procesa | Namen |
|
||||
| ------------------ | -------------------- | ----------------------------------------------- |
|
||||
| `colibri_status` | `status` | Stanje ozadnjega procesa (agenti, opravila, predpomnilnik) |
|
||||
| `colibri_snapshot` | `glasspane-snapshot` | Trenutni posnetek podoken Glasspane |
|
||||
| `colibri_spawn` | `spawn-agent` | Zaženi novega agenta |
|
||||
| Orodje | Ukaz ozadnjega procesa | Namen |
|
||||
| ------------------ | ---------------------- | ---------------------------------------------------------- |
|
||||
| `colibri_status` | `status` | Stanje ozadnjega procesa (agenti, opravila, predpomnilnik) |
|
||||
| `colibri_snapshot` | `glasspane-snapshot` | Trenutni posnetek podoken Glasspane |
|
||||
| `colibri_spawn` | `spawn-agent` | Zaženi novega agenta |
|
||||
|
||||
Ta tri orodja pokrivajo 90 % zunanjih interakcij. Celoten API vtičnice je na
|
||||
voljo neposrednim odjemalcem vtičnice; MCP je priročna podmnožica.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ clippy.
|
|||
|
||||
| Stran | Kaj pokriva |
|
||||
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [agent-harness](./agent-harness.md) | Razcep zot (agent) + Colibri (krmilna ravnina); vprega, samodejni zagon + gonilnik RPC |
|
||||
| [agent-harness](./agent-harness.md) | Razcep zot (agent) + Colibri (krmilna ravnina); vprega, samodejni zagon + gonilnik RPC |
|
||||
| [agent-events-reference](./agent-events-reference.md) | Referenca dogodkov zot po opremi, preslikave Glasspane in preverjena polja prepisa |
|
||||
| [cost-model](./cost-model.md) | Bajtno stabilne predpone, merjenje zadetkov predpomnilnika, samodejno stopnjevanje, stiskanje T14 |
|
||||
| [glasspane](./glasspane.md) | Avtomat stanj agenta, pretakanje JSONL, taksonomija AgentRuntime, API posnetkov |
|
||||
|
|
@ -62,11 +62,11 @@ clippy.
|
|||
| [naming-decisions](./naming-decisions.md) | Imenik preimenovanj, nevtralnih glede na opremo / arhitekturnih — dostavljenih in v teku |
|
||||
| [layered-soul](./layered-soul.md) | Kako Colibri danes uporablja repozitorij pregledanega konteksta layered-soul proti načrtovanemu |
|
||||
| [task-board](./task-board.md) | Točkovanje po zmožnostih, cron razporejanje, praznjenje vnosne vrste, podlaga SQLite |
|
||||
| [quality-gates](./quality-gates.md) | `ci-checks.sh` kot preverjanje pred združitvijo; zakaj je odmik prej dosegel `main` |
|
||||
| [quality-gates](./quality-gates.md) | `ci-checks.sh` kot preverjanje pred združitvijo; zakaj je odmik prej dosegel `main` |
|
||||
| [contracts](./contracts.md) | Stabilne JSON sheme (run-manifest, runtime-inventory, provider-smoke), zlati testi |
|
||||
| [store-schema](./store-schema.md) | Usklajevalna shema SQLite in disciplina migracij |
|
||||
| [external-mcp](./external-mcp.md) | Most MCP za urejevalnike + zunanji gostitelj stdio MCP; dovoljenja za branje/pisanje/zunanji-klic |
|
||||
| [operator-cli](./operator-cli.md) | CLI `colibri` kot tanek tipiziran odjemalec Unix vtičnice prek API ozadnjega procesa |
|
||||
| [external-mcp](./external-mcp.md) | Most MCP za urejevalnike + zunanji gostitelj stdio MCP; dovoljenja za branje/pisanje/zunanji-klic |
|
||||
| [operator-cli](./operator-cli.md) | CLI `colibri` kot tanek tipiziran odjemalec Unix vtičnice prek API ozadnjega procesa |
|
||||
| [tui](./tui.md) | Odjemalec terminalske nadzorne plošče (colibri-tui) proti avtomatu stanj colibri-glasspane |
|
||||
| [terminal](./terminal.md) | Odločitev o terminalski zmožnosti (Kitty, razširjeno poročanje tipk, prehod tmux, SSH terminfo) |
|
||||
| [runtime-inventory](./runtime-inventory.md) | Popis izvajalnega okolja gostitelja + bralnik statusa čuvaja; aditivne, bralne integracije |
|
||||
|
|
|
|||
|
|
@ -37,15 +37,15 @@ bridge and the CLI. It keeps Colibri headless-safe, which is required for an
|
|||
|
||||
→ `crates/colibri-glasspane-tui/src/main.rs` (socket resolution, refresh loop)
|
||||
|
||||
### TUI gets spawn/kill keys, not just read-only status
|
||||
### TUI gets spawn/stop keys, not just read-only status
|
||||
|
||||
You can spawn a local test agent (`s`) and kill the selected pane (`x`) from
|
||||
You can spawn a local test agent (`s`) and stop the selected pane (`x`) from
|
||||
the dashboard. That overlaps with commands the `colibri` CLI can already do,
|
||||
but the experience is different: a CLI command is one-shot; the TUI is a live
|
||||
supervision surface with a selected row and an immediate status bar.
|
||||
|
||||
We kept the action keys because the dashboard's job is to let an operator
|
||||
notice and react — spot a stalled pane and kill it without leaving the
|
||||
notice and react — spot a stalled pane and stop it without leaving the
|
||||
terminal.
|
||||
|
||||
→ `crates/colibri-glasspane-tui/src/main.rs` (`spawn_agent`, `kill_selected`)
|
||||
|
|
@ -79,7 +79,7 @@ should be revisited.
|
|||
| `q` / `Esc` | Quit, or close detail pane if open |
|
||||
| `r` | Refresh snapshot now |
|
||||
| `s` | Spawn a local `colibri-test-agent` |
|
||||
| `x` | Kill the selected pane |
|
||||
| `x` | Stop the selected pane |
|
||||
| `Enter` | Open/close the detail pane for the selected row |
|
||||
| `Tab` / `Shift-Tab` | Cycle through distinct sessions |
|
||||
| `j` / `k` or `↓` / `↑` | Navigate the pane table |
|
||||
|
|
@ -89,7 +89,7 @@ should be revisited.
|
|||
Use the TUI when:
|
||||
|
||||
- You want a live, auto-refreshing view of all panes.
|
||||
- You are picking a pane to inspect or kill visually.
|
||||
- You are picking a pane to inspect or stop visually.
|
||||
- You are on an SSH session with only a terminal.
|
||||
|
||||
Use the `colibri` CLI when:
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ doesn't have to re-derive it:
|
|||
|
||||
1. **The socket has no auth — the tailnet boundary is the auth.** With both
|
||||
hosts bridging the control plane, any tailnet peer that can reach either host
|
||||
can issue full control-plane commands (`spawn-agent`, `kill-agent`,
|
||||
can issue full control-plane commands (`spawn-agent`, `stop-agent`,
|
||||
`terminal-*`). Consider a Tailscale ACL scoping `:9190` to specific peers.
|
||||
2. **Socket path parity.** Both sides assume `/run/colibri/colibri.sock`
|
||||
(FreeBSD: `/var/run/colibri/colibri.sock`). domedog's daemon must be started
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue