@edgehero/pi-dispatch-admin 1.3.0 → 1.5.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/README.md +8 -6
- package/dist/index.mjs +1347 -497
- package/package.json +1 -1
- package/skills/operate-pi-dispatch/SKILL.md +67 -6
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# pi-dispatch: run the pi coding agent as a self-hosted service
|
|
6
6
|
|
|
7
|
-
**Let a coding agent work on your repositories while you are not watching, without surprise bills and without giving it the keys to your machine.** [pi](https://github.com/earendil-works/pi) is a superb coding agent, but it has no job queue, no spend limit, and, by its own README, no permission system. pi-dispatch adds exactly those, so you can run pi unattended and safely: on a cron schedule, on your repo's issues and PRs, or straight from the CLI. Every job runs in an isolated container, spend is bounded before a single token is spent, and everything the agent did (and what it cost) is recorded, graphed and priced for you. On a forge you stay in the loop at both ends: a job starts only when someone with write access to the repo asks for one, by a label, an `@pi` comment or a review, and what comes back is a pull request you review and land, because pi-dispatch never merges anything. This is not another agent to weigh against the one you already use; it is the queue, the budget and the box for the pi you already run.
|
|
7
|
+
**Let a coding agent work on your repositories while you are not watching, without surprise bills and without giving it the keys to your machine.** [pi](https://github.com/earendil-works/pi) is a superb coding agent, but it has no job queue, no spend limit, and, by its own README, no permission system. pi-dispatch adds exactly those, so you can run pi unattended and safely: on a cron schedule, on your repo's issues and PRs, or straight from the CLI. Every job runs in an isolated container, spend is bounded before a single token is spent (per deployment and per-repo or per-folder), and everything the agent did (and what it cost) is recorded, graphed and priced for you. On a forge you stay in the loop at both ends: a job starts only when someone with write access to the repo asks for one, by a label, an `@pi` comment or a review, and what comes back is a pull request you review and land, because pi-dispatch never merges anything. This is not another agent to weigh against the one you already use; it is the queue, the budget and the box for the pi you already run.
|
|
8
8
|
|
|
9
9
|
> This npm package, **`@edgehero/pi-dispatch-admin`**, is the **operator console** (a pi extension). The service itself is `@edgehero/pi-dispatch` (worker + CLI) and `@edgehero/pi-dispatch-receiver` (the webhook edge); the [main repo](https://github.com/edgehero/pi-dispatch) has the container image, docs, and SECURITY.md.
|
|
10
10
|
|
|
@@ -42,9 +42,10 @@ Every trigger is one `{ on, run }` entry in a single `triggers.json`, read live
|
|
|
42
42
|
| `cron` | your schedule | nothing: a schedule is its own condition | the `task` written in the file |
|
|
43
43
|
| `label` | a label on an **issue** (or an Azure work item), never a pull request | a label predicate: `any`, `all`, or `none` (which can suppress a fire, never cause one) | the issue title and body |
|
|
44
44
|
| `comment` | a comment containing your phrase, for example `@pi` | the phrase, and one comment trigger per forge | the comment body, plus the issue title and body |
|
|
45
|
-
| `pull_request` | a PR or MR event | `action`, in your forge's own words, plus the same label predicate | the PR title and body |
|
|
45
|
+
| `pull_request` | a PR or MR event, including its close (the close word rides alone, never mixed with other actions; on GitHub and Forgejo a merged PR counts as closed, on GitLab only an explicit close fires it) | `action`, in your forge's own words, plus the same label predicate; on a close-only rule, `number` and `once` instead | the PR title and body |
|
|
46
|
+
| `issue` | an issue closing | `action` (the forge's close word), `number` to pin one issue, `once: true` for a one-shot that spends itself after a single run | the issue title and body |
|
|
46
47
|
|
|
47
|
-
Four forges: GitHub, GitLab, Forgejo (and Gitea), Azure DevOps. **Who may fire a trigger is your forge's decision, not this service's**: on GitHub the label *is* the approval, because only collaborators can apply one, while GitLab, Forgejo and Azure resolve the actor's permission through their APIs. Each forge's action vocabulary is validated when the file loads, so a word from the wrong forge is refused instead of silently never matching.
|
|
48
|
+
Four forges: GitHub, GitLab, Forgejo (and Gitea), Azure DevOps. **Who may fire a trigger is your forge's decision, not this service's**: on GitHub the label *is* the approval, because only collaborators can apply one, while GitLab, Forgejo and Azure resolve the actor's permission through their APIs. A close trigger is gated on the actor who **closed** the item, resolved the same way (Azure has no close trigger yet: it refuses at load rather than never matching). Each forge's action vocabulary is validated when the file loads, so a word from the wrong forge is refused instead of silently never matching.
|
|
48
49
|
|
|
49
50
|
**Flows, and workflows.** `run.flow` names a skill committed to the target repo at `.pi/skills/<flow>/SKILL.md`, read from the **default branch**, so the repo owns the prompt and merging it is the repo's consent. A skill may call other skills, which is already a workflow. For typed multi-stage ones, a pi extension such as `@juicesharp/rpiv-workflow` can be staged into the deployment: pinned to an exact version, installed on your host (never at job time, since jobs run offline), loaded in every container, and declinable per trigger. Anything you already installed with `pi install` is staged automatically, at the version your host has, so there is nothing to declare twice. `run.command` is the second entry point: instead of a flow, a trigger may name a registered command a staged extension provides (`"command": "wf run nightly"`), and the job's whole prompt is that dispatch line, handled by the extension with no model turn in between. It picks which vetted command dispatches, never what code runs, and it is never AI-triggerable: job chaining refuses any request naming one, and `dispatch_run` cannot express one.
|
|
50
51
|
|
|
@@ -55,7 +56,7 @@ Four forges: GitHub, GitLab, Forgejo (and Gitea), Azure DevOps. **Who may fire a
|
|
|
55
56
|
One command puts a live TUI over the whole deployment:
|
|
56
57
|
|
|
57
58
|
<p align="center">
|
|
58
|
-
<img src="https://raw.githubusercontent.com/edgehero/pi-dispatch/main/docs/images/dispatch-dashboard.png?v=1.0.0" alt="The /dispatch panel: status, spend meters, triggers (including a command trigger shown as its /name), pause windows, runs, and settings" width="820">
|
|
59
|
+
<img src="https://raw.githubusercontent.com/edgehero/pi-dispatch/main/docs/images/dispatch-dashboard.png?v=1.0.0" alt="The /dispatch panel: status, spend meters, triggers (including a command trigger shown as its /name), pause windows, scoped limits, runs, and settings" width="820">
|
|
59
60
|
</p>
|
|
60
61
|
|
|
61
62
|
- **Status and spend.** Queue and worker state, day/week/month spend meters, a daily token counter, and a run-history table with per-job tokens and cost.
|
|
@@ -65,9 +66,10 @@ One command puts a live TUI over the whole deployment:
|
|
|
65
66
|
<img src="https://raw.githubusercontent.com/edgehero/pi-dispatch/main/docs/images/insights-view.png?v=1.0.0" alt="The insights page: KPI tiles, a plan verdict card, the daily spend chart, the four breakdowns with plan-covered buckets drawn as chips instead of dollar bars, and the topology with spend badges and tier-resolved flows" width="820">
|
|
66
67
|
</p>
|
|
67
68
|
|
|
68
|
-
- **Triggers, editable live.** cron, label, comment and
|
|
69
|
+
- **Triggers, editable live.** cron, label, comment, pull_request and issue triggers with colored drill-ins showing what fires each one, what it runs, and its trust model. Added, edited and deleted without a restart. A one-shot (`once: true`) shows armed or spent in its drill-in: a spent entry stays in the list, matches nothing, and re-arms when the operator deletes its `on.disarmed` mark from the file. Triggers that run third-party code or a custom image are badged; opting in or out of either stays an edit to the reviewed `triggers.json`, which neither the console nor a model-callable tool will make for you.
|
|
69
70
|
- **Quiet hours.** Scheduled pause windows per folder or repo: defer runs between certain times, timezone-aware, and resume automatically. Deferred, never dropped, at zero budget cost.
|
|
70
|
-
- **
|
|
71
|
+
- **Scoped limits.** Per-repo or per-folder job caps (day, week, month) refused before any spend, plus a per-scope concurrency ceiling enforced by deferral. Local jobs also hold a one-job-per-folder guard that is always on and has no switch (it lives in the worker process, and one worker per docker daemon is the supported shape), because two agents editing one working tree race each other with no gate and no undo.
|
|
72
|
+
- **AI-operable, with a human gate.** Model-callable tools let an agent change limits (global and scoped) and manage triggers and pause windows, and every **config** write pops an operator confirmation the model cannot answer, refusing outright when no operator is present. Two tools sit outside that gate on purpose: `dispatch_pause` and `dispatch_resume` write durable queue state but are reversible and spend nothing, so they carry no confirm. One more sits outside it and is **not** money-safe: `dispatch_run` enqueues a **paid** run that edits a local folder in place with no undo, bounded instead by six independent limits (the `PI_DISPATCH_RUN_ROOTS` folder allowlist, a committed per-flow `ai-trigger: allow` opt-in read at a pre-agent SHA, a dirty-tree refusal with no force option, no spend knobs on the tool, a per-hour rate limit, and the worker's daily cap). Commands sit outside its reach entirely: `dispatch_run` speaks flows only, and a chained job's request naming a `command` is refused outright, with no opt-in. Read [`SECURITY.md`](https://github.com/edgehero/pi-dispatch/blob/main/SECURITY.md) on that one before you enable it. The bundled `operate-pi-dispatch` skill teaches the agent those gates.
|
|
71
73
|
- **Logs stay put.** Raw container output renders only in the overlay viewer, never into model context.
|
|
72
74
|
|
|
73
75
|
## Install
|