Skip to content

Commit 8493ec9

Browse files
fix(cli): Pi RPC parsers compatible with Zod 4 optional fields (#973)
asStrOrDef/asOpt* helpers now treat missing keys as undefined so get_available_models/get_commands parsing works again. safeParse success checked explicitly. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent f51e06e commit 8493ec9

1 file changed

Lines changed: 15 additions & 13 deletions

File tree

cli/src/pi/schemas.ts

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ import type { PiModelSummary } from '@hapi/protocol/apiTypes';
1717
// 字段级容错 schema
1818
// ============================================================================
1919

20-
/** 提取 string 值,非 string 返回 undefined */
21-
const asOptStr = z.unknown().transform(v => typeof v === 'string' ? v : undefined);
20+
/** 提取 string 值,非 string 或缺失返回 undefined */
21+
const asOptStr = z.unknown().optional().transform(v => typeof v === 'string' ? v : undefined);
2222

23-
/** 提取 number 值,非 number 返回 undefined */
24-
const asOptNum = z.unknown().transform(v => typeof v === 'number' ? v : undefined);
23+
/** 提取 number 值,非 number 或缺失返回 undefined */
24+
const asOptNum = z.unknown().optional().transform(v => typeof v === 'number' ? v : undefined);
2525

26-
/** 提取 boolean 值,非 boolean 返回 undefined */
27-
const asOptBool = z.unknown().transform(v => typeof v === 'boolean' ? v : undefined);
26+
/** 提取 boolean 值,非 boolean 或缺失返回 undefined */
27+
const asOptBool = z.unknown().optional().transform(v => typeof v === 'boolean' ? v : undefined);
2828

29-
/** 提取 string 值,非 string 返回指定默认值 */
30-
const asStrOrDef = (def: string) => z.unknown().transform(v => typeof v === 'string' ? v : def);
29+
/** 提取 string 值,非 string 或缺失返回指定默认值 */
30+
const asStrOrDef = (def: string) => z.unknown().optional().transform(v => typeof v === 'string' ? v : def);
3131

32-
/** 提取合法的 thinkingLevelMap,非法结构返回 undefined */
33-
const asOptThinkingLevelMap = z.unknown().transform((v): Record<string, string | null> | undefined => {
32+
/** 提取合法的 thinkingLevelMap,非法结构或缺失返回 undefined */
33+
const asOptThinkingLevelMap = z.unknown().optional().transform((v): Record<string, string | null> | undefined => {
3434
if (typeof v !== 'object' || v === null) return undefined;
3535
const map: Record<string, string | null> = {};
3636
for (const [key, val] of Object.entries(v as Record<string, unknown>)) {
@@ -80,7 +80,7 @@ const PiCommandSummarySchema = z.object({
8080
const PiCommandEntrySchema = z.object({
8181
name: asStrOrDef(''),
8282
description: asOptStr,
83-
source: z.unknown().transform(v =>
83+
source: z.unknown().optional().transform(v =>
8484
VALID_COMMAND_SOURCES.includes(v as PiCommandSource)
8585
? (v as PiCommandSource)
8686
: ('skill' as const),
@@ -195,9 +195,11 @@ export const PiAssistantMessageEventSchema = z.object({
195195
// ============================================================================
196196

197197
export function parsePiCommands(data: unknown) {
198-
return PiCommandsResponseDataSchema.safeParse(data).data ?? [];
198+
const result = PiCommandsResponseDataSchema.safeParse(data)
199+
return result.success ? result.data : []
199200
}
200201

201202
export function parsePiModels(data: unknown) {
202-
return PiModelsResponseDataSchema.safeParse(data).data ?? [];
203+
const result = PiModelsResponseDataSchema.safeParse(data)
204+
return result.success ? result.data : []
203205
}

0 commit comments

Comments
 (0)