From 83bfb6dbd8ca94e42ee8de718fa23ff90c1acee1 Mon Sep 17 00:00:00 2001 From: roboomp Date: Sat, 18 Jul 2026 04:11:26 +0000 Subject: [PATCH] fix(task): avoided boolean output subschemas Represent task output schema inputs as explicit JSON-compatible types so ArkType emits object-form subschemas accepted by llama.cpp grammar generation. Fixes #5957 --- packages/coding-agent/CHANGELOG.md | 4 ++++ packages/coding-agent/src/task/types.ts | 19 +++++++++++-------- .../coding-agent/test/task/task-batch.test.ts | 2 ++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index ad20be261..161776971 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Fixed + +- Fixed `task` tool schemas emitting boolean subschemas that llama.cpp grammar generation cannot parse ([#5957](https://github.com/can1357/oh-my-pi/issues/5957)). + ## [17.0.3] - 2026-07-17 ### Changed diff --git a/packages/coding-agent/src/task/types.ts b/packages/coding-agent/src/task/types.ts index e6d2aad6f..62007fd3d 100644 --- a/packages/coding-agent/src/task/types.ts +++ b/packages/coding-agent/src/task/types.ts @@ -106,11 +106,14 @@ export interface SubagentLifecyclePayload { /** Display cap for a normalized one-line label (roster line, registry `displayName`, prompt field). */ export const LABEL_MAX = 80; +// Keep this explicit: ArkType serializes `unknown` as a boolean subschema, which llama.cpp grammars reject. +const outputSchemaInputSchema = type("object | boolean | string | null"); + export const taskItemSchema = type({ "name?": "string", agent: "string = 'task'", task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "+": "delete", }); @@ -118,7 +121,7 @@ const taskItemSchemaIsolated = type({ "name?": "string", agent: "string = 'task'", task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "isolated?": "boolean", "+": "delete", @@ -144,7 +147,7 @@ export const taskSchema = type({ "name?": "string", agent: "string = 'task'", task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "isolated?": "boolean", "+": "delete", @@ -153,7 +156,7 @@ const taskSchemaNoIsolation = type({ "name?": "string", agent: "string = 'task'", task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "+": "delete", }); @@ -197,7 +200,7 @@ function createTaskSchema(options: { "name?": "string", agent, task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "isolated?": "boolean", "+": "delete", @@ -212,7 +215,7 @@ function createTaskSchema(options: { "name?": "string", agent, task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "+": "delete", }); @@ -227,7 +230,7 @@ function createTaskSchema(options: { "name?": "string", agent, task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "isolated?": "boolean", "+": "delete", @@ -237,7 +240,7 @@ function createTaskSchema(options: { "name?": "string", agent, task: "string", - "outputSchema?": "unknown", + "outputSchema?": outputSchemaInputSchema, "schemaMode?": '"permissive" | "strict"', "+": "delete", }); diff --git a/packages/coding-agent/test/task/task-batch.test.ts b/packages/coding-agent/test/task/task-batch.test.ts index 019dd4ef2..9af6cb447 100644 --- a/packages/coding-agent/test/task/task-batch.test.ts +++ b/packages/coding-agent/test/task/task-batch.test.ts @@ -102,6 +102,7 @@ describe("task.batch schema gating", () => { expect(offProperties.task).toBeDefined(); expect(offProperties.name).toBeDefined(); expect(offProperties.outputSchema).toBeDefined(); + expect(typeof offProperties.outputSchema).toBe("object"); expect(offProperties.schemaMode).toBeDefined(); const on = await TaskTool.create(createSession({ settings: { "task.batch": true } })); @@ -120,6 +121,7 @@ describe("task.batch schema gating", () => { expect(items?.properties?.name).toBeDefined(); expect(items?.properties?.agent).toBeDefined(); expect(items?.properties?.outputSchema).toBeDefined(); + expect(typeof items?.properties?.outputSchema).toBe("object"); expect(items?.properties?.schemaMode).toBeDefined(); });