mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-27 19:52:49 +00:00
fix(client): require host support for import modes
Older daemons discard unknown import fields. Reject explicit mode selection before sending the import unless the host advertises support, while preserving imports that omit a mode.
This commit is contained in:
@@ -5381,7 +5381,39 @@ test("fetches scoped recent provider sessions", async () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("imports an agent by provider handle id", async () => {
|
||||
test.each([undefined, false])(
|
||||
"rejects explicit import modes on hosts without support (%s)",
|
||||
async (supported) => {
|
||||
const transport = createMockTransport();
|
||||
const client = new DaemonClient({
|
||||
url: "ws://test",
|
||||
clientId: "clsk_import_mode_compat",
|
||||
logger: createMockLogger(),
|
||||
reconnect: { enabled: false },
|
||||
transportFactory: () => transport.transport,
|
||||
});
|
||||
clients.push(client);
|
||||
const connecting = client.connect();
|
||||
transport.triggerOpen({ features: { importSessionMode: supported } });
|
||||
await connecting;
|
||||
|
||||
const importing = client.importAgent({
|
||||
provider: "claude",
|
||||
sessionId: "native-session",
|
||||
modeId: "auto",
|
||||
});
|
||||
void importing.catch(() => undefined);
|
||||
expect(transport.sent).toHaveLength(0);
|
||||
await expect(importing).rejects.toThrow(
|
||||
"Update the host to select a mode when importing an agent.",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test.each([
|
||||
["full-access", true],
|
||||
[undefined, undefined],
|
||||
] as const)("imports an agent by provider handle id with mode %s", async (modeId, supported) => {
|
||||
const logger = createMockLogger();
|
||||
const mock = createMockTransport();
|
||||
|
||||
@@ -5395,14 +5427,14 @@ test("imports an agent by provider handle id", async () => {
|
||||
clients.push(client);
|
||||
|
||||
const connectPromise = client.connect();
|
||||
mock.triggerOpen();
|
||||
mock.triggerOpen({ features: { importSessionMode: supported } });
|
||||
await connectPromise;
|
||||
|
||||
const promise = client.importAgent({
|
||||
providerId: "custom-codex",
|
||||
providerHandleId: "thread-1",
|
||||
cwd: "/tmp/repo",
|
||||
modeId: "full-access",
|
||||
modeId,
|
||||
});
|
||||
|
||||
expect(mock.sent).toHaveLength(1);
|
||||
@@ -5423,8 +5455,8 @@ test("imports an agent by provider handle id", async () => {
|
||||
providerId: "custom-codex",
|
||||
providerHandleId: "thread-1",
|
||||
cwd: "/tmp/repo",
|
||||
modeId: "full-access",
|
||||
});
|
||||
expect(request.message.modeId).toBe(modeId);
|
||||
expect(request.message).not.toHaveProperty("sessionId");
|
||||
|
||||
mock.triggerMessage(
|
||||
|
||||
@@ -3211,6 +3211,10 @@ export class DaemonClient {
|
||||
}
|
||||
|
||||
async importAgent(input: ImportAgentInput): Promise<AgentSnapshotPayload> {
|
||||
// COMPAT(importSessionMode): added after v0.11.4, remove gate after 2027-04-16.
|
||||
if (input.modeId && this.lastServerInfoMessage?.features?.importSessionMode !== true) {
|
||||
throw new Error("Update the host to select a mode when importing an agent.");
|
||||
}
|
||||
const requestId = this.createRequestId();
|
||||
const message = SessionInboundMessageSchema.parse({
|
||||
type: "import_agent_request",
|
||||
|
||||
@@ -3715,6 +3715,8 @@ export const ServerInfoStatusPayloadSchema = z
|
||||
hopliteProvider: z.boolean().optional(),
|
||||
// COMPAT(importSessionWorkspaceTarget): added in v0.1.110, remove gate after 2027-01-16.
|
||||
importSessionWorkspaceTarget: z.boolean().optional(),
|
||||
// COMPAT(importSessionMode): added after v0.11.4, remove gate after 2027-04-16.
|
||||
importSessionMode: z.boolean().optional(),
|
||||
// COMPAT(importSessionSearch): added in v0.8.0, remove gate after 2027-03-02.
|
||||
importSessionSearch: z.boolean().optional(),
|
||||
// COMPAT(forgeProviders): added in v0.2.0-beta.1. Drop the gate after
|
||||
|
||||
@@ -1918,6 +1918,8 @@ export class VoiceAssistantWebSocketServer {
|
||||
hopliteProvider: this.providerSnapshotManager.supportsConfigRequiredProvider("hoplite"),
|
||||
// COMPAT(importSessionWorkspaceTarget): added in v0.1.110, remove gate after 2027-01-16.
|
||||
importSessionWorkspaceTarget: true,
|
||||
// COMPAT(importSessionMode): added after v0.11.4, remove gate after 2027-04-16.
|
||||
importSessionMode: true,
|
||||
// COMPAT(importSessionSearch): added in v0.7.3, remove gate after 2027-03-02.
|
||||
importSessionSearch: true,
|
||||
// COMPAT(forgeProviders): added in v0.2.0-beta.1. Drop the gate after
|
||||
|
||||
Reference in New Issue
Block a user