fix(goal): normalize strict-schema fillers

This commit is contained in:
Tianyi Cui
2026-07-24 20:45:23 +08:00
parent 145ba169f6
commit 9e691d54c0
10 changed files with 101 additions and 49 deletions
+11 -9
View File
@@ -132,13 +132,13 @@ function resolveConfig(config: Config): ResolvedConfig {
return { blockedAfterConsecutiveRounds: blockedAfter }
}
/** Whether an optional string carries a meaningful action-specific value. */
function hasText(value: string | undefined): boolean {
/** Whether optional text is meaningful rather than a strict-schema empty filler. */
function hasText(value: string | undefined): value is string {
return value !== undefined && value !== ''
}
/** Whether an optional round cap carries a meaningful action-specific value. */
function hasRoundCap(value: number | undefined): boolean {
/** Whether an optional round cap is meaningful rather than a strict-schema zero filler. */
function hasRoundCap(value: number | undefined): value is number {
return value !== undefined && value !== 0
}
@@ -281,13 +281,11 @@ export function apply(ctx: Context, config: Config): void {
const execution = goalToolExecution(ctx, exec)
const ref = goalRef(args.goal_id, args.revision)
const replacements = {
...args.objective === undefined ? {} : { objective: args.objective },
...args.max_goal_rounds === undefined ? {} : { maxGoalRounds: args.max_goal_rounds },
...hasText(args.objective) ? { objective: args.objective } : {},
...hasRoundCap(args.max_goal_rounds) ? { maxGoalRounds: args.max_goal_rounds } : {},
}
if (args.action === 'edit') {
requireDirectHuman(ctx, execution)
// Some strict-schema providers emit empty placeholders for every declared
// optional field. Reject only values that could change another action.
if (hasText(args.blocked_reason)) {
throw new HarnessError('blocked_reason is valid only with action blocked', 'GOAL_TOOL_INVALID_UPDATE')
}
@@ -343,7 +341,11 @@ export function apply(ctx: Context, config: Config): void {
presentCall: args => present(
`${args.action === 'blocked' ? 'Mark' : args.action.charAt(0).toUpperCase() + args.action.slice(1)} goal`,
'other',
args.blocked_reason ?? args.objective ?? args.goal_id,
hasText(args.blocked_reason)
? args.blocked_reason
: hasText(args.objective)
? args.objective
: hasRoundCap(args.max_goal_rounds) ? args.max_goal_rounds : args.goal_id,
),
}))
}