diff --git a/.changeset/persistent-scheduled-sessions.md b/.changeset/persistent-scheduled-sessions.md new file mode 100644 index 00000000..101a7180 --- /dev/null +++ b/.changeset/persistent-scheduled-sessions.md @@ -0,0 +1,5 @@ +--- +"@jmfederico/pi-web": patch +--- + +Add first-class workspace automations on local and federated machines with manual, one-shot, interval, and timezone-aware cron triggers. Each target machine stores and executes its own schedules in fresh daemon-owned Pi sessions with fixed model and thinking settings, configurable timeouts, durable cancellation, immutable run history, and visual duration, token, and estimated-cost reporting. diff --git a/README.md b/README.md index 314c248b..b5272e0f 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ PI WEB lets you: - keep Pi Coding Agent sessions alive after browser disconnects; - run agents inside real repositories and git worktrees; - supervise multiple sessions in parallel; +- schedule workspace automations with model, timeout, cancellation, token, and estimated-cost visibility; - switch between laptop, phone, tablet, and desktop; - use a server, workstation, or remote dev box as your agent runtime; - manage projects, workspaces, files, terminals, sessions, and remote machines from one web UI. @@ -176,6 +177,7 @@ It is not a sandbox, permission system, or multi-tenant platform. Do not expose - [Install](https://pi-web.dev/install) - [Remote-first development](https://pi-web.dev/remote-first) - [Machines / fleet](https://pi-web.dev/machines) +- [Automations](https://pi-web.dev/automations) - [Configuration](https://pi-web.dev/config) - [Plugins](https://pi-web.dev/plugins) - [FAQ](https://pi-web.dev/faq) diff --git a/docs/assets/workspace-automations.png b/docs/assets/workspace-automations.png new file mode 100644 index 00000000..052ba827 Binary files /dev/null and b/docs/assets/workspace-automations.png differ diff --git a/docs/automations.html b/docs/automations.html new file mode 100644 index 00000000..c0f9801f --- /dev/null +++ b/docs/automations.html @@ -0,0 +1,145 @@ + + + + + + PI WEB Automations — scheduled Pi sessions, timeouts, and usage + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+

Durable agent work

+

Schedule Pi sessions. Keep control of every run.

+

Create workspace automations with explicit models and deadlines, then inspect which jobs ran, how long they took, and how many tokens and estimated dollars they consumed.

+
+
+ +
+
+ + +
+
+

Create, test, then enable

+

Select a machine, project, and workspace, then open Automations in the workspace panel. New definitions are saved disabled. Use Run now to test the exact revision before enabling its schedule.

+

Editing a job creates a new revision, pauses it, and requires another completed manual test. Each run gets a fresh, independent Pi session.

+
+ +
+

Machine-owned, federation-aware

+

Automations belong to the machine that owns the selected workspace. For a federated machine, the controlling gateway forwards automation requests while the remote pi-web-sessiond stores definitions and history, resolves its own models and workspace, and runs the schedule locally.

+

The browser and controlling gateway may disconnect or restart without stopping the remote schedule. The unversioned automations capability is the stable baseline federation contract; future optional operations will use separate feature capabilities. Definitions are not replicated and do not fail over automatically. To move one, recreate it against a destination workspace so that machine can validate its model and settings.

+
+ +
+

Manual and scheduled triggers

+
    +
  • Manual: run only on demand.
  • +
  • One shot: run once at a future timestamp.
  • +
  • Interval: use a fixed cadence of at least one minute.
  • +
  • Cron: use a six-field expression and an explicit IANA timezone.
  • +
+

The same automation never overlaps itself. Colliding scheduled occurrences are recorded as skipped instead of starting another session.

+
+ +
+

Visible model and thinking settings

+

Every automation card shows its model, provider, thinking policy, and timeout. Fixed models are validated again at dispatch and never silently replaced. Historical runs preserve the actual model and thinking level that were used.

+
+ +
+

Hard deadlines and durable cancellation

+

The default execution timeout is 60 minutes and can be set from one minute through 24 hours. PI WEB records cancellation intent before aborting the Pi session. If a soft abort does not settle within 15 seconds, it force-closes the runtime.

+

Runs become unknown when PI WEB cannot prove termination. Cancellation cannot undo external effects that already completed.

+
+ +
+

Run inbox and visual analytics

+

The workspace view includes a run timeline, median and p95 duration, outcomes, root-session tokens, estimated spend, per-automation usage totals, and links to resulting sessions.

+

Costs are model-pricing estimates unless a provider reports an authoritative charge. Unknown and partial usage stays visibly unknown rather than becoming zero. Current totals cover the fresh root session and do not silently include untracked subagents or paid external tools.

+
+ +
+

Daemon-owned persistence

+

Definitions, revisions, occurrences, attempts, cancellation, and terminal usage live in automations.sqlite under $PI_WEB_DATA_DIR. The daemon acquires an exclusive runtime-owner record before listening or recovering work, so a second live daemon using the same database refuses to start. Browser and web/API restarts reconstruct state from the long-lived session daemon.

+

After an unexpected daemon restart, queued runs remain eligible, while ambiguous starting or running attempts become unknown and are never blindly repeated.

+

The unreleased schedule-plugin prototype's .pi-web/scheduled-sessions.json format is not imported because it lacks the revision, attempt, cancellation, and accounting records required by this runtime. Development-branch prototype definitions must be recreated.

+
+ +
+

Know the boundary

+

A fresh session isolates conversational context, not the host. Automations run with the target machine's Pi configuration and OS-user permissions. PI WEB revalidates the registered project and workspace before dispatch, but prompts and tools can still exercise the permissions granted to Pi.

+ +
+
+
+
+
+ + + + + diff --git a/docs/automations.md b/docs/automations.md new file mode 100644 index 00000000..826c4188 --- /dev/null +++ b/docs/automations.md @@ -0,0 +1,118 @@ +# Automations + +PI WEB automations run prompts in fresh, independent Pi sessions on a selected machine. The long-lived session daemon owns scheduling and execution, so refreshing the browser or restarting the web/API service does not stop active runs. + +The target machine and its session daemon must be running to execute a due run. If they are offline at the scheduled time, the run cannot start then; after restart, PI WEB coalesces missed recurring occurrences rather than replaying every one. Local workspaces, credentials, browser bridges, and machine-local tools are not cloud resources and are unavailable while the target machine is offline. + +## Open the Automations view + +1. Select a machine, project, and workspace. +2. Open **Automations** in the workspace panel tabs. +3. Create a disabled draft. +4. Use **Run now** to test the exact revision. +5. Enable the schedule after the test run completes. + +Editing an automation creates a new revision, pauses its schedule, and requires another successful manual test before it can be enabled again. + +## Machine federation + +Automations belong to the machine that owns the selected workspace. For a federated remote machine, the controlling PI WEB gateway forwards definition, history, model, run, and cancellation requests to that machine. The remote machine's `pi-web-sessiond` stores the automation in its own `$PI_WEB_DATA_DIR`, resolves its own workspace and model configuration, and executes the schedule locally. + +The controlling browser and gateway do not need to remain online after a definition is saved. The target machine's session daemon remains the scheduler, so its automations continue through browser disconnects and web/API restarts. The **Automations** panel appears only when the selected machine reports that both its web runtime and session daemon support the `automations` capability. That capability is the baseline federation contract: compatible releases keep its routes and required fields backward-compatible, while future optional or incompatible operations must advertise a separate, feature-specific capability. + +Definitions and history are not replicated into the controlling gateway, and removing a machine registration does not delete automations on that machine. PI WEB does not automatically fail over or migrate an automation to another machine. To move one, recreate it explicitly against a destination workspace so that machine can revalidate the model and thinking settings and create its own revision. Session links from run history retain the machine, project, and workspace selection needed to open the resulting remote session. + +## Triggers + +Every automation can be run manually. Its configured trigger may be: + +- **Manual only** — runs only when you select **Run now**. +- **One shot** — runs once at a future timestamp and then disables itself. +- **Interval** — runs at a fixed interval. The minimum interval is one minute. +- **Cron** — uses a six-field cron expression, including seconds, with an explicit IANA timezone such as `Europe/Amsterdam` or `America/New_York`. + +Cron and interval schedules may run no more frequently than once per minute. If PI WEB was offline across several interval occurrences, it coalesces the backlog instead of replaying every missed run. The next occurrence is persisted by the session daemon. + +An automation never overlaps with another run of the same automation. A scheduled occurrence that collides with an active run is recorded as `skipped` with an overlap reason. + +## Model and thinking settings + +A job displays the model, provider, thinking policy, and timeout associated with its current revision. + +- A **fixed model** pins the provider and model ID. PI WEB validates it again when dispatching the run and does not silently fall back to a different model. +- **Follow machine default** resolves the model when each run starts. +- Thinking can use the model default or a fixed supported level. + +Run history freezes the actual model and thinking level used. Later edits or machine-default changes do not rewrite historical records. + +## Timeouts and cancellation + +The default execution timeout is 60 minutes. The supported range is one minute through 24 hours. + +Execution time starts when the fresh session begins running the prompt; queue delay is reported separately. The timeout deadline is persisted, so restarting the web/API service does not reset it. + +Select **Cancel** on an active run to request a durable cancellation. PI WEB: + +1. records the cancellation before contacting the session; +2. clears queued prompts and requests a soft Pi abort; +3. waits up to 15 seconds for the run to settle; +4. force-closes the runtime if it does not acknowledge the abort. + +A run becomes `unknown` when PI WEB cannot prove that cancellation completed. Cancellation cannot undo external effects that already happened, such as a pushed commit, sent message, deployment, or detached child process. + +Pausing an automation prevents future scheduled runs; it does not cancel an already active run. + +## Run history and visualizations + +The Automations view includes: + +- a run timeline showing which jobs ran and how long they took; +- completed, failed, timed-out, cancelled, skipped, and unknown outcomes; +- median and p95 execution duration; +- root-session input, output, and cache token totals; +- estimated cost trends and per-automation totals; +- model and thinking-level attribution; +- direct links to the resulting Pi sessions. + +Token and cost values are frozen when a run settles. Costs are estimates derived from Pi's model pricing unless a provider reports an authoritative charge. Missing or partial usage remains `unknown`; PI WEB does not display unknown cost as zero. + +Current totals cover the fresh root session. Usage from untracked subagents, detached child processes, and external paid tools is not silently included. Future inclusive accounting requires explicit run lineage across those boundaries. + +## Run statuses + +| Status | Meaning | +| --- | --- | +| `queued` | The occurrence is durably recorded and waiting for capacity. | +| `starting` | PI WEB is resolving the workspace and creating the fresh session. | +| `running` | The prompt is executing. | +| `cancelling` | A user cancellation or timeout is being applied. | +| `completed` | The root agent turn settled. This does not by itself prove a business outcome. | +| `failed` | Setup, model validation, provider execution, or the prompt failed. | +| `cancelled` | A user-requested abort settled. | +| `timed_out` | The execution deadline caused an abort that settled. | +| `skipped` | The occurrence was intentionally not started, currently because of overlap. | +| `unknown` | A restart or force-stop left the final outcome unprovable. | + +PI WEB intentionally uses `completed` rather than `succeeded`: an agent finishing a turn does not prove that tests passed, a deployment succeeded, or an external side effect occurred exactly once. + +## Persistence and restarts + +Automation definitions, revisions, occurrences, attempts, cancellation intent, terminal usage, and run history are stored in `automations.sqlite` under `$PI_WEB_DATA_DIR` (`~/.pi-web` by default). Only `pi-web-sessiond` opens this database. The daemon acquires an exclusive runtime-owner record before listening or recovering work; a second live daemon using the same database refuses to start, while a record left by a dead process is reclaimed. + +Browser and web/API restarts reconstruct their view from the daemon. After an unexpected session-daemon restart: + +- queued work remains eligible for dispatch; +- ambiguous starting, running, or cancelling attempts become `unknown`; +- PI WEB does not blindly repeat an attempt that may already have caused external effects. + +Changes to the automation runtime require a manual restart of `pi-web-sessiond.service`. + +The unreleased schedule-plugin prototype used `.pi-web/scheduled-sessions.json`. PI WEB does not import that experimental format because it lacks the immutable revision, attempt, cancellation, and accounting data required by this runtime. If you used the prototype from a development branch, recreate those definitions in the Automations view. + +## Security boundaries + +A fresh session separates conversational context; it is not a host security sandbox. A Git worktree, when used manually by a prompt, isolates changes but does not restrict filesystem, network, credentials, or process access. + +Automations run with the selected machine's Pi configuration and OS-user permissions. PI WEB validates the registered project/workspace identity before every dispatch and never accepts a caller-provided execution directory, but the underlying agent can still use the permissions granted to Pi and the operating-system account. + +Review prompts, model settings, tool permissions, network access, and credentials before enabling unattended schedules. Avoid embedding secrets directly in prompts. diff --git a/docs/index.html b/docs/index.html index bd5b502b..e0c58488 100644 --- a/docs/index.html +++ b/docs/index.html @@ -65,6 +65,7 @@