Files
paseo/plugins/muse-provider/server/wire.ts
T
paseo-bot[bot]andMohamed Boudra d826d8109f fix(muse): load models whose effort tiers carry descriptions (#6021)
* fix(muse): load models whose effort tiers carry descriptions

Muse 1.4.2 sends reasoningEffortVariants as described tiers
({ tier, description? }) and the complete effort list on variants, as
the bundled MSP types declare. The catalog schema had the two shapes
swapped, so any model with a described tier failed the whole model/list
parse: the model picker stayed empty and agent creation failed.

Parse both fields as declared, offer the efforts from variants, and
show Muse's tier descriptions on the matching options.

* fix(muse): leave effort descriptions out until the pickers show them

* fix(muse): keep unused catalog metadata outside validation

Described effort tiers are presentation metadata, not selectable efforts. Validating their shape blocks both discovery and session startup even though Paseo never consumes them. Normalize the complete variants list at the wire boundary and cover session readiness and selecting max.

* fix(muse): align consumed session and event wire fields

---------

Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
2026-10-05 16:12:12 +01:00

287 lines
8.4 KiB
TypeScript

import { z } from "zod";
export const fingerprint =
"sha256:e0e163db6ccf00dbe68402ce55d6319b3edc33c421f31e9583b587b2de8a118f";
export const effortSchema = z.enum([
"none",
"minimal",
"low",
"medium",
"high",
"xhigh",
"max",
"ultra",
]);
export const approvalModeSchema = z.enum([
"onRequest",
"promptUnmatched",
"denyUnmatched",
"allowAll",
]);
export const itemSchema = z.object({
itemId: z.string(),
revision: z.number().int(),
childSessionId: z.string().optional(),
role: z.string().optional(),
objective: z.string().optional(),
message: z.string().default(""),
entryId: z.string().optional(),
kind: z.string(),
status: z.string(),
turnId: z.string().nullable().optional(),
commandId: z.string().optional(),
recordedAt: z.string().optional(),
text: z.string().default(""),
displayText: z.string().optional(),
summary: z.array(z.string()).default([]),
tool: z.string().default(""),
args: z.string().default("{}"),
callId: z.string().optional(),
commandText: z.string().optional(),
visibleOutput: z.string().default(""),
exitCode: z.number().optional(),
fallbackText: z.string().default(""),
failureReason: z.string().optional(),
patchRef: z.object({ id: z.string() }).optional(),
tokensBefore: z.number().optional(),
});
export type WireItem = z.infer<typeof itemSchema>;
export const requirementSchema = z.object({
approvalId: z.string(),
sourceIndex: z.number().optional(),
});
export const choiceSchema = z.object({
choiceId: z.string(),
decision: z.string(),
label: z.string(),
scope: z.string(),
});
export const approvalSchema = z.object({
approvalId: z.string(),
currentRequirementId: requirementSchema.optional(),
availableChoices: z.array(choiceSchema),
toolName: z.string().default("Tool"),
subject: z.object({
kind: z.string(),
command: z.string().default(""),
path: z.string().default(""),
host: z.string().default(""),
workspaceRoot: z.string().optional(),
stages: z
.array(
z.object({
position: z.number(),
totalStages: z.number(),
argv: z.array(z.string()),
requirementId: requirementSchema,
resolution: z.object({ kind: z.string() }),
}),
)
.default([]),
}),
});
export type WireApproval = z.infer<typeof approvalSchema>;
export const notificationSchema = z.object({
sessionId: z.string().optional(),
viewCursor: z.string().optional(),
});
export const frameSchema = z.object({
jsonrpc: z.literal("2.0"),
id: z.union([z.string(), z.number()]).nullable().optional(),
method: z.string().optional(),
params: z.unknown().optional(),
result: z.unknown().optional(),
error: z
.object({
code: z.number(),
message: z.string(),
data: z
.object({ kind: z.string().optional(), reason: z.string().optional() })
.passthrough()
.optional(),
})
.optional(),
});
export const initializedSchema = z.object({ schema: z.object({ fingerprint: z.string() }) });
export const accountSchema = z.object({
state: z.string(),
});
export const catalogSchema = z.object({
models: z.array(
z.object({
modelId: z.string(),
providerId: z.string(),
displayLabel: z.string(),
contextLimit: z.number().nullable(),
isDefault: z.boolean(),
defaultReasoningEffort: effortSchema.nullable().optional(),
// Validate consumed fields only. Muse's described subset (reasoningEffortVariants)
// is presentation metadata; its shape must not gate catalog discovery or session startup.
variants: z
.union([z.array(effortSchema), z.literal("unknown")])
.transform((variants) => (variants === "unknown" ? [] : variants))
.default([]),
}),
),
});
export const sessionSchema = z.object({
session: z.object({
sessionId: z.string(),
modelId: z.string().nullable(),
providerId: z.string().nullable(),
approvalMode: z.object({ mode: approvalModeSchema }).optional(),
}),
viewCursor: z.string(),
history: z
.object({ mode: z.string(), items: z.array(itemSchema).nullable().default([]) })
.optional(),
pendingRequests: z
.array(
z.object({ kind: z.string(), approvalId: z.string().optional(), viewCursor: z.string() }),
)
.default([]),
});
export const persistenceSchema = z.object({
sessionId: z.string(),
cursor: z.string().optional(),
model: z.string().optional(),
thinkingOption: effortSchema.optional(),
});
export const deltaSchema = z.object({
itemId: z.string(),
field: z.string().default("text"),
delta: z.string(),
});
export const turnSchema = z.object({
turnId: z.string(),
commandId: z.string().optional(),
terminal: z.string().optional(),
error: z.object({ kind: z.string(), message: z.string() }).optional(),
});
export const promptResultSchema = z.object({ turnId: z.string(), disposition: z.string() });
export const outputSchema = z.object({
content: z.string(),
encoding: z.enum(["utf8", "base64"]),
eof: z.boolean(),
});
export const patchSchema = z.object({
files: z.array(
z.object({
path: z.string(),
hunks: z.array(
z.object({
oldStart: z.number(),
oldLines: z.number(),
newStart: z.number(),
newLines: z.number(),
lines: z.array(z.string()),
}),
),
}),
),
});
export const toolArgsSchema = z.object({
objective: z.string().optional(),
role: z.string().optional(),
command: z.string().default(""),
path: z.string().default(""),
find: z.string().optional(),
replace: z.string().optional(),
content: z.string().optional(),
query: z.string().default(""),
pattern: z.string().default(""),
url: z.string().default(""),
});
export const tokenUsageSchema = z.object({
cumulative: z.object({ promptTokens: z.number(), outputTokens: z.number() }),
usage: z.object({ cachedTokens: z.number().optional() }).optional(),
});
export const contextUsageSchema = z.object({
usedTokens: z.number(),
windowTokens: z.number().optional(),
});
export const ackSchema = z.object({}).passthrough();
export const skillsSchema = z.object({
skills: z.array(
z.object({
selector: z.string(),
description: z.string(),
argumentHint: z.string().optional(),
}),
),
});
export const questionSchema = z.object({
userInputId: z.string(),
toolName: z.string(),
questions: z.array(
z.object({
id: z.string(),
header: z.string(),
question: z.string(),
options: z.array(z.object({ label: z.string(), description: z.string().default("") })),
selection: z.object({
mode: z.enum(["single", "multiple"]),
minSelections: z.number().optional(),
maxSelections: z.number().optional(),
}),
}),
),
});
export const settledQuestionSchema = z.object({ userInputId: z.string() });
export const questionAnswersSchema = z.object({ answers: z.record(z.string(), z.string()) });
export const todoSchema = z.object({
viewCursor: z.string(),
items: z.array(
z.object({ text: z.string(), status: z.string(), activeForm: z.string().optional() }),
),
});
export const pageSchema = z.object({
events: z.array(z.object({ method: z.string(), params: z.record(z.string(), z.unknown()) })),
nextCursor: z.string().nullable(),
});
export const gapSchema = z.object({ after: z.string(), next: z.string() });
export const sessionListSchema = z.object({
nextCursor: z.string().nullable(),
sessions: z.array(
z.object({
sessionId: z.string(),
workspaceRoot: z.string().nullable(),
title: z.string().optional(),
updatedAt: z.string(),
modelId: z.string().nullable(),
}),
),
});
export const usageSchema = z.object({
usage: z
.object({
observedAtMs: z.number(),
tier: z.string(),
window: z.object({
resetsAtMs: z.number(),
usedPercent: z.number(),
windowDurationMins: z.number(),
}),
weekly: z.object({ resetsAtMs: z.number(), usedPercent: z.number() }),
})
.optional(),
});
export const childSessionSchema = z.object({
session: z.object({
sessionId: z.string(),
workspaceRoot: z.string().nullable(),
title: z.string().optional(),
}),
viewCursor: z.string(),
});
export const itemNotificationSchema = z.object({ item: itemSchema });
export const pendingSchema = z.object({
approvals: z.array(approvalSchema),
userInputs: z.array(questionSchema).default([]),
});
export const approvalResolvedSchema = z.object({ approvalId: z.string() });