cargo-hauler 0.7.3 → 0.8.0
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.
- package/CHANGELOG.md +23 -0
- package/README.md +40 -30
- package/dist/.claude-plugin/marketplace.json +1 -1
- package/dist/.claude-plugin/plugin.json +1 -1
- package/dist/.codex-plugin/plugin.json +1 -1
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/INSTALL.md +1 -1
- package/dist/README.md +40 -30
- package/dist/agent-bundle.compile-evidence.json +1 -1
- package/dist/agent-bundle.manifest.json +1 -1
- package/dist/agent-bundle.package-compile-evidence.json +1 -1
- package/dist/bin/cargo-hauler-flight.mjs +211 -922
- package/dist/bin/cargo-hauler.mjs +255 -729
- package/dist/bin/hauler.js +219 -86
- package/dist/hooks/event-route-session-start.claude.mjs +2 -2
- package/dist/hooks/event-route-session-start.codex.mjs +2 -2
- package/dist/hooks/event-route-session-start.cursor.mjs +2 -2
- package/dist/hooks/event-route-stop.claude.mjs +2 -2
- package/dist/hooks/event-route-stop.codex.mjs +2 -2
- package/dist/hooks/event-route-stop.cursor.mjs +2 -2
- package/dist/hooks/event-route-tool-after.claude.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.claude.mjs +115 -64
- package/dist/hooks/event-route-tool-after.codex.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.codex.mjs +115 -64
- package/dist/hooks/event-route-tool-after.cursor.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-after.cursor.mjs +115 -64
- package/dist/hooks/event-route-tool-before.claude.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-before.codex.execute.mjs +2 -2
- package/dist/hooks/event-route-tool-before.cursor.execute.mjs +2 -2
- package/dist/hooks/hooks-flight.mjs +161 -122
- package/dist/install.mjs +1 -1
- package/dist/mcp/mcp-hauler-2b8242f9-flight.mjs +509 -393
- package/dist/mcp/mcp-hauler-2b8242f9.mjs +261 -111
- package/dist/mcp-apps/dashboard.html +2 -2
- package/dist/package.json +3 -3
- package/dist/plugin.json +1 -1
- package/dist/scripts/hauler.mjs +219 -86
- package/dist/skills/cargo-hauler/SKILL.md +4 -0
- package/dist/skills/hauler-dashboard/SKILL.md +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 970dbde: New `hauler_dashboard` MCP tool carries the dashboard App
|
|
8
|
+
(`ui://cargo-hauler/dashboard.html`): hosts that render MCP Apps open the
|
|
9
|
+
dashboard beside its result, populated from the same status payload the App
|
|
10
|
+
then polls through `hauler_status`. Its text result is one summary line plus
|
|
11
|
+
where the App and the text form are, so opening the dashboard never pastes the
|
|
12
|
+
status document into the model's context. `hauler_status` no longer advertises
|
|
13
|
+
the App and returns the queue, lanes, and tickets as text for the model, as
|
|
14
|
+
before. `hauler web` opens the App through `hauler_dashboard`. The
|
|
15
|
+
`hauler-dashboard` skill and the status document's dashboard line name the new
|
|
16
|
+
tool.
|
|
17
|
+
|
|
18
|
+
## 0.7.4
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 4267d0c: Keep read-only commands and MCP tools on a protocol-compatible running daemon, and defer automatic replacement for submissions until the older daemon is idle (#209).
|
|
23
|
+
|
|
24
|
+
Initialize the dashboard on every MCP Apps host — Codex, Claude, ChatGPT, VS Code/Cursor, and Goose — without host-specific origin exceptions (#212).
|
|
25
|
+
|
|
3
26
|
## 0.7.3
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -59,10 +59,11 @@ hauler install-shim # optional: cargo from script
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
Restart the host (or reload the window) so new sessions load the hooks. The
|
|
62
|
-
daemon starts on demand with the first brokered request; `hauler status`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
checkout? See
|
|
62
|
+
daemon starts on demand with the first brokered request; `hauler status` and
|
|
63
|
+
the `hauler_status` tool show what is running as text, and the
|
|
64
|
+
`hauler_dashboard` tool opens the dashboard in hosts that render MCP Apps.
|
|
65
|
+
Prefer the hosts' own plugin commands, or building from a checkout? See
|
|
66
|
+
[Install](#install).
|
|
66
67
|
|
|
67
68
|
The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
68
69
|
`scripts/hauler.mjs` or any path under `.claude/plugins/cache`,
|
|
@@ -85,13 +86,16 @@ The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
|
85
86
|
| `hauler result <ticket> [--full]` | A stored ticket in full: the settled 16 KiB output tail, or the whole live in-memory tail while it runs (not the status preview). The document names the full on-disk output log (`Full output: <path> (size)`) and `--json` carries it as `request.outputPath`; `--full` prints that whole log instead of the tail (the last ~768 KiB when it does not fit, with the path for the rest). |
|
|
86
87
|
| `hauler kill <ticket>` | Stop a ticket: drop it from the queue or SIGTERM (then SIGKILL) its cargo process group, freeing the lane. Riders return to their lane or fail with it. |
|
|
87
88
|
| `hauler request [--session ID] [--host HOST] [--cwd DIR] [--after TICKET …] -- <cargo …>` | Submit a background request and return its ticket, with where it landed in its lane (`queued behind cc-3281 (~13m)`, `waiting for cc-3281`, or `attached to cc-3281`). `--cwd` overrides the current CLI workspace; `--after` works as for `exec`. |
|
|
88
|
-
| `hauler daemon <run\|start\|stop\|status\|restart>` | Manage the daemon lifecycle. `stop` records its typed `shutdown` outcome in JSON and exits `0` only after a `shutting-down` acknowledgement followed by the original pid's exit, or when the daemon was already absent. Refusal, timeout, protocol error, disconnect before acknowledgement, and an acknowledged daemon still alive after 5 s exit `1`; `running` remains `true` when the original pid is alive and `null` when liveness could not be established. `restart` is the
|
|
89
|
+
| `hauler daemon <run\|start\|stop\|status\|restart>` | Manage the daemon lifecycle. `stop` records its typed `shutdown` outcome in JSON and exits `0` only after a `shutting-down` acknowledgement followed by the original pid's exit, or when the daemon was already absent. Refusal, timeout, protocol error, disconnect before acknowledgement, and an acknowledged daemon still alive after 5 s exit `1`; `running` remains `true` when the original pid is alive and `null` when liveness could not be established. `restart` is the explicit replacement path: it sends the graceful stop, waits up to 5 s for the old pid to exit, then starts a daemon from this install and prints both (`restarted: pid 741314 (0.6.0) → pid 742001 (0.6.1)`). Tickets in flight are not handed over: the old daemon settles them itself as it shuts down — `killed`, error `daemon shutdown` — and callers resubmit. Automatic upgrades are gentler: read-only commands and MCP/dashboard reads never retire a daemon; a protocol-compatible older daemon serves them directly. Submission commands replace an older daemon only after an idle status check; daemons from 0.7.4 onward hold admission closed while confirming that state, while 0.7.1–0.7.3 receive a client preflight. A busy or slow-to-retire daemon keeps serving the submission and emits one line such as `daemon 0.7.1 will be replaced by 0.7.3 when idle`. A truly incompatible daemon is reported with its pid and version instead of having its payload parsed. |
|
|
89
90
|
| `hauler install-shim [--dir DIR] [--real-cargo PATH] [--force]` | Install the optional PATH shim. |
|
|
90
|
-
| `hauler web [--port N] [--no-open]` | Open the dashboard from the checkout, npm package, or installed plugin. Agent Bundle's generated web command serves the built App against the plugin's own `hauler` server, opens it populated by `
|
|
91
|
+
| `hauler web [--port N] [--no-open]` | Open the dashboard from the checkout, npm package, or installed plugin. Agent Bundle's generated web command serves the built App against the plugin's own `hauler` server, opens it populated by `hauler_dashboard`, and stays in the foreground until Ctrl-C. In an MCP host, call `hauler_dashboard` instead. |
|
|
91
92
|
|
|
92
93
|
The `hauler` MCP server projects the same operations as `hauler_status`,
|
|
93
94
|
`hauler_log`, `hauler_last`, `hauler_await`, `hauler_result`, `hauler_kill`,
|
|
94
|
-
and `hauler_request`, with the same filters as the CLI
|
|
95
|
+
and `hauler_request`, with the same filters as the CLI, plus
|
|
96
|
+
`hauler_dashboard`, which carries the MCP App (below) and answers with one
|
|
97
|
+
summary line so opening the dashboard never pastes the status text into the
|
|
98
|
+
model's context. `hauler_status` and
|
|
95
99
|
`hauler_log` rows are the same bounded summaries (`outputPreview`, never a
|
|
96
100
|
tail); `hauler_result`, `hauler_await`, and `hauler_last` carry the whole
|
|
97
101
|
tail. `hauler_request.cwd` is an optional override: Agent Bundle's authoritative
|
|
@@ -102,7 +106,8 @@ workspace.
|
|
|
102
106
|
## Dashboard
|
|
103
107
|
|
|
104
108
|
The dashboard is an MCP App (`ui://cargo-hauler/dashboard.html`) attached to
|
|
105
|
-
`hauler_status
|
|
109
|
+
`hauler_dashboard`; `hauler_status` is the same data as text for the model and
|
|
110
|
+
never opens it. It shows contention and admission, in-flight and queued work
|
|
106
111
|
— each running row with the last line of its output preview, each ticket's
|
|
107
112
|
drawer with the whole tail fetched through `hauler_result` — metrics over
|
|
108
113
|
one-hour, 24-hour, and all-time windows, per-command timings, optional kache
|
|
@@ -448,9 +453,13 @@ ever flagged.
|
|
|
448
453
|
Tickets do not survive a daemon stop; runs are never handed over to the next
|
|
449
454
|
daemon. How a ticket ends depends on how the daemon went. A graceful stop —
|
|
450
455
|
`hauler daemon restart`, `hauler daemon stop`, or the automatic replacement of
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
456
|
+
an idle older daemon by the next `hauler exec`, `hauler request`, hook
|
|
457
|
+
submission, or `hauler daemon start` — is the shutdown request. Automatic
|
|
458
|
+
replacement checks for queued, running, executing, or attached work first;
|
|
459
|
+
0.7.4 and later daemons hold admission closed through that decision, while
|
|
460
|
+
0.7.1–0.7.3 receive the compatible client's status preflight. When a stop does
|
|
461
|
+
proceed, the old daemon settles every queued, running, and attached ticket
|
|
462
|
+
itself as it exits:
|
|
454
463
|
its cargo processes are terminated (SIGTERM, then SIGKILL after
|
|
455
464
|
`CARGO_HAULER_KILL_GRACE_MS`) and each row is marked `killed` with the error
|
|
456
465
|
`daemon shutdown`, so `hauler result cc-N` shows the ticket `killed` with
|
|
@@ -708,9 +717,9 @@ it from the umask:
|
|
|
708
717
|
under `XDG_RUNTIME_DIR`, `TMPDIR`, or the system temporary directory —
|
|
709
718
|
never directly into a shared temporary root. Two accounts sharing one
|
|
710
719
|
temporary root get separate directories. A daemon from an earlier install
|
|
711
|
-
still listening at the previous relocated path is
|
|
712
|
-
|
|
713
|
-
too before reporting nothing running
|
|
720
|
+
still listening at the previous relocated path is considered only by a
|
|
721
|
+
daemon-starting submission, never by a read; `hauler daemon stop` asks it
|
|
722
|
+
too before reporting nothing running.
|
|
714
723
|
|
|
715
724
|
Windows has neither POSIX modes nor uids, and its control endpoint is a
|
|
716
725
|
named pipe rather than a filesystem entry, so none of the above applies
|
|
@@ -728,14 +737,11 @@ there; state files keep the permissions the filesystem gives them.
|
|
|
728
737
|
`hauler_await` fail loudly when the daemon is unreachable instead of
|
|
729
738
|
reporting a ticket as not found; `hauler_status`, `hauler_log`, and
|
|
730
739
|
`hauler_last` read the ledger with the daemon marked `stopped` or
|
|
731
|
-
`unresponsive`.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
an older or unversioned client), reports the daemon as newer, and runs
|
|
737
|
-
cargo directly. If replacement fails, the reads report that failure
|
|
738
|
-
instead of reading the stale payload.
|
|
740
|
+
`unresponsive`. Reads never request daemon shutdown. They use an older
|
|
741
|
+
daemon when its wire-protocol identity is compatible; a truly incompatible
|
|
742
|
+
daemon is reported with its pid and version. A client older than the daemon
|
|
743
|
+
it finds — a session still on a previous plugin — keeps the directional
|
|
744
|
+
`DaemonNewer` behavior and never shuts it down.
|
|
739
745
|
- The state directory is not migrated between installs. Every rendered
|
|
740
746
|
document names the one in use (`state dir …` in the header; `stateRoot` in
|
|
741
747
|
`--json`), so a `CARGO_HAULER_STATE_DIR` change is visible on the next
|
|
@@ -782,7 +788,7 @@ src/
|
|
|
782
788
|
layout.tsx the hauler shell around every rendered route
|
|
783
789
|
providers/hauler-daemon.ts request-scoped daemon configuration
|
|
784
790
|
components/ typed components over pure view-models
|
|
785
|
-
mcp/hauler/tools/*.tsx hauler_status, _log, _last, _await, _result, _request, _kill
|
|
791
|
+
mcp/hauler/tools/*.tsx hauler_status, _dashboard, _log, _last, _await, _result, _request, _kill
|
|
786
792
|
mcp/hauler/tools/*.cli.ts each tool's `hauler <command>` projection (flags, positionals)
|
|
787
793
|
mcp/hauler/apps/dashboard.tsx the MCP App (ui://cargo-hauler/dashboard.html)
|
|
788
794
|
cli/daemon.ts the one plain CLI command
|
|
@@ -897,7 +903,8 @@ the same filter as its `session` field). Results carry
|
|
|
897
903
|
|
|
898
904
|
| Route | Surface | Document |
|
|
899
905
|
| --- | --- | --- |
|
|
900
|
-
| `tool:hauler/hauler_status` (`hauler status`) | queue, lanes, admission, kache, filters; bounded summary rows (`StatusRow`): `outputPreview` on running rows, never a tail | `StatusDocument
|
|
906
|
+
| `tool:hauler/hauler_status` (`hauler status`) | queue, lanes, admission, kache, filters; bounded summary rows (`StatusRow`): `outputPreview` on running rows, never a tail | `StatusDocument`, text for the model |
|
|
907
|
+
| `tool:hauler/hauler_dashboard` (`hauler web`) | the same `StatusResult`, `limit` only; the tool advertises the dashboard App (`_meta.ui.resourceUri`) so hosts open it beside the result | `DashboardDocument`: one summary line plus where the App and the text form are |
|
|
901
908
|
| `tool:hauler/hauler_log` (`hauler log`) | recent requests, as summary rows | `LogStream` → `LogDocument` |
|
|
902
909
|
| `tool:hauler/hauler_last` (`hauler last`) | most recent request, as a detail record with its tail | `LastDocument` |
|
|
903
910
|
| `tool:hauler/hauler_await` (`hauler await`) | long-poll a ticket (≤ 2 h) | `AwaitStream` → `AwaitDocument` |
|
|
@@ -921,8 +928,10 @@ resource URI it describes, so the document cannot drift from the surface.
|
|
|
921
928
|
#### Dashboard
|
|
922
929
|
|
|
923
930
|
`src/mcp/hauler/apps/dashboard.tsx` is the MCP App at
|
|
924
|
-
`ui://cargo-hauler/dashboard.html`, attached to `
|
|
925
|
-
render MCP Apps
|
|
931
|
+
`ui://cargo-hauler/dashboard.html`, attached to `hauler_dashboard` on hosts
|
|
932
|
+
that render MCP Apps; the opening result is that tool's status payload, and
|
|
933
|
+
`hauler_status` carries no App so its text reaches the model alone. It shows
|
|
934
|
+
contention and admission, in-flight and queued
|
|
926
935
|
work, metrics windows, optional kache data, lanes, and history, with a live
|
|
927
936
|
output drawer per ticket. The App polls `hauler_status` every 5 s; its rows
|
|
928
937
|
are summaries, so a running row's `outputPreview` shows as one line under the
|
|
@@ -978,7 +987,7 @@ pnpm run check # the gate
|
|
|
978
987
|
To see the dashboard outside an MCP host, run `node artifact/bin/cargo-hauler.mjs
|
|
979
988
|
web` after a build: the framework's `web` command (configured under `web` in
|
|
980
989
|
`agent-bundle.config.ts`) launches the artifact's own `hauler` server, calls
|
|
981
|
-
`
|
|
990
|
+
`hauler_dashboard` once so the App opens populated, approves `call-tool` so its
|
|
982
991
|
panels may poll, and serves `ui://cargo-hauler/dashboard.html` on a loopback
|
|
983
992
|
origin until Ctrl-C — so the data is the daemon's own. `pnpm run dev` and the
|
|
984
993
|
Workbench's MCP page preview the same App with live rebuilds. The repository
|
|
@@ -986,9 +995,10 @@ ships no preview harness of its own.
|
|
|
986
995
|
|
|
987
996
|
agent-bundle does not yet have an npm release; this repository pins the
|
|
988
997
|
[pkg.pr.new](https://pkg.pr.new) preview of Agent Bundle main commit
|
|
989
|
-
[`
|
|
990
|
-
|
|
991
|
-
for
|
|
998
|
+
[`e040c32`](https://github.com/ScriptedAlchemy/agent-bundle/commit/e040c32591d586eba72da6fa5c1bc1c881993000),
|
|
999
|
+
built from [Agent Bundle PR #779](https://github.com/ScriptedAlchemy/agent-bundle/pull/779),
|
|
1000
|
+
for `agent-bundle`, `@agent-bundle/runtime`, and their paired
|
|
1001
|
+
`rsc-markdown-stream` preview. `inspect` reports the
|
|
992
1002
|
`agent` component kind as unavailable on every host (agent-bundle G5
|
|
993
1003
|
deferral); this plugin defines no agents.
|
|
994
1004
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler-marketplace","owner":{"name":"cargo-hauler"},"plugins":[{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","source":"./","version":"0.
|
|
1
|
+
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler-marketplace","owner":{"name":"cargo-hauler"},"plugins":[{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","source":"./","version":"0.8.0"}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","version":"0.
|
|
1
|
+
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","name":"cargo-hauler","version":"0.8.0"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","hooks":"./.codex-plugin/hooks.json","interface":{"capabilities":["mcp","hooks","skills"],"category":"Productivity","defaultPrompt":["Help me use cargo-hauler."],"developerName":"cargo-hauler","displayName":"cargo-hauler","longDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","shortDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks."},"keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","mcpServers":"./.codex-plugin/mcp.json","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","skills":"./skills/","version":"0.
|
|
1
|
+
{"author":{"name":"cargo-hauler"},"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","hooks":"./.codex-plugin/hooks.json","interface":{"capabilities":["mcp","hooks","skills"],"category":"Productivity","defaultPrompt":["Help me use cargo-hauler."],"developerName":"cargo-hauler","displayName":"cargo-hauler","longDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","shortDescription":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks."},"keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","mcpServers":"./.codex-plugin/mcp.json","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","skills":"./skills/","version":"0.8.0"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","displayName":"cargo-hauler","hooks":"./.cursor-plugin/hooks.json","keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","mcpServers":"./.cursor-plugin/mcp.json","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","skills":"./skills/","version":"0.
|
|
1
|
+
{"description":"Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.","displayName":"cargo-hauler","hooks":"./.cursor-plugin/hooks.json","keywords":["cargo","rust","agent","mcp","claude-code","codex","cursor","build-orchestration"],"license":"MIT","mcpServers":"./.cursor-plugin/mcp.json","name":"cargo-hauler","repository":"https://github.com/ScriptedAlchemy/cargo-hauler","skills":"./skills/","version":"0.8.0"}
|
package/dist/INSTALL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Coalesce, schedule, and stream cargo so concurrent agent sessions share compiles instead of fighting locks.
|
|
4
4
|
|
|
5
|
-
Version: `0.
|
|
5
|
+
Version: `0.8.0`
|
|
6
6
|
|
|
7
7
|
Run these commands from this bundle directory. The bundle is self-contained: every command below is
|
|
8
8
|
a host command or the bundled installer, and nothing requires the `agent-bundle` CLI. Where that CLI is
|
package/dist/README.md
CHANGED
|
@@ -59,10 +59,11 @@ hauler install-shim # optional: cargo from script
|
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
Restart the host (or reload the window) so new sessions load the hooks. The
|
|
62
|
-
daemon starts on demand with the first brokered request; `hauler status`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
checkout? See
|
|
62
|
+
daemon starts on demand with the first brokered request; `hauler status` and
|
|
63
|
+
the `hauler_status` tool show what is running as text, and the
|
|
64
|
+
`hauler_dashboard` tool opens the dashboard in hosts that render MCP Apps.
|
|
65
|
+
Prefer the hosts' own plugin commands, or building from a checkout? See
|
|
66
|
+
[Install](#install).
|
|
66
67
|
|
|
67
68
|
The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
68
69
|
`scripts/hauler.mjs` or any path under `.claude/plugins/cache`,
|
|
@@ -85,13 +86,16 @@ The CLI is `hauler` on PATH from `npm i -g cargo-hauler`. Never run
|
|
|
85
86
|
| `hauler result <ticket> [--full]` | A stored ticket in full: the settled 16 KiB output tail, or the whole live in-memory tail while it runs (not the status preview). The document names the full on-disk output log (`Full output: <path> (size)`) and `--json` carries it as `request.outputPath`; `--full` prints that whole log instead of the tail (the last ~768 KiB when it does not fit, with the path for the rest). |
|
|
86
87
|
| `hauler kill <ticket>` | Stop a ticket: drop it from the queue or SIGTERM (then SIGKILL) its cargo process group, freeing the lane. Riders return to their lane or fail with it. |
|
|
87
88
|
| `hauler request [--session ID] [--host HOST] [--cwd DIR] [--after TICKET …] -- <cargo …>` | Submit a background request and return its ticket, with where it landed in its lane (`queued behind cc-3281 (~13m)`, `waiting for cc-3281`, or `attached to cc-3281`). `--cwd` overrides the current CLI workspace; `--after` works as for `exec`. |
|
|
88
|
-
| `hauler daemon <run\|start\|stop\|status\|restart>` | Manage the daemon lifecycle. `stop` records its typed `shutdown` outcome in JSON and exits `0` only after a `shutting-down` acknowledgement followed by the original pid's exit, or when the daemon was already absent. Refusal, timeout, protocol error, disconnect before acknowledgement, and an acknowledged daemon still alive after 5 s exit `1`; `running` remains `true` when the original pid is alive and `null` when liveness could not be established. `restart` is the
|
|
89
|
+
| `hauler daemon <run\|start\|stop\|status\|restart>` | Manage the daemon lifecycle. `stop` records its typed `shutdown` outcome in JSON and exits `0` only after a `shutting-down` acknowledgement followed by the original pid's exit, or when the daemon was already absent. Refusal, timeout, protocol error, disconnect before acknowledgement, and an acknowledged daemon still alive after 5 s exit `1`; `running` remains `true` when the original pid is alive and `null` when liveness could not be established. `restart` is the explicit replacement path: it sends the graceful stop, waits up to 5 s for the old pid to exit, then starts a daemon from this install and prints both (`restarted: pid 741314 (0.6.0) → pid 742001 (0.6.1)`). Tickets in flight are not handed over: the old daemon settles them itself as it shuts down — `killed`, error `daemon shutdown` — and callers resubmit. Automatic upgrades are gentler: read-only commands and MCP/dashboard reads never retire a daemon; a protocol-compatible older daemon serves them directly. Submission commands replace an older daemon only after an idle status check; daemons from 0.7.4 onward hold admission closed while confirming that state, while 0.7.1–0.7.3 receive a client preflight. A busy or slow-to-retire daemon keeps serving the submission and emits one line such as `daemon 0.7.1 will be replaced by 0.7.3 when idle`. A truly incompatible daemon is reported with its pid and version instead of having its payload parsed. |
|
|
89
90
|
| `hauler install-shim [--dir DIR] [--real-cargo PATH] [--force]` | Install the optional PATH shim. |
|
|
90
|
-
| `hauler web [--port N] [--no-open]` | Open the dashboard from the checkout, npm package, or installed plugin. Agent Bundle's generated web command serves the built App against the plugin's own `hauler` server, opens it populated by `
|
|
91
|
+
| `hauler web [--port N] [--no-open]` | Open the dashboard from the checkout, npm package, or installed plugin. Agent Bundle's generated web command serves the built App against the plugin's own `hauler` server, opens it populated by `hauler_dashboard`, and stays in the foreground until Ctrl-C. In an MCP host, call `hauler_dashboard` instead. |
|
|
91
92
|
|
|
92
93
|
The `hauler` MCP server projects the same operations as `hauler_status`,
|
|
93
94
|
`hauler_log`, `hauler_last`, `hauler_await`, `hauler_result`, `hauler_kill`,
|
|
94
|
-
and `hauler_request`, with the same filters as the CLI
|
|
95
|
+
and `hauler_request`, with the same filters as the CLI, plus
|
|
96
|
+
`hauler_dashboard`, which carries the MCP App (below) and answers with one
|
|
97
|
+
summary line so opening the dashboard never pastes the status text into the
|
|
98
|
+
model's context. `hauler_status` and
|
|
95
99
|
`hauler_log` rows are the same bounded summaries (`outputPreview`, never a
|
|
96
100
|
tail); `hauler_result`, `hauler_await`, and `hauler_last` carry the whole
|
|
97
101
|
tail. `hauler_request.cwd` is an optional override: Agent Bundle's authoritative
|
|
@@ -102,7 +106,8 @@ workspace.
|
|
|
102
106
|
## Dashboard
|
|
103
107
|
|
|
104
108
|
The dashboard is an MCP App (`ui://cargo-hauler/dashboard.html`) attached to
|
|
105
|
-
`hauler_status
|
|
109
|
+
`hauler_dashboard`; `hauler_status` is the same data as text for the model and
|
|
110
|
+
never opens it. It shows contention and admission, in-flight and queued work
|
|
106
111
|
— each running row with the last line of its output preview, each ticket's
|
|
107
112
|
drawer with the whole tail fetched through `hauler_result` — metrics over
|
|
108
113
|
one-hour, 24-hour, and all-time windows, per-command timings, optional kache
|
|
@@ -448,9 +453,13 @@ ever flagged.
|
|
|
448
453
|
Tickets do not survive a daemon stop; runs are never handed over to the next
|
|
449
454
|
daemon. How a ticket ends depends on how the daemon went. A graceful stop —
|
|
450
455
|
`hauler daemon restart`, `hauler daemon stop`, or the automatic replacement of
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
456
|
+
an idle older daemon by the next `hauler exec`, `hauler request`, hook
|
|
457
|
+
submission, or `hauler daemon start` — is the shutdown request. Automatic
|
|
458
|
+
replacement checks for queued, running, executing, or attached work first;
|
|
459
|
+
0.7.4 and later daemons hold admission closed through that decision, while
|
|
460
|
+
0.7.1–0.7.3 receive the compatible client's status preflight. When a stop does
|
|
461
|
+
proceed, the old daemon settles every queued, running, and attached ticket
|
|
462
|
+
itself as it exits:
|
|
454
463
|
its cargo processes are terminated (SIGTERM, then SIGKILL after
|
|
455
464
|
`CARGO_HAULER_KILL_GRACE_MS`) and each row is marked `killed` with the error
|
|
456
465
|
`daemon shutdown`, so `hauler result cc-N` shows the ticket `killed` with
|
|
@@ -708,9 +717,9 @@ it from the umask:
|
|
|
708
717
|
under `XDG_RUNTIME_DIR`, `TMPDIR`, or the system temporary directory —
|
|
709
718
|
never directly into a shared temporary root. Two accounts sharing one
|
|
710
719
|
temporary root get separate directories. A daemon from an earlier install
|
|
711
|
-
still listening at the previous relocated path is
|
|
712
|
-
|
|
713
|
-
too before reporting nothing running
|
|
720
|
+
still listening at the previous relocated path is considered only by a
|
|
721
|
+
daemon-starting submission, never by a read; `hauler daemon stop` asks it
|
|
722
|
+
too before reporting nothing running.
|
|
714
723
|
|
|
715
724
|
Windows has neither POSIX modes nor uids, and its control endpoint is a
|
|
716
725
|
named pipe rather than a filesystem entry, so none of the above applies
|
|
@@ -728,14 +737,11 @@ there; state files keep the permissions the filesystem gives them.
|
|
|
728
737
|
`hauler_await` fail loudly when the daemon is unreachable instead of
|
|
729
738
|
reporting a ticket as not found; `hauler_status`, `hauler_log`, and
|
|
730
739
|
`hauler_last` read the ledger with the daemon marked `stopped` or
|
|
731
|
-
`unresponsive`.
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
an older or unversioned client), reports the daemon as newer, and runs
|
|
737
|
-
cargo directly. If replacement fails, the reads report that failure
|
|
738
|
-
instead of reading the stale payload.
|
|
740
|
+
`unresponsive`. Reads never request daemon shutdown. They use an older
|
|
741
|
+
daemon when its wire-protocol identity is compatible; a truly incompatible
|
|
742
|
+
daemon is reported with its pid and version. A client older than the daemon
|
|
743
|
+
it finds — a session still on a previous plugin — keeps the directional
|
|
744
|
+
`DaemonNewer` behavior and never shuts it down.
|
|
739
745
|
- The state directory is not migrated between installs. Every rendered
|
|
740
746
|
document names the one in use (`state dir …` in the header; `stateRoot` in
|
|
741
747
|
`--json`), so a `CARGO_HAULER_STATE_DIR` change is visible on the next
|
|
@@ -782,7 +788,7 @@ src/
|
|
|
782
788
|
layout.tsx the hauler shell around every rendered route
|
|
783
789
|
providers/hauler-daemon.ts request-scoped daemon configuration
|
|
784
790
|
components/ typed components over pure view-models
|
|
785
|
-
mcp/hauler/tools/*.tsx hauler_status, _log, _last, _await, _result, _request, _kill
|
|
791
|
+
mcp/hauler/tools/*.tsx hauler_status, _dashboard, _log, _last, _await, _result, _request, _kill
|
|
786
792
|
mcp/hauler/tools/*.cli.ts each tool's `hauler <command>` projection (flags, positionals)
|
|
787
793
|
mcp/hauler/apps/dashboard.tsx the MCP App (ui://cargo-hauler/dashboard.html)
|
|
788
794
|
cli/daemon.ts the one plain CLI command
|
|
@@ -897,7 +903,8 @@ the same filter as its `session` field). Results carry
|
|
|
897
903
|
|
|
898
904
|
| Route | Surface | Document |
|
|
899
905
|
| --- | --- | --- |
|
|
900
|
-
| `tool:hauler/hauler_status` (`hauler status`) | queue, lanes, admission, kache, filters; bounded summary rows (`StatusRow`): `outputPreview` on running rows, never a tail | `StatusDocument
|
|
906
|
+
| `tool:hauler/hauler_status` (`hauler status`) | queue, lanes, admission, kache, filters; bounded summary rows (`StatusRow`): `outputPreview` on running rows, never a tail | `StatusDocument`, text for the model |
|
|
907
|
+
| `tool:hauler/hauler_dashboard` (`hauler web`) | the same `StatusResult`, `limit` only; the tool advertises the dashboard App (`_meta.ui.resourceUri`) so hosts open it beside the result | `DashboardDocument`: one summary line plus where the App and the text form are |
|
|
901
908
|
| `tool:hauler/hauler_log` (`hauler log`) | recent requests, as summary rows | `LogStream` → `LogDocument` |
|
|
902
909
|
| `tool:hauler/hauler_last` (`hauler last`) | most recent request, as a detail record with its tail | `LastDocument` |
|
|
903
910
|
| `tool:hauler/hauler_await` (`hauler await`) | long-poll a ticket (≤ 2 h) | `AwaitStream` → `AwaitDocument` |
|
|
@@ -921,8 +928,10 @@ resource URI it describes, so the document cannot drift from the surface.
|
|
|
921
928
|
#### Dashboard
|
|
922
929
|
|
|
923
930
|
`src/mcp/hauler/apps/dashboard.tsx` is the MCP App at
|
|
924
|
-
`ui://cargo-hauler/dashboard.html`, attached to `
|
|
925
|
-
render MCP Apps
|
|
931
|
+
`ui://cargo-hauler/dashboard.html`, attached to `hauler_dashboard` on hosts
|
|
932
|
+
that render MCP Apps; the opening result is that tool's status payload, and
|
|
933
|
+
`hauler_status` carries no App so its text reaches the model alone. It shows
|
|
934
|
+
contention and admission, in-flight and queued
|
|
926
935
|
work, metrics windows, optional kache data, lanes, and history, with a live
|
|
927
936
|
output drawer per ticket. The App polls `hauler_status` every 5 s; its rows
|
|
928
937
|
are summaries, so a running row's `outputPreview` shows as one line under the
|
|
@@ -978,7 +987,7 @@ pnpm run check # the gate
|
|
|
978
987
|
To see the dashboard outside an MCP host, run `node artifact/bin/cargo-hauler.mjs
|
|
979
988
|
web` after a build: the framework's `web` command (configured under `web` in
|
|
980
989
|
`agent-bundle.config.ts`) launches the artifact's own `hauler` server, calls
|
|
981
|
-
`
|
|
990
|
+
`hauler_dashboard` once so the App opens populated, approves `call-tool` so its
|
|
982
991
|
panels may poll, and serves `ui://cargo-hauler/dashboard.html` on a loopback
|
|
983
992
|
origin until Ctrl-C — so the data is the daemon's own. `pnpm run dev` and the
|
|
984
993
|
Workbench's MCP page preview the same App with live rebuilds. The repository
|
|
@@ -986,9 +995,10 @@ ships no preview harness of its own.
|
|
|
986
995
|
|
|
987
996
|
agent-bundle does not yet have an npm release; this repository pins the
|
|
988
997
|
[pkg.pr.new](https://pkg.pr.new) preview of Agent Bundle main commit
|
|
989
|
-
[`
|
|
990
|
-
|
|
991
|
-
for
|
|
998
|
+
[`e040c32`](https://github.com/ScriptedAlchemy/agent-bundle/commit/e040c32591d586eba72da6fa5c1bc1c881993000),
|
|
999
|
+
built from [Agent Bundle PR #779](https://github.com/ScriptedAlchemy/agent-bundle/pull/779),
|
|
1000
|
+
for `agent-bundle`, `@agent-bundle/runtime`, and their paired
|
|
1001
|
+
`rsc-markdown-stream` preview. `inspect` reports the
|
|
992
1002
|
`agent` component kind as unavailable on every host (agent-bundle G5
|
|
993
1003
|
deferral); this plugin defines no agents.
|
|
994
1004
|
|