Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions AGENTS.md

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
and `fleet/retention.py`'s filename parsers, and `fleet/records.py`'s own
timestamp parser, now derive their run-id-matching regexes from the same
shared pattern.
- **Install hints for optional extras now print a command that works, and
upgrades stop uninstalling the extras you have** (#441). Every hint pointing
at an optional extra hardcoded `pip install 'conductor-cli[<extra>]'`, which
cannot work on the documented install path: `install.sh`/`install.ps1` create
a `uv tool` venv, which is not pip-managed, and `conductor-cli` is not
published to PyPI so pip has nothing to resolve against there. `conductor
fleet` without the `tui` extra, and the `aca` / `claude-agent-sdk` provider
errors, now resolve the command from the *detected* install context — `uv
tool install --force '<spec>'` for an install-script install, `uv sync
--inexact --extra <extra>` for a source checkout, and `pip install` as the
fallback, carrying the git URL you installed from when there is one so a
`pip`/`pipx`-from-git install resolves too. The suggested command reuses the
install source recorded for your install (so a fork or a local build is not
redirected upstream) and carries the extras you already have, because `uv
tool install --force` replaces the tool's entire requirement set and `uv
sync` is exact by default. A receipt that cannot be read is reported rather
than treated as "no extras" — in the hint, and in both install scripts,
which warn and carry on rather than either dropping the extras silently or
refusing to run.
For the same reason, `install.sh` and `install.ps1` now read the existing
install's `uv-receipt.toml` and rebuild the source as
`conductor-cli[<extras>] @ <source>`, so `conductor update` (which drives
them) no longer silently uninstalls `[tui]` or `[aca]` on upgrade — it also
names the extras it found before you commit. New `--extras <a,b>` /
`CONDUCTOR_INSTALL_EXTRAS` adds an extra during an install or upgrade
(rejecting one this package does not declare, which uv would otherwise
accept with a warning and a zero exit status), and `--no-preserve-extras` /
`CONDUCTOR_INSTALL_NO_PRESERVE_EXTRAS` drops back to a bare install.

- **Fleet Manager History no longer accumulates an entire retained event log
into memory to build one entry** (#436). `_read_full_log` now streams
parsed events one at a time instead of materializing them into a list
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ conductor update --apply

`--apply` launches the install script automatically — on Windows it opens in a new console window so you can watch progress; on macOS/Linux it replaces the current process. Either way, the running `conductor` exits before the installer touches the venv, so file locks release cleanly.

**Optional extras survive the upgrade.** `uv tool install --force` replaces the tool's entire requirement set, so an upgrade that named no extras used to silently uninstall `[tui]` or `[aca]`. Both install scripts now read the existing install's uv receipt and carry those extras forward, and `conductor update` tells you which ones it found. To add one during an upgrade, or to drop back to a bare install:

```bash
curl -sSfL https://aka.ms/conductor/install.sh | sh -s -- --extras tui
curl -sSfL https://aka.ms/conductor/install.sh | sh -s -- --no-preserve-extras
```

```powershell
$env:CONDUCTOR_INSTALL_EXTRAS = 'tui'; irm https://aka.ms/conductor/install.ps1 | iex
```

The install script handles file-lock safety (process detection, stale-file cleanup, and on Windows a rename-fallback when the venv directory can't be removed), retries with backoff, and verifies the installed version after install. If your shell ever gets into a bad state from a failed update, re-running the install script is always the right next step.

Conductor periodically checks GitHub for newer releases (cached for 24 hours under `~/.conductor/update-check.json`) and prints a one-line hint when one is available. To silence the hint permanently — for example when you manage upgrades through a package manager or company-mirrored install — set `CONDUCTOR_NO_UPDATE_CHECK=1` in your shell environment. The check is also skipped automatically for non-TTY invocations, `--silent` mode, the `update` subcommand, and `--help` / `--version`.
Expand Down Expand Up @@ -217,10 +228,17 @@ conductor stop
The dashboard shows you one run in depth. The **Fleet Manager** shows you *every* run at once — and it's where you go when something needs you. Launch it with `conductor fleet`:

```bash
pip install 'conductor-cli[tui]' # one-time: the TUI ships as an optional extra
# One-time: the TUI ships as an optional extra.
curl -sSfL https://aka.ms/conductor/install.sh | sh -s -- --extras tui
conductor fleet
```

> The install command depends on how you installed Conductor. Running `conductor fleet`
> without the extra prints the one that works on your machine — pinned to the version
> you are running and carrying any extras you already have, because `uv tool install
> --force` replaces the tool's whole requirement set. `conductor update` carries them
> forward for the same reason.

![Fleet Manager](docs/img/fleet-manager.png)

> **TUI = breadth. Dashboard = depth.**
Expand Down
31 changes: 22 additions & 9 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,21 +541,34 @@ bindings, and status vocabulary.
conductor fleet
```

The TUI requires the `tui` extra:

```bash
pip install 'conductor-cli[tui]'
```

Without it, the bare invocation prints an install hint and exits non-zero
rather than raising an `ImportError` traceback:
The TUI requires the `tui` extra. The install command depends on how
Conductor itself was installed, so the bare invocation prints the one that
works on your machine rather than guessing:

| How you installed | Command |
| --- | --- |
| The install script | `uv tool install --force 'conductor-cli[tui] @ git+https://github.com/microsoft/conductor.git@v<version>'` |
| A source checkout (`uv sync`) | `uv sync --extra tui` |
| Anything else — a wheel, `pip`/`pipx` from git, a system package | `pip install 'conductor-cli[tui]'` (with the git URL appended when there is one) |

`conductor-cli` is not on PyPI, so the `pip` form resolves only where pip
can already see an installed `conductor-cli` — never inside the uv tool venv
the install script creates. Without the extra, the bare invocation prints the
resolved command and exits non-zero rather than raising an `ImportError`
traceback:

```bash
$ conductor fleet
Error: the interactive fleet manager requires the 'tui' extra.
Install with: pip install 'conductor-cli[tui]'
Install with: uv tool install --force 'conductor-cli[tui] @ git+https://github.com/microsoft/conductor.git@v<version>'
```

The suggested command pins the running version and includes any extras
already installed, since `uv tool install --force` replaces the tool's
entire requirement set. `conductor update` and the install scripts preserve
them for the same reason — see
[Updating](../README.md#updating).

`conductor fleet list` and `conductor fleet prune` (below) need nothing
beyond a normal Conductor install — only the bare, no-subcommand
invocation needs `textual`.
Expand Down
42 changes: 35 additions & 7 deletions docs/fleet.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,47 @@ below is a separate, optional layer on top of it.
`conductor fleet list` and `conductor fleet prune` (documented in the
[CLI reference](cli-reference.md)) need nothing beyond a normal Conductor
install. The interactive TUI (`conductor fleet`, invoked with no
subcommand) additionally requires the `tui` extra:
subcommand) additionally requires the `tui` extra.

The command depends on how Conductor itself was installed, so
`conductor fleet` prints the right one for your machine rather than
guessing:

| How you installed | Command |
| --- | --- |
| The install script (`curl -sSfL https://aka.ms/conductor/install.sh \| sh`) | `uv tool install --force 'conductor-cli[tui] @ git+https://github.com/microsoft/conductor.git@v<version>'` |
| A source checkout (`uv sync`) | `uv sync --extra tui` |
| Anything else — a wheel, `pip`/`pipx` from git, a system package | `pip install 'conductor-cli[tui]'` (with the git URL appended when there is one) |

`conductor-cli` is **not** published to PyPI, so the `pip` form resolves
only where pip can already see an installed `conductor-cli` — never inside a
uv tool venv, which is what the install script creates. That is why the hint
is resolved rather than hardcoded (issue #441); for a `pip`/`pipx`-from-git
install it also appends the git URL you installed from, so the command
actually resolves.

Without the extra, `conductor fleet` prints that command and exits non-zero
rather than raising an `ImportError` traceback:

```bash
pip install 'conductor-cli[tui]'
$ conductor fleet
Error: the interactive fleet manager requires the 'tui' extra.
Install with: uv tool install --force 'conductor-cli[tui] @ git+https://github.com/microsoft/conductor.git@v<version>'
```

Without it, `conductor fleet` prints an install hint and exits non-zero
rather than raising an `ImportError` traceback:
The suggested command pins the version already running and carries any
extras you already have, because `uv tool install --force` replaces the
tool's whole requirement set — installing `[tui]` on a machine that had
`[aca]` would otherwise remove it.

For the same reason, `conductor update` (and the install scripts it drives)
preserve the extras recorded in the existing install, so an upgrade never
silently uninstalls the TUI. To install an extra as part of an upgrade, or
to drop back to a bare install:

```bash
$ conductor fleet
Error: the interactive fleet manager requires the 'tui' extra.
Install with: pip install 'conductor-cli[tui]'
curl -sSfL https://aka.ms/conductor/install.sh | sh -s -- --extras tui
curl -sSfL https://aka.ms/conductor/install.sh | sh -s -- --no-preserve-extras
```

`conductor fleet list` and `conductor fleet prune` are unaffected either
Expand Down
30 changes: 25 additions & 5 deletions docs/providers/aca.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,31 @@ the source design:

### 1. Install the azure-identity extra

The command depends on how Conductor itself was installed. `conductor run`
and `conductor doctor` print the right one when the extra is missing, so you
can also just run your workflow and copy what it says. (`conductor validate`
does not — the provider is constructed lazily, so the guard only fires once
an `aca`-backed agent actually runs.)

```bash
# Using uv (recommended)
uv add 'conductor-cli[aca]'
# Installed via the install script (uv tool install)
uv tool install --force 'conductor-cli[aca] @ git+https://github.com/microsoft/conductor.git@v<version>'

# A source checkout
uv sync --extra aca

# Using pip
# A wheel from a GitHub Release or a private index
pip install 'conductor-cli[aca]'
```

`conductor-cli` is not published to PyPI, so the `pip` form resolves only
where pip can already see an installed `conductor-cli` — never inside a uv
tool venv (issue #441). The `uv tool install` form must name every
extra you want to keep — `--force` replaces the tool's entire requirement
set, so `[aca]` alone would remove an already-installed `[tui]`. Conductor's
own hint builds that list for you, and `conductor update` preserves it
across upgrades.

This pins `azure-identity` plus `azure-core[aio]` (which pulls in `aiohttp`),
used to acquire a `dynamicsessions.io` bearer token via the async
`DefaultAzureCredential` for the *Session Executor* role — `azure-identity`
Expand Down Expand Up @@ -780,8 +797,11 @@ except the two that are pure narrowing (binding loopback, the

### `aca provider requires the azure-identity package`

Install the extra: `pip install 'conductor-cli[aca]'` (or `uv add
'conductor-cli[aca]'`).
Install the `aca` extra. The error's own `suggestion` carries the exact
command for how this Conductor was installed — see
[Install the azure-identity extra](#1-install-the-azure-identity-extra) for
the three forms and why a hardcoded `pip install 'conductor-cli[aca]'`
does not work on the documented install path.

### `'pool_endpoint' is required when name='aca'`

Expand Down
Loading
Loading