Merge remote-tracking branch 'origin/main' into merge/main-into-dev
# Conflicts: # CLAUDE.md # nix/package.nix # packages/app/src/components/combined-model-selector.tsx # packages/app/src/hooks/use-sidebar-workspaces-list.ts # packages/app/src/screens/workspace/workspace-screen.tsx # packages/app/src/stores/session-store.test.ts # packages/server/src/client/daemon-client.ts # packages/server/src/server/agent/agent-manager.ts # packages/server/src/server/session.ts # packages/server/src/server/session.workspace-git-watch.test.ts # packages/server/src/server/session.workspaces.test.ts # packages/server/src/shared/messages.ts
This commit is contained in:
@@ -203,6 +203,74 @@ describe("shared messages stream parsing", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("parses optional permission actions and selectedActionId compatibly", () => {
|
||||
const requestParsed = AgentStreamMessageSchema.parse({
|
||||
type: "agent_stream",
|
||||
payload: {
|
||||
agentId: "agent_live",
|
||||
timestamp: "2026-02-08T20:10:00.000Z",
|
||||
event: {
|
||||
type: "permission_requested",
|
||||
provider: "codex",
|
||||
request: {
|
||||
id: "perm-1",
|
||||
provider: "codex",
|
||||
name: "CodexPlanApproval",
|
||||
kind: "plan",
|
||||
input: { plan: "- step 1" },
|
||||
actions: [
|
||||
{
|
||||
id: "reject",
|
||||
label: "Reject",
|
||||
behavior: "deny",
|
||||
variant: "danger",
|
||||
intent: "dismiss",
|
||||
},
|
||||
{
|
||||
id: "implement",
|
||||
label: "Implement",
|
||||
behavior: "allow",
|
||||
variant: "primary",
|
||||
intent: "implement",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(requestParsed.payload.event.type).toBe("permission_requested");
|
||||
if (requestParsed.payload.event.type === "permission_requested") {
|
||||
expect(requestParsed.payload.event.request.actions).toHaveLength(2);
|
||||
expect(requestParsed.payload.event.request.actions?.[1]?.label).toBe("Implement");
|
||||
}
|
||||
|
||||
const resolutionParsed = AgentStreamMessageSchema.parse({
|
||||
type: "agent_stream",
|
||||
payload: {
|
||||
agentId: "agent_live",
|
||||
timestamp: "2026-02-08T20:10:01.000Z",
|
||||
event: {
|
||||
type: "permission_resolved",
|
||||
provider: "claude",
|
||||
requestId: "perm-1",
|
||||
resolution: {
|
||||
behavior: "allow",
|
||||
selectedActionId: "implement_resume",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(resolutionParsed.payload.event.type).toBe("permission_resolved");
|
||||
if (resolutionParsed.payload.event.type === "permission_resolved") {
|
||||
expect(resolutionParsed.payload.event.resolution).toEqual({
|
||||
behavior: "allow",
|
||||
selectedActionId: "implement_resume",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it("rejects removed initialize_agent_request inbound payload", () => {
|
||||
const parsed = SessionInboundMessageSchema.safeParse({
|
||||
type: "initialize_agent_request",
|
||||
|
||||
@@ -146,6 +146,8 @@ const AgentUsageSchema: z.ZodType<AgentUsage> = z.object({
|
||||
cachedInputTokens: z.number().optional(),
|
||||
outputTokens: z.number().optional(),
|
||||
totalCostUsd: z.number().optional(),
|
||||
contextWindowMaxTokens: z.number().optional(),
|
||||
contextWindowUsedTokens: z.number().optional(),
|
||||
});
|
||||
|
||||
const McpStdioServerConfigSchema = z.object({
|
||||
@@ -197,15 +199,24 @@ const AgentSessionConfigSchema = z.object({
|
||||
});
|
||||
|
||||
const AgentPermissionUpdateSchema = z.record(z.unknown());
|
||||
const AgentPermissionActionSchema = z.object({
|
||||
id: z.string(),
|
||||
label: z.string(),
|
||||
behavior: z.enum(["allow", "deny"]),
|
||||
variant: z.enum(["primary", "secondary", "danger"]).optional(),
|
||||
intent: z.enum(["implement", "implement_resume", "dismiss"]).optional(),
|
||||
});
|
||||
|
||||
export const AgentPermissionResponseSchema: z.ZodType<AgentPermissionResponse> = z.union([
|
||||
z.object({
|
||||
behavior: z.literal("allow"),
|
||||
selectedActionId: z.string().optional(),
|
||||
updatedInput: z.record(z.unknown()).optional(),
|
||||
updatedPermissions: z.array(AgentPermissionUpdateSchema).optional(),
|
||||
}),
|
||||
z.object({
|
||||
behavior: z.literal("deny"),
|
||||
selectedActionId: z.string().optional(),
|
||||
message: z.string().optional(),
|
||||
interrupt: z.boolean().optional(),
|
||||
}),
|
||||
@@ -220,6 +231,7 @@ export const AgentPermissionRequestPayloadSchema: z.ZodType<AgentPermissionReque
|
||||
description: z.string().optional(),
|
||||
input: z.record(z.unknown()).optional(),
|
||||
suggestions: z.array(AgentPermissionUpdateSchema).optional(),
|
||||
actions: z.array(AgentPermissionActionSchema).optional(),
|
||||
metadata: z.record(z.unknown()).optional(),
|
||||
});
|
||||
|
||||
@@ -978,6 +990,7 @@ const CheckoutErrorSchema = z.object({
|
||||
const CheckoutDiffCompareSchema = z.object({
|
||||
mode: z.enum(["uncommitted", "base"]),
|
||||
baseRef: z.string().optional(),
|
||||
ignoreWhitespace: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const CheckoutStatusRequestSchema = z.object({
|
||||
@@ -1098,6 +1111,32 @@ export const WorkspaceSetupStatusRequestSchema = z.object({
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const EditorTargetIdSchema = z.enum([
|
||||
"cursor",
|
||||
"vscode",
|
||||
"zed",
|
||||
"finder",
|
||||
"explorer",
|
||||
"file-manager",
|
||||
]);
|
||||
|
||||
export const EditorTargetDescriptorPayloadSchema = z.object({
|
||||
id: EditorTargetIdSchema,
|
||||
label: z.string(),
|
||||
});
|
||||
|
||||
export const ListAvailableEditorsRequestSchema = z.object({
|
||||
type: z.literal("list_available_editors_request"),
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const OpenInEditorRequestSchema = z.object({
|
||||
type: z.literal("open_in_editor_request"),
|
||||
path: z.string(),
|
||||
editorId: EditorTargetIdSchema,
|
||||
requestId: z.string(),
|
||||
});
|
||||
|
||||
export const OpenProjectRequestSchema = z.object({
|
||||
type: z.literal("open_project_request"),
|
||||
cwd: z.string(),
|
||||
@@ -1366,6 +1405,8 @@ export const SessionInboundMessageSchema = z.discriminatedUnion("type", [
|
||||
PaseoWorktreeArchiveRequestSchema,
|
||||
CreatePaseoWorktreeRequestSchema,
|
||||
WorkspaceSetupStatusRequestSchema,
|
||||
ListAvailableEditorsRequestSchema,
|
||||
OpenInEditorRequestSchema,
|
||||
OpenProjectRequestSchema,
|
||||
ArchiveWorkspaceRequestSchema,
|
||||
FileExplorerRequestSchema,
|
||||
@@ -1915,6 +1956,23 @@ export const StartWorkspaceServiceResponseMessageSchema = z.object({
|
||||
}),
|
||||
});
|
||||
|
||||
export const ListAvailableEditorsResponseMessageSchema = z.object({
|
||||
type: z.literal("list_available_editors_response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
editors: z.array(EditorTargetDescriptorPayloadSchema),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const OpenInEditorResponseMessageSchema = z.object({
|
||||
type: z.literal("open_in_editor_response"),
|
||||
payload: z.object({
|
||||
requestId: z.string(),
|
||||
error: z.string().nullable(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const ArchiveWorkspaceResponseMessageSchema = z.object({
|
||||
type: z.literal("archive_workspace_response"),
|
||||
payload: z.object({
|
||||
@@ -2608,6 +2666,8 @@ export const SessionOutboundMessageSchema = z.discriminatedUnion("type", [
|
||||
FetchWorkspacesResponseMessageSchema,
|
||||
OpenProjectResponseMessageSchema,
|
||||
StartWorkspaceServiceResponseMessageSchema,
|
||||
ListAvailableEditorsResponseMessageSchema,
|
||||
OpenInEditorResponseMessageSchema,
|
||||
ArchiveWorkspaceResponseMessageSchema,
|
||||
FetchAgentResponseMessageSchema,
|
||||
FetchAgentTimelineResponseMessageSchema,
|
||||
@@ -2708,6 +2768,8 @@ export type WorkspaceDescriptorPayload = z.infer<typeof WorkspaceDescriptorPaylo
|
||||
export type WorkspaceServiceLifecycle = z.infer<typeof WorkspaceServiceLifecycleSchema>;
|
||||
export type WorkspaceServiceHealth = z.infer<typeof WorkspaceServiceHealthSchema>;
|
||||
export type WorkspaceServicePayload = z.infer<typeof WorkspaceServicePayloadSchema>;
|
||||
export type EditorTargetId = z.infer<typeof EditorTargetIdSchema>;
|
||||
export type EditorTargetDescriptorPayload = z.infer<typeof EditorTargetDescriptorPayloadSchema>;
|
||||
export type FetchAgentsResponseMessage = z.infer<typeof FetchAgentsResponseMessageSchema>;
|
||||
export type FetchWorkspacesResponseMessage = z.infer<typeof FetchWorkspacesResponseMessageSchema>;
|
||||
export type ServiceStatusUpdateMessage = z.infer<typeof ServiceStatusUpdateMessageSchema>;
|
||||
@@ -2715,6 +2777,10 @@ export type OpenProjectResponseMessage = z.infer<typeof OpenProjectResponseMessa
|
||||
export type StartWorkspaceServiceResponseMessage = z.infer<
|
||||
typeof StartWorkspaceServiceResponseMessageSchema
|
||||
>;
|
||||
export type ListAvailableEditorsResponseMessage = z.infer<
|
||||
typeof ListAvailableEditorsResponseMessageSchema
|
||||
>;
|
||||
export type OpenInEditorResponseMessage = z.infer<typeof OpenInEditorResponseMessageSchema>;
|
||||
export type ArchiveWorkspaceResponseMessage = z.infer<typeof ArchiveWorkspaceResponseMessageSchema>;
|
||||
export type FetchAgentResponseMessage = z.infer<typeof FetchAgentResponseMessageSchema>;
|
||||
export type FetchAgentTimelineResponseMessage = z.infer<
|
||||
@@ -2863,6 +2929,8 @@ export type PaseoWorktreeListResponse = z.infer<typeof PaseoWorktreeListResponse
|
||||
export type PaseoWorktreeArchiveRequest = z.infer<typeof PaseoWorktreeArchiveRequestSchema>;
|
||||
export type PaseoWorktreeArchiveResponse = z.infer<typeof PaseoWorktreeArchiveResponseSchema>;
|
||||
export type WorkspaceSetupStatusRequest = z.infer<typeof WorkspaceSetupStatusRequestSchema>;
|
||||
export type ListAvailableEditorsRequest = z.infer<typeof ListAvailableEditorsRequestSchema>;
|
||||
export type OpenInEditorRequest = z.infer<typeof OpenInEditorRequestSchema>;
|
||||
export type OpenProjectRequest = z.infer<typeof OpenProjectRequestSchema>;
|
||||
export type ArchiveWorkspaceRequest = z.infer<typeof ArchiveWorkspaceRequestSchema>;
|
||||
export type FileExplorerRequest = z.infer<typeof FileExplorerRequestSchema>;
|
||||
|
||||
@@ -29,6 +29,27 @@ describe("workspace message schemas", () => {
|
||||
expect(parsed.type).toBe("open_project_request");
|
||||
});
|
||||
|
||||
test("parses list_available_editors_request", () => {
|
||||
const parsed = SessionInboundMessageSchema.parse({
|
||||
type: "list_available_editors_request",
|
||||
requestId: "req-editors",
|
||||
});
|
||||
|
||||
expect(parsed.type).toBe("list_available_editors_request");
|
||||
});
|
||||
|
||||
test("parses open_in_editor_response", () => {
|
||||
const parsed = SessionOutboundMessageSchema.parse({
|
||||
type: "open_in_editor_response",
|
||||
payload: {
|
||||
requestId: "req-open-editor",
|
||||
error: null,
|
||||
},
|
||||
});
|
||||
|
||||
expect(parsed.type).toBe("open_in_editor_response");
|
||||
});
|
||||
|
||||
test("rejects invalid workspace update payload", () => {
|
||||
const result = SessionOutboundMessageSchema.safeParse({
|
||||
type: "workspace_update",
|
||||
|
||||
Reference in New Issue
Block a user