From 132debb5fedd386a16d888a04e1cbb92f0b6dcd6 Mon Sep 17 00:00:00 2001 From: Yichen Jiang Date: Sat, 8 Aug 2026 20:16:50 +0800 Subject: [PATCH] fix(apiproxy): echo the resolved agent preset on create and session-added MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit session.create's reply named only the id, and the session-added frame's agentPreset — which the server already derives via sessionListFields — was stripped by the wire schema it never joined. A client therefore could not label a session it just created (or learned live) until the next full list refresh: the header's preset label rendered nothing for exactly the sessions made in this tab. The create reply is the commit point that knows the RESOLVED composition (a caller that named none gets the default the header recorded), so both carriers now say it. --- packages/host/apiproxy/src/api-proxy.ts | 8 +++++++- packages/host/apiproxy/src/api/events.schema.ts | 1 + packages/host/apiproxy/src/api/events.ts | 1 + packages/host/apiproxy/src/api/sessions.schema.ts | 1 + packages/host/apiproxy/src/api/sessions.ts | 2 +- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/host/apiproxy/src/api-proxy.ts b/packages/host/apiproxy/src/api-proxy.ts index 72fff0cdf0..8ee0a02175 100644 --- a/packages/host/apiproxy/src/api-proxy.ts +++ b/packages/host/apiproxy/src/api-proxy.ts @@ -1773,7 +1773,13 @@ export function createApiProxy(ctx: Context, defaults: ApiProxyDefaults): ApiPro }) } } - return ok(request, { sessionId }) + // Echo the RESOLVED composition so a client can label the session it + // just created without waiting for the next list refresh — the create + // is the commit point that knows it (a caller that named none gets + // the default the header recorded). + const created = ctx.agents.get(sessionId) + const createdPreset = created?.session.header.agentPreset + return ok(request, { sessionId, ...createdPreset === undefined ? {} : { agentPreset: createdPreset } }) }, async history(request) { diff --git a/packages/host/apiproxy/src/api/events.schema.ts b/packages/host/apiproxy/src/api/events.schema.ts index 13ead7d08d..b432880810 100644 --- a/packages/host/apiproxy/src/api/events.schema.ts +++ b/packages/host/apiproxy/src/api/events.schema.ts @@ -73,6 +73,7 @@ export const hostFrameSchema = z.discriminatedUnion('type', [ parentSessionId: sessionIdSchema.optional(), origin: z.literal('subagent').optional(), cwd: z.string().optional(), + agentPreset: z.string().optional(), }), z.object({ type: z.literal('host/session-removed'), sessionId: sessionIdSchema }), z.object({ type: z.literal('host/session-status'), sessionId: sessionIdSchema, running: z.boolean() }), diff --git a/packages/host/apiproxy/src/api/events.ts b/packages/host/apiproxy/src/api/events.ts index 7fc54f6f01..555e08a9a2 100644 --- a/packages/host/apiproxy/src/api/events.ts +++ b/packages/host/apiproxy/src/api/events.ts @@ -116,6 +116,7 @@ export type HostFrame = parentSessionId?: SessionId origin?: 'subagent' cwd?: string + agentPreset?: string } | { type: 'host/session-removed'; sessionId: SessionId } | { type: 'host/session-status'; sessionId: SessionId; running: boolean } diff --git a/packages/host/apiproxy/src/api/sessions.schema.ts b/packages/host/apiproxy/src/api/sessions.schema.ts index 7e2ead7c2b..b20dc66579 100644 --- a/packages/host/apiproxy/src/api/sessions.schema.ts +++ b/packages/host/apiproxy/src/api/sessions.schema.ts @@ -109,6 +109,7 @@ export const sessionCreateRequestSchema = z.object({ /** session.create response value. */ export const sessionCreateValueSchema = z.object({ sessionId: sessionIdSchema, + agentPreset: z.string().optional(), }) satisfies z.ZodType>> /** session.rename request payload (raw title; host-side normalization decides acceptance). */ diff --git a/packages/host/apiproxy/src/api/sessions.ts b/packages/host/apiproxy/src/api/sessions.ts index 2fa9a65916..c2966b7cb3 100644 --- a/packages/host/apiproxy/src/api/sessions.ts +++ b/packages/host/apiproxy/src/api/sessions.ts @@ -217,7 +217,7 @@ export interface SessionsApi { * cannot be mounted fails with `agent-preset-invalid`. */ create(request: RpcRequest<{ workspaceId?: WorkspaceId; cwd?: string; sessionId?: SessionId; agentPreset?: string }>): - Promise> + Promise> /** * Reads a window of history events; page boundaries align to append-origin message