mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-28 20:22:45 +00:00
fix(muse-provider): negotiate session.subsession and gate child projection
This commit is contained in:
@@ -21,6 +21,7 @@ export class Children {
|
||||
private readonly parentId: string,
|
||||
private readonly cwd: string,
|
||||
private readonly emit: (event: ProviderEvent) => void,
|
||||
private readonly subsessions: boolean,
|
||||
) {}
|
||||
|
||||
async update(item: WireItem): Promise<void> {
|
||||
@@ -34,6 +35,10 @@ export class Children {
|
||||
)
|
||||
)
|
||||
return;
|
||||
// Emitting a child session.opened with parentSessionId is only valid when the
|
||||
// parent session negotiated the session.subsession capability; the daemon
|
||||
// fails the provider connection otherwise.
|
||||
if (!this.subsessions) return;
|
||||
const id = item.childSessionId;
|
||||
if (!this.children.has(id)) {
|
||||
const { session } = await this.host.request(
|
||||
|
||||
@@ -27,6 +27,7 @@ const capabilities = [
|
||||
"session.persistence",
|
||||
"permission",
|
||||
"session.list",
|
||||
"session.subsession",
|
||||
] as const;
|
||||
|
||||
export function createMuseProvider(usage: Usage): ProviderRegistration {
|
||||
|
||||
@@ -142,7 +142,13 @@ export class Session {
|
||||
const nativeId = response.session.sessionId;
|
||||
this.liveState = {
|
||||
nativeId,
|
||||
children: new Children(this.host, this.options.id, this.config.cwd, this.options.emit),
|
||||
children: new Children(
|
||||
this.host,
|
||||
this.options.id,
|
||||
this.config.cwd,
|
||||
this.options.emit,
|
||||
this.options.capabilities.includes("session.subsession"),
|
||||
),
|
||||
timeline: new Timeline(
|
||||
this.host,
|
||||
nativeId,
|
||||
|
||||
@@ -45,6 +45,7 @@ async function harness(
|
||||
scenario = "text-reasoning",
|
||||
env: Record<string, string> = {},
|
||||
providerOptions?: Record<string, unknown>,
|
||||
connectCapabilities: readonly string[] = PROVIDER_CAPABILITIES,
|
||||
) {
|
||||
const root = await mkdtemp(path.join(os.tmpdir(), "muse-provider-test-"));
|
||||
roots.push(root);
|
||||
@@ -62,7 +63,7 @@ async function harness(
|
||||
const connection = await provider.connect({
|
||||
launch,
|
||||
versions: [1],
|
||||
capabilities: PROVIDER_CAPABILITIES,
|
||||
capabilities: connectCapabilities,
|
||||
});
|
||||
connections.push(connection);
|
||||
const events: ProviderEvent[] = [];
|
||||
@@ -1192,6 +1193,20 @@ for (const variant of ["tool", "dedicated", "workflow"]) {
|
||||
).toHaveLength(1);
|
||||
});
|
||||
}
|
||||
|
||||
test("subagent children are not projected when session.subsession is not negotiated", async () => {
|
||||
const h = await harness(
|
||||
"subagent",
|
||||
{},
|
||||
undefined,
|
||||
PROVIDER_CAPABILITIES.filter((capability) => capability !== "session.subsession"),
|
||||
);
|
||||
await h.open();
|
||||
await h.prompt();
|
||||
await h.wait((e) => e.type === "session.turn" && e.state === "completed");
|
||||
expect(h.events.filter((e) => e.type === "session.opened" && e.parentSessionId)).toHaveLength(0);
|
||||
expect((await h.recorded()).filter((f) => f.method === "session/read")).toEqual([]);
|
||||
});
|
||||
test("gap backfill repairs a missing completion without duplicating item revisions", async () => {
|
||||
const h = await harness("text-reasoning", { MUSE_TEST_GAP: "1" });
|
||||
await h.open();
|
||||
|
||||
Reference in New Issue
Block a user