mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-11 10:57:07 +00:00
Give plugins an agent's background work count and a background flag on hooks (#9362)
* feat(plugins): give plugins the agent's sidebar indicator and background flag Plugin UI re-derived agent state from status and attention fields and could not see background work, so it showed agents as done while a shell they left running was still live. Agent snapshots now carry the sidebar's own bucket as indicator/indicatorLabel, computed by the same function the sidebar uses so the two cannot drift. Lifecycle hooks and the agent.open.before request now carry `background`, so a hook can skip a hidden helper agent without a lookup. A hook cannot change it; an omitted value means unchanged, like metadata. `finished` attention still means the turn finished; background work is the indicator's concern. * fix(plugins): keep session-open hooks that omit background typechecking A hook that returns its own object instead of spreading the request has no background field; the result type now treats it as optional, like metadata, matching the runtime where an omitted value means unchanged. * refactor(plugins): give agent snapshots the background work count instead of an indicator * fix(plugins): keep legacy session-open hooks that omit background typechecking
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import { i18n } from "@/i18n/i18next";
|
||||
import { fr } from "@/i18n/resources/fr";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { WorkspaceDescriptor } from "@/stores/session-store";
|
||||
import type { Agent, WorkspaceDescriptor } from "@/stores/session-store";
|
||||
import { normalizeAgentSnapshot, projectAgentSnapshot } from "@/utils/agent-snapshots";
|
||||
import {
|
||||
createPluginAgentSnapshot,
|
||||
createPluginWorkspaceSnapshot,
|
||||
@@ -109,6 +110,26 @@ describe("sidebar entity snapshots", () => {
|
||||
).toBe(after);
|
||||
});
|
||||
|
||||
it("carries the background work count the host publishes for the agent", () => {
|
||||
// Round-trip through the wire payload, the way the app receives each agent update.
|
||||
const published = (backgroundWork: Agent["backgroundWork"]) =>
|
||||
createPluginAgentSnapshot(
|
||||
normalizeAgentSnapshot({ ...projectAgentSnapshot(agent), backgroundWork }, agent.serverId),
|
||||
workspace.id,
|
||||
).backgroundWork;
|
||||
expect(published(undefined)).toEqual({ count: 0 });
|
||||
expect(published({ count: 2 })).toEqual({ count: 2 });
|
||||
expect(published({ count: 0 })).toEqual({ count: 0 });
|
||||
expect(Object.isFrozen(published({ count: 1 }))).toBe(true);
|
||||
});
|
||||
|
||||
it("marks a background agent", () => {
|
||||
expect(createPluginAgentSnapshot(agent, workspace.id).background).toBe(false);
|
||||
expect(createPluginAgentSnapshot({ ...agent, background: true }, workspace.id).background).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("reads projects without requiring a workspace", () => {
|
||||
const project = {
|
||||
projectId: "empty",
|
||||
|
||||
@@ -86,6 +86,8 @@ export function createPluginAgentSnapshot(agent: Agent, workspaceId: string): Pl
|
||||
workspaceId,
|
||||
provider: agent.provider,
|
||||
status: agent.status,
|
||||
backgroundWork: Object.freeze({ count: agent.backgroundWork?.count ?? 0 }),
|
||||
background: agent.background ?? false,
|
||||
createdAt: agent.createdAt.toISOString(),
|
||||
updatedAt: agent.updatedAt.toISOString(),
|
||||
lastActivityAt: agent.lastActivityAt.toISOString(),
|
||||
|
||||
@@ -51,6 +51,8 @@ const agent: PluginAgentSnapshot = {
|
||||
workspaceId: workspace.id,
|
||||
provider: "codex",
|
||||
status: "running",
|
||||
backgroundWork: { count: 0 },
|
||||
background: false,
|
||||
createdAt: "2026-08-16T10:00:00.000Z",
|
||||
updatedAt: "2026-08-16T10:00:00.000Z",
|
||||
lastActivityAt: "2026-08-16T10:00:00.000Z",
|
||||
|
||||
Reference in New Issue
Block a user