diff --git a/.changeset/clear-session-message-queue.md b/.changeset/clear-session-message-queue.md
new file mode 100644
index 0000000..32eb429
--- /dev/null
+++ b/.changeset/clear-session-message-queue.md
@@ -0,0 +1,5 @@
+---
+"@jmfederico/pi-web": patch
+---
+
+Add a capability-aware Clear queue action that removes queued session messages, including prompts held during compaction, without stopping active work.
diff --git a/.changeset/generic-agent-runtime-config.md b/.changeset/generic-agent-runtime-config.md
index 359a42d..1156ff9 100644
--- a/.changeset/generic-agent-runtime-config.md
+++ b/.changeset/generic-agent-runtime-config.md
@@ -2,4 +2,4 @@
"@jmfederico/pi-web": patch
---
-Add configurable agent runtime settings so PI WEB can use alternate Pi-compatible commands and isolated agent state/session directories, with web-side status and plugin views re-reading saved config.
+Add selectable Pi-compatible agent profiles and companion CLIs for isolated auth, models, settings, sessions, Pi packages, plugins, diagnostics, and safe update commands. Settings shows when a session-daemon restart is required, and mixed-version remote saves fail instead of reporting false success. The embedded runtime remains the bundled Pi SDK.
diff --git a/.changeset/yield-to-tracked-subsessions.md b/.changeset/yield-to-tracked-subsessions.md
new file mode 100644
index 0000000..29e8089
--- /dev/null
+++ b/.changeset/yield-to-tracked-subsessions.md
@@ -0,0 +1,5 @@
+---
+"@jmfederico/pi-web": patch
+---
+
+Add explicit tracked-subsession yielding with no-poll wake-up guidance, remaining-child status, and clear boundaries around child output.
diff --git a/docs/config.html b/docs/config.html
index 9cce628..e1c97d4 100644
--- a/docs/config.html
+++ b/docs/config.html
@@ -81,7 +81,7 @@
PI WEB configuration covers the machine-local and project-local settings you usually need: bind address,
trusted development-host settings, UI preferences, PI WEB plugin enablement, file-explorer path access,
- manual upload defaults, upload limits, agent runtime selection, and session-daemon tools.
+ manual upload defaults, upload limits, Pi-compatible agent profiles and companion CLIs, and session-daemon tools.
Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected
- machine for config that affects work running there: agent runtime selection, session daemon tools,
- PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway:
+ machine for config that affects work running there: the Pi-compatible agent profile and companion CLI,
+ session daemon tools, PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway:
keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts. Remote servers
that do not advertise selected-machine settings support report those settings as unavailable instead of
silently falling back to the gateway.
@@ -334,7 +334,7 @@
Restart web/API and session daemon on that machine
-
Agent CLI command
+
Companion CLI command
agent.command
PI_WEB_AGENT_COMMAND
Global/session daemon
@@ -342,12 +342,12 @@
Restart session daemon on that machine; affects doctor/status/update checks
-
Agent state directory
+
Agent profile state directory
agent.dir
PI_WEB_AGENT_DIR (PI_CODING_AGENT_DIR for Pi compatibility)
Global/session daemon
Not supported locally
-
Restart session daemon on that machine; affects auth, models, settings, and sessions
+
Restart session daemon on that machine; affects auth, models, settings, sessions, Pi packages, and package-backed plugins
Agent can spawn sessions
@@ -455,7 +455,7 @@
Restart web/API; advanced state override
-
Agent session storage directory
+
Agent profile session storage directory
—
PI_WEB_AGENT_SESSION_DIR (PI_CODING_AGENT_SESSION_DIR for Pi compatibility)
PI_WEB_AGENT_DIR (PI_CODING_AGENT_DIR for Pi compatibility)
Web/API + session daemon env
@@ -537,46 +537,63 @@
-
Agent runtime
+
Pi-compatible agent profile and companion CLI
- agent.command controls which Pi-compatible CLI PI WEB checks in doctor/status/update flows.
- It defaults to pi. Set it only when diagnostics and package-managed update checks should target
- another compatible command; the embedded session runtime still uses PI WEB's SDK integration.
+ agent.command selects the Pi-compatible companion CLI used by pi-web doctor and,
+ when it can be generated safely, package-managed update commands. It defaults to pi. This
+ setting does not replace the embedded runtime: every session continues to use PI WEB's
+ bundled Pi SDK.
- agent.dir controls which compatible agent state directory PI WEB reads for auth providers,
- model settings, settings, and session metadata. It defaults to ~/.pi/agent only for the default
- pi command. Set it explicitly when you want an isolated Pi profile or when
- agent.command points at another compatible CLI.
+ agent.dir selects the Pi-compatible state profile used for auth providers, models, settings,
+ sessions, Pi packages, and Pi-package-backed PI WEB plugin discovery. It defaults to
+ ~/.pi/agent only for a canonical Pi companion command. The directory must use the data layout
+ supported by the bundled Pi SDK; PI WEB does not load or convert incompatible fork formats, migrate
+ profile data, or repartition PI WEB-managed archives when the profile changes.
- For example, a fork profile can set agent.command to my-pi-fork and
- agent.dir to /opt/my-pi-fork/agent.
+ An alternate command always requires an explicit state directory. The command must be a safe bare
+ executable name such as pi-lab or a host-absolute executable path such as
+ /opt/pi/bin/pi; relative paths, shell expressions, and launcher strings are rejected. The
+ state directory must be host-absolute or start with ~. In a federated save, the gateway
+ transports Unix and Windows absolute paths without reinterpreting them, and the target machine validates
+ and returns the persisted profile.
Environment variables take precedence over the config file. PI_WEB_AGENT_COMMAND selects the
- command, PI_WEB_AGENT_DIR sets the state directory, and PI_WEB_AGENT_SESSION_DIR
- overrides session storage separately from agent.dir. Existing Pi Coding Agent env names
- (PI_CODING_AGENT_DIR and PI_CODING_AGENT_SESSION_DIR) remain supported only for
- Pi compatibility; alternate commands should use the explicit PI WEB variables or config keys.
+ companion CLI, PI_WEB_AGENT_DIR sets the profile state directory, and
+ PI_WEB_AGENT_SESSION_DIR overrides session storage separately from agent.dir. The
+ legacy PI_CODING_AGENT_DIR and PI_CODING_AGENT_SESSION_DIR names apply only to a
+ canonical Pi companion command; PI WEB never derives ambient environment-variable names from an arbitrary
+ command. Use the explicit PI_WEB_AGENT_* names for alternate commands.
+ PI_WEB_AGENT_DIR is an unconditional override, while a legacy
+ PI_CODING_AGENT_DIR override stops applying when Settings selects an alternate command so the
+ command and directory can transition together.
- Session directory overrides are environment-only; use PI_WEB_AGENT_SESSION_DIR unless you are
- intentionally using the legacy Pi-compatible PI_CODING_AGENT_SESSION_DIR name.
+ The session daemon resolves the persisted desired values plus its environment once at startup. That
+ secret-free active profile stays fixed for the daemon lifetime. Settings → Session daemon
+ saves command and directory together as desired configuration and shows whether the profile is active,
+ needs a restart, or cannot be compared. Until the daemon restarts, sessions, Pi package operations,
+ package-backed plugin discovery, status/install detection, and update planning continue to use the
+ daemon-owned active profile; a web/API restart recovers that same active profile instead of applying the
+ newly saved values.
- In Settings → Session daemon, agent settings are saved on the selected machine. Restart
- the session daemon on that machine after changing them. The web/API process can display the new config
- immediately, and status/plugin discovery may re-read it on later requests, but active session runtime
- ownership is intentionally long-lived.
+ If the session daemon cannot report a valid active profile, profile-dependent package and plugin
+ operations report unavailable instead of falling back to independently resolved config. A package-managed
+ update command is shown only when PI WEB can preserve the active profile with a recognized, safe Pi
+ companion CLI; otherwise the command is omitted. Remote profile editing likewise requires advertised
+ support, and the gateway rejects a remote save if the target does not return the requested profile.
+ Restart the session daemon on the selected machine to establish the next active profile.
@@ -592,24 +609,35 @@
subsessions
Boolean. Beta. Controls whether agents receive the tracked-subsession tools:
- spawn_subsession, list_subsessions, check_subsession, and
- read_subsession. Defaults to false and also requires spawnSessions
- to be enabled.
+ spawn_subsession, list_subsessions, check_subsession,
+ read_subsession, and yield_to_subsessions. Defaults to false and also
+ requires spawnSessions to be enabled.
- Tracked subsessions let an agent delegate work to child sessions, receive a notification when each child
- stops working, and inspect their status and transcripts. Calling spawn_subsession returns
- immediately. The parent can continue independent work while treating every child whose result it needs
- as pending. Before producing work that depends on those results, the parent reaches a join point and
- yields until every required child has sent a completion notice.
+ Tracked subsessions are join-oriented. Calling spawn_subsession returns immediately, so the
+ parent can continue independent work while the child runs. Work whose result the parent does not need to
+ join belongs in the fire-and-forget spawn_session tool instead.
- A completion notice wakes an idle parent. If the parent is busy, the notice queues until the current
- turn ends rather than interrupting in-flight work. For multiple required children, each notice resolves
- one pending child; after processing it, the parent yields again if another required child is pending.
- list_subsessions, check_subsession, and read_subsession provide
- on-demand status and transcript inspection for deliberate progress checks or recovery. Completion
- notifications, rather than polling these tools, are the normal synchronization mechanism.
+ At a join point, after finishing its independent work, the parent calls
+ yield_to_subsessions alone as the final action in its tool batch. Pi ends a tool batch early
+ only when every result in that batch is terminating. If any tracked child is still working, the action
+ ends the current agent run so the parent becomes idle. If none are working, it does not end the run and
+ clearly reports that there is nothing to wait for.
+
+
+ A completion notice wakes an idle parent or queues behind in-flight work. Each notice lists any other
+ tracked children still working, so the parent can continue work or call
+ yield_to_subsessions again at the next join point. Further notices arrive automatically; do
+ not poll.
+
+
+ list_subsessions, check_subsession, and read_subsession never yield
+ or change control flow. They are for deliberate inspection or recovery, not completion polling. While a
+ child works, agent-facing check_subsession and read_subsession withhold partial
+ output and direct the parent to continue independent work or yield at the join point. Output becomes
+ available when the child stops. In notices and inspection results, PI WEB guidance precedes a labeled
+ marker and the child output or transcript always comes last.
In Settings → Session daemon, these keys are saved on the selected machine. Restart the
diff --git a/docs/config.md b/docs/config.md
index 6bf1e52..8819de0 100644
--- a/docs/config.md
+++ b/docs/config.md
@@ -1,6 +1,6 @@
# PI WEB configuration reference
-PI WEB configuration covers the machine-local and project-local settings you usually need: the web/API bind address, trusted development-host settings, UI preferences, plugin enablement, file-explorer path access, manual upload defaults, upload limits, agent runtime selection, and session-daemon tools.
+PI WEB configuration covers the machine-local and project-local settings you usually need: the web/API bind address, trusted development-host settings, UI preferences, plugin enablement, file-explorer path access, manual upload defaults, upload limits, Pi-compatible agent profiles and companion CLIs, and session-daemon tools.
This file is the markdown reference for agents and package consumers. The website page is .
@@ -11,7 +11,7 @@ PI WEB uses two config files:
- **Global PI WEB config:** `$PI_WEB_CONFIG`, or `$XDG_CONFIG_HOME/pi-web/config.json`, or `~/.config/pi-web/config.json`.
- **Project-local PI WEB config:** `/.pi-web/config.json` for commit-able project settings.
-Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: agent runtime selection, session daemon tools, PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts. Remote servers that do not advertise selected-machine settings support report those settings as unavailable instead of silently falling back to the gateway.
+Each PI WEB machine has its own config. When using Fleet/machine federation, Settings uses the selected machine for config that affects work running there: the Pi-compatible agent profile and companion CLI, session daemon tools, PI WEB plugin enablement, external path access, and upload defaults. Gateway/browser-only settings stay local to the gateway: keyboard shortcuts, remote machine registry/tokens, and gateway host/port/allowed-hosts. Remote servers that do not advertise selected-machine settings support report those settings as unavailable instead of silently falling back to the gateway.
Pi package settings are separate from PI WEB config. They live in Pi's package-manager settings on the target machine and are managed by Pi (`pi install`, `pi remove`, `pi update`) or **Settings → Pi packages**. In a federated setup, **Settings → Pi packages** targets the currently selected machine. The PI WEB `plugins` config key only enables or disables discovered PI WEB browser plugins on the machine whose config you are editing; it does not install, remove, or update Pi packages.
@@ -112,8 +112,8 @@ Rows with JSON key `—` are runtime-only environment variables, not config-file
| External filesystem roots | `pathAccess.allowedPaths` | — | Global + project | **Merges**: global roots first, then project roots; duplicates removed | Next file request; refresh existing views if needed |
| Manual file upload default folder | `uploads.defaultFolder` | — | Global + project | **Overrides**: project value wins for workspaces in that project; otherwise global/default applies | New Upload dialogs and direct drag/drop batches after config/workspace refresh |
| Upload/body limit | `maxUploadBytes` | `PI_WEB_MAX_UPLOAD_BYTES` | Global | Not supported locally | Restart web/API and session daemon on that machine |
-| Agent CLI command | `agent.command` | `PI_WEB_AGENT_COMMAND` | Global/session daemon | Not supported locally | Restart session daemon on that machine; affects doctor/status/update checks |
-| Agent state directory | `agent.dir` | `PI_WEB_AGENT_DIR` (`PI_CODING_AGENT_DIR` for Pi compatibility) | Global/session daemon | Not supported locally | Restart session daemon on that machine; affects auth, models, settings, and sessions |
+| Companion CLI command | `agent.command` | `PI_WEB_AGENT_COMMAND` | Global/session daemon | Not supported locally | Restart session daemon on that machine; affects doctor/status/update checks |
+| Agent profile state directory | `agent.dir` | `PI_WEB_AGENT_DIR` (`PI_CODING_AGENT_DIR` for Pi compatibility) | Global/session daemon | Not supported locally | Restart session daemon on that machine; affects auth, models, settings, sessions, Pi packages, and package-backed plugins |
| Agent can spawn sessions | `spawnSessions` | `PI_WEB_SPAWN_SESSIONS` | Global/session daemon | Not supported locally | Restart session daemon on that machine |
| Tracked subsessions (beta) | `subsessions` | `PI_WEB_SUBSESSIONS` | Global/session daemon | Not supported locally; also requires `spawnSessions` | Restart session daemon on that machine |
| Plugin enablement/settings | `plugins..enabled`, `plugins..settings` | — | Global | Not core local config; plugins may read their own project files | Reload browser tab |
@@ -128,8 +128,8 @@ Rows with JSON key `—` are runtime-only environment variables, not config-file
| Web-to-daemon URL | — | `PI_WEB_SESSIOND_URL` | Web/API env | Not supported locally | Restart web/API |
| Projects storage file | — | `PI_WEB_PROJECTS_FILE` | Web/API + session daemon env | Not supported locally | Restart services; advanced state override |
| Remote machines storage file | — | `PI_WEB_MACHINES_FILE` | Web/API env | Not supported locally | Restart web/API; advanced state override |
-| Agent session storage directory | — | `PI_WEB_AGENT_SESSION_DIR` (`PI_CODING_AGENT_SESSION_DIR` for Pi compatibility) | Session daemon env | Not supported locally | Restart session daemon; env-only session storage override |
-| Agent config directory | — | `PI_WEB_AGENT_DIR` (`PI_CODING_AGENT_DIR` for Pi compatibility) | Web/API + session daemon env | Not supported locally | Restart services |
+| Agent profile session storage directory | — | `PI_WEB_AGENT_SESSION_DIR` (`PI_CODING_AGENT_SESSION_DIR` for Pi compatibility) | Session daemon env | Not supported locally | Restart session daemon; env-only session storage override |
+| Agent profile state directory | — | `PI_WEB_AGENT_DIR` (`PI_CODING_AGENT_DIR` for Pi compatibility) | Web/API + session daemon env | Not supported locally | Restart services |
| Skip update checks | — | `PI_WEB_SKIP_VERSION_CHECK`, `PI_WEB_OFFLINE`, `PI_SKIP_VERSION_CHECK`, `PI_OFFLINE` | Web/API env | Not supported locally | Restart web/API after env changes |
## Key details
@@ -183,38 +183,42 @@ For machine federation, Settings saves the global upload default on the selected
The per-request size limit is still controlled by `maxUploadBytes` / `PI_WEB_MAX_UPLOAD_BYTES` on the machine serving the upload.
-### Agent runtime selection
+### Pi-compatible agent profile and companion CLI
-`agent.command` controls which Pi-compatible CLI PI WEB checks in doctor/status/update flows. It defaults to `pi`. Set it only when diagnostics and package-managed update checks should target another compatible command; the embedded session runtime still uses PI WEB's SDK integration.
+`agent.command` selects the Pi-compatible companion CLI used by `pi-web doctor` and, when it can be generated safely, package-managed update commands. It defaults to `pi`. This setting does **not** replace the embedded runtime: every session continues to use PI WEB's bundled Pi SDK.
-`agent.dir` controls which compatible agent state directory PI WEB reads for auth providers, model settings, settings, and session metadata. It defaults to `~/.pi/agent` only for the default `pi` command. Set it explicitly when you want an isolated Pi profile or when `agent.command` points at another compatible CLI.
+`agent.dir` selects the Pi-compatible state profile used for auth providers, models, settings, sessions, Pi packages, and Pi-package-backed PI WEB plugin discovery. It defaults to `~/.pi/agent` only for a canonical Pi companion command. The directory must use the data layout supported by the bundled Pi SDK; PI WEB does not load or convert incompatible fork formats, migrate profile data, or repartition PI WEB-managed archives when the profile changes.
```json
{
"agent": {
- "command": "my-pi-fork",
- "dir": "/opt/my-pi-fork/agent"
+ "command": "pi-lab",
+ "dir": "/opt/pi-profiles/lab"
}
}
```
-For example, a fork profile can set `agent.command` to `my-pi-fork` and `agent.dir` to `/opt/my-pi-fork/agent`.
+An alternate command always requires an explicit state directory. The command must be a safe bare executable name such as `pi-lab` or a host-absolute executable path such as `/opt/pi/bin/pi`; relative paths, shell expressions, and launcher strings are rejected. The state directory must be host-absolute or start with `~`. In a federated save, the gateway transports Unix and Windows absolute paths without reinterpreting them, and the target machine validates and returns the persisted profile.
-Environment variables take precedence over the config file. `PI_WEB_AGENT_COMMAND` selects the command, `PI_WEB_AGENT_DIR` sets the state directory, and `PI_WEB_AGENT_SESSION_DIR` overrides session storage separately from `agent.dir`. Existing Pi Coding Agent env names (`PI_CODING_AGENT_DIR` and `PI_CODING_AGENT_SESSION_DIR`) remain supported only for Pi compatibility; alternate commands should use the explicit PI WEB variables or config keys.
+Environment variables take precedence over the config file. `PI_WEB_AGENT_COMMAND` selects the companion CLI, `PI_WEB_AGENT_DIR` sets the profile state directory, and `PI_WEB_AGENT_SESSION_DIR` overrides session storage separately from `agent.dir`. The legacy `PI_CODING_AGENT_DIR` and `PI_CODING_AGENT_SESSION_DIR` names apply only to a canonical Pi companion command; PI WEB never derives ambient environment-variable names from an arbitrary command. Use the explicit `PI_WEB_AGENT_*` names for alternate commands. `PI_WEB_AGENT_DIR` is an unconditional override, while a legacy `PI_CODING_AGENT_DIR` override stops applying when Settings selects an alternate command so the command and directory can transition together.
-Session directory overrides are environment-only; use `PI_WEB_AGENT_SESSION_DIR` unless you are intentionally using the legacy Pi-compatible `PI_CODING_AGENT_SESSION_DIR` name.
+The session daemon resolves the persisted desired values plus its environment once at startup. That secret-free active profile stays fixed for the daemon lifetime. **Settings → Session daemon** saves command and directory together as desired configuration and shows whether the profile is active, needs a restart, or cannot be compared. Until the daemon restarts, sessions, Pi package operations, package-backed plugin discovery, status/install detection, and update planning continue to use the daemon-owned active profile; a web/API restart recovers that same active profile instead of applying the newly saved values.
-In **Settings → Session daemon**, agent settings are saved on the selected machine. Restart the session daemon on that machine after changing them. The web/API process can display the new config immediately, and status/plugin discovery may re-read it on later requests, but active session runtime ownership is intentionally long-lived.
+If the session daemon cannot report a valid active profile, profile-dependent package and plugin operations report unavailable instead of falling back to independently resolved config. A package-managed update command is shown only when PI WEB can preserve the active profile with a recognized, safe Pi companion CLI; otherwise the command is omitted. Remote profile editing likewise requires advertised support, and the gateway rejects a remote save if the target does not return the requested profile. Restart the session daemon on the selected machine to establish the next active profile.
### Session daemon tools
`spawnSessions` controls whether agents receive the `spawn_session` tool. It defaults to `true`; set it to `false` if you do not want an agent to start independent PI WEB sessions.
-`subsessions` is beta and controls whether agents receive the tracked-subsession tools: `spawn_subsession`, `list_subsessions`, `check_subsession`, and `read_subsession`. It defaults to `false` and also requires `spawnSessions` to be enabled.
+`subsessions` is beta and controls whether agents receive the tracked-subsession tools: `spawn_subsession`, `list_subsessions`, `check_subsession`, `read_subsession`, and `yield_to_subsessions`. It defaults to `false` and also requires `spawnSessions` to be enabled.
-Tracked subsessions let an agent delegate work to child sessions, receive a notification when each child stops working, and inspect their status and transcripts. Calling `spawn_subsession` returns immediately. The parent can continue independent work while treating every child whose result it needs as pending. Before producing work that depends on those results, the parent reaches a join point and yields until every required child has sent a completion notice.
+Tracked subsessions are join-oriented. Calling `spawn_subsession` returns immediately, so the parent can continue independent work while the child runs. Work whose result the parent does not need to join belongs in the fire-and-forget `spawn_session` tool instead.
-A completion notice wakes an idle parent. If the parent is busy, the notice queues until the current turn ends rather than interrupting in-flight work. For multiple required children, each notice resolves one pending child; after processing it, the parent yields again if another required child is pending. `list_subsessions`, `check_subsession`, and `read_subsession` provide on-demand status and transcript inspection for deliberate progress checks or recovery. Completion notifications, rather than polling these tools, are the normal synchronization mechanism.
+At a join point, after finishing its independent work, the parent calls `yield_to_subsessions` alone as the final action in its tool batch. Pi ends a tool batch early only when every result in that batch is terminating. If any tracked child is still working, the action ends the current agent run so the parent becomes idle. If none are working, it does not end the run and clearly reports that there is nothing to wait for.
+
+A completion notice wakes an idle parent or queues behind in-flight work. Each notice lists any other tracked children still working, so the parent can continue work or call `yield_to_subsessions` again at the next join point. Further notices arrive automatically; do not poll.
+
+`list_subsessions`, `check_subsession`, and `read_subsession` never yield or change control flow. They are for deliberate inspection or recovery, not completion polling. While a child works, agent-facing `check_subsession` and `read_subsession` withhold partial output and direct the parent to continue independent work or yield at the join point. Output becomes available when the child stops. In notices and inspection results, PI WEB guidance precedes a labeled marker and the child output or transcript always comes last.
In **Settings → Session daemon**, these keys are saved on the selected machine. Restart the session daemon on that machine after changing them.
diff --git a/src/client/src/api/clients.test.ts b/src/client/src/api/clients.test.ts
index 5107c95..4e6b4ac 100644
--- a/src/client/src/api/clients.test.ts
+++ b/src/client/src/api/clients.test.ts
@@ -250,6 +250,36 @@ describe("session API compatibility", () => {
expect(url).toBe("https://pi.example.test/api/machines/remote%20a/sessions/s%201/prompt");
expect(JSON.parse(requestBody(init))).toEqual({ cwd: "/repo", text: "hello" });
});
+
+ it("clears a session queue through an encoded machine route and parses the returned status", async () => {
+ const fetchMock = stubJsonFetch({
+ sessionId: "s /?",
+ isStreaming: true,
+ isCompacting: false,
+ isBashRunning: false,
+ pendingMessageCount: 0,
+ tokens: { input: 3, output: 2, cacheRead: 1, cacheWrite: 0, total: 6 },
+ cost: 0.25,
+ ignored: "not part of SessionStatus",
+ });
+
+ await expect(sessionsApi.clearQueue({ id: "s /?", cwd: "/repo with spaces" }, "remote /?")).resolves.toEqual({
+ sessionId: "s /?",
+ isStreaming: true,
+ isCompacting: false,
+ isBashRunning: false,
+ pendingMessageCount: 0,
+ queuedMessages: [],
+ tokens: { input: 3, output: 2, cacheRead: 1, cacheWrite: 0, total: 6 },
+ cost: 0.25,
+ });
+
+ expect(fetchMock).toHaveBeenCalledOnce();
+ const [url, init] = fetchCall(fetchMock, 0);
+ expect(url).toBe("https://pi.example.test/api/machines/remote%20%2F%3F/sessions/s%20%2F%3F/queue/clear");
+ expect(init?.method).toBe("POST");
+ expect(JSON.parse(requestBody(init))).toEqual({ cwd: "/repo with spaces" });
+ });
});
describe("machine-scoped file suggestion API", () => {
diff --git a/src/client/src/api/clients.ts b/src/client/src/api/clients.ts
index 190abb4..493b506 100644
--- a/src/client/src/api/clients.ts
+++ b/src/client/src/api/clients.ts
@@ -209,6 +209,7 @@ export const sessionsApi = {
deleteArchivedMany: (sessions: readonly SessionLookup[], machineId = "local") => request(`${machinePrefix(machineId)}/sessions/bulk/delete-archived`, parseSessionBulkDeleteArchivedResponse, { method: "POST", body: sessionBulkMutationBody(sessions) }),
messages: (session: SessionLookup, options?: { limit?: number; before?: number }, machineId = "local") => request(messagePath(session, options, machineId), parseMessagePage),
status: (session: SessionLookup, machineId = "local") => request(sessionQueryPath(session, "status", machineId), parseSessionStatus),
+ clearQueue: (session: SessionLookup, machineId = "local") => request(sessionPath(session, "queue/clear", machineId), parseSessionStatus, { method: "POST", body: sessionBody(session) }),
models: (session: SessionLookup, machineId = "local") => request(sessionQueryPath(session, "models", machineId), parseModelSelectionResponse),
setModel: (session: SessionLookup, provider: string, modelId: string, machineId = "local") => request(sessionPath(session, "model", machineId), parseSessionStatus, { method: "POST", body: sessionBody(session, { provider, modelId }) }),
cycleModel: (session: SessionLookup, direction: "forward" | "backward", machineId = "local") => request(sessionPath(session, "model/cycle", machineId), parseSessionStatus, { method: "POST", body: sessionBody(session, { direction }) }),
diff --git a/src/client/src/api/federatedRouteContract.test.ts b/src/client/src/api/federatedRouteContract.test.ts
index 28a5257..52a53c2 100644
--- a/src/client/src/api/federatedRouteContract.test.ts
+++ b/src/client/src/api/federatedRouteContract.test.ts
@@ -64,6 +64,7 @@ describe("federated route contract", () => {
ignoreParseFailure(sessionsApi.deleteArchivedMany([session], machineId)),
ignoreParseFailure(sessionsApi.messages(session, { limit: 20, before: 10 }, machineId)),
ignoreParseFailure(sessionsApi.status(session, machineId)),
+ ignoreParseFailure(sessionsApi.clearQueue(session, machineId)),
ignoreParseFailure(sessionsApi.models(session, machineId)),
ignoreParseFailure(sessionsApi.setModel(session, "openai", "gpt", machineId)),
ignoreParseFailure(sessionsApi.cycleModel(session, "forward", machineId)),
diff --git a/src/client/src/components/AuthDialog.ts b/src/client/src/components/AuthDialog.ts
index 6cb0bbf..7225ee2 100644
--- a/src/client/src/components/AuthDialog.ts
+++ b/src/client/src/components/AuthDialog.ts
@@ -54,13 +54,13 @@ export class AuthDialog extends LitElement {
case "method": return html`