mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-04 15:34:39 +00:00
* feat(server): add background agents An agent can be created background in any workspace. It stays a durable, addressable agent, but default discovery, workspace status and attention leave it out. Effective background is agent.background || workspace.background. - Protocol: `create_agent_request.background` now marks the agent itself and stays the workspace intent for a workspace the request creates. Snapshots carry `background`. The daemon advertises `features.backgroundAgents`. Clients advertise the `background_agents` capability. - Daemon: the flag persists in the agent record, so restart and resume keep it. AgentDirectory owns visibility. Inclusive reads and subscriptions from sources without `background_agents` see only agents in background workspaces, because older apps would otherwise open a tab for each one. - Inheritance: omitted on agent-scoped creation, children and new workspaces take the caller agent's background. - MCP: create_agent accepts `background`. - SDK: placing a background agent in an existing workspace, or under a caller, fails fast with "Update the host to use background agents." on older hosts. - CLI: `ls -a` and `ls --background` add a BACKGROUND column. * feat(app): hide background agents from tabs, track and status * docs(plugins): point hidden helpers at background agents * fix: keep background agents hidden across cache reload and connected hosts * fix: keep remote creation working on older hosts and inherit foreign parents' background
66 lines
2.4 KiB
TypeScript
66 lines
2.4 KiB
TypeScript
import { test } from "../support/fixtures";
|
|
import {
|
|
expectWorkspaceShownIdle,
|
|
finishAndArchiveAgent,
|
|
startBackgroundAgent,
|
|
} from "../support/helpers/background-agents";
|
|
import { openAgentRoute } from "../support/helpers/mock-agent";
|
|
import { seedWorkspace, type SeededWorkspace } from "../support/helpers/seed-client";
|
|
import {
|
|
expectSubagentRowGone,
|
|
expectSubagentRowVisible,
|
|
openSubagentsTrack,
|
|
seedParentWithSubagent,
|
|
seedSubagent,
|
|
} from "../support/helpers/subagents";
|
|
import { expectOnlyWorkspaceAgentTabsVisible } from "../support/helpers/workspace-tabs";
|
|
|
|
test.describe("Background agents", () => {
|
|
let workspace: SeededWorkspace;
|
|
|
|
test.beforeAll(async () => {
|
|
workspace = await seedWorkspace({
|
|
repoPrefix: "background-agents-",
|
|
title: "Classifier workspace",
|
|
});
|
|
});
|
|
|
|
test.afterAll(async () => {
|
|
await workspace?.cleanup();
|
|
});
|
|
|
|
test("a background agent runs in an open workspace without announcing itself", async ({
|
|
page,
|
|
}) => {
|
|
const agents = await seedParentWithSubagent(workspace, {
|
|
parentTitle: "Feature agent",
|
|
childTitle: "Visible helper",
|
|
});
|
|
await openAgentRoute(page, { workspaceId: agents.workspaceId, agentId: agents.parent.id });
|
|
await openSubagentsTrack(page);
|
|
await expectSubagentRowVisible(page, agents.child.id);
|
|
|
|
const classifier = await test.step("a plugin starts a background agent", () =>
|
|
startBackgroundAgent(workspace, { parentId: agents.parent.id, title: "Classifier" }));
|
|
// A visible child created after the classifier reaches the app on the same stream, so once
|
|
// its row shows, the app has processed the classifier too.
|
|
const marker = await seedSubagent(workspace, {
|
|
parentId: agents.parent.id,
|
|
title: "Ordering marker",
|
|
});
|
|
|
|
await test.step("it stays out of the track, the tabs and the sidebar status", async () => {
|
|
await expectSubagentRowVisible(page, marker.id);
|
|
await expectSubagentRowGone(page, classifier.id);
|
|
await expectOnlyWorkspaceAgentTabsVisible(page, [agents.parent.id]);
|
|
await expectWorkspaceShownIdle(page, "Classifier workspace");
|
|
});
|
|
|
|
await test.step("the plugin reads its finish and archives it", async () => {
|
|
await finishAndArchiveAgent(workspace, classifier.id);
|
|
await expectOnlyWorkspaceAgentTabsVisible(page, [agents.parent.id]);
|
|
await expectSubagentRowGone(page, classifier.id);
|
|
});
|
|
});
|
|
});
|