feat(coding-agent/task): added task.enableEffort setting to gate effort parameter

- Introduce task.enableEffort setting defaulting to false to hide per-spawn effort parameters.
- Conditionally include effort in single and batch task schemas and descriptions based on the new setting.
This commit is contained in:
can1357
2026-07-27 07:01:09 +02:00
parent d1239fd3e5
commit 0388946e85
6 changed files with 118 additions and 66 deletions
@@ -24,6 +24,7 @@ import * as discoveryModule from "@oh-my-pi/pi-coding-agent/task/discovery";
import * as executorModule from "@oh-my-pi/pi-coding-agent/task/executor";
import type { AgentDefinition, SingleResult, TaskParams } from "@oh-my-pi/pi-coding-agent/task/types";
import type { ToolSession } from "@oh-my-pi/pi-coding-agent/tools";
import { isRecord } from "@oh-my-pi/pi-utils";
const taskAgent: AgentDefinition = {
name: "task",
@@ -53,8 +54,14 @@ function createSession(
}
function getSchemaProperties(tool: TaskTool): Record<string, unknown> {
const wire = toolWireSchema(tool) as { properties?: Record<string, unknown> };
return wire.properties ?? {};
const properties = toolWireSchema(tool).properties;
return isRecord(properties) ? properties : {};
}
function getBatchItemProperties(tool: TaskTool): Record<string, unknown> {
const tasks = getSchemaProperties(tool).tasks;
if (!isRecord(tasks) || !isRecord(tasks.items) || !isRecord(tasks.items.properties)) return {};
return tasks.items.properties;
}
function getFirstText(result: { content: Array<{ type: string; text?: string }> }): string {
@@ -116,13 +123,35 @@ describe("task.batch schema gating", () => {
expect(onProperties.agent).toBeUndefined();
expect(onProperties.outputSchema).toBeUndefined();
expect(onProperties.schemaMode).toBeUndefined();
const items = (onProperties.tasks as { items?: { properties?: Record<string, unknown> } }).items;
expect(items?.properties?.task).toBeDefined();
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();
const itemProperties = getBatchItemProperties(on);
expect(itemProperties.task).toBeDefined();
expect(itemProperties.name).toBeDefined();
expect(itemProperties.agent).toBeDefined();
expect(itemProperties.outputSchema).toBeDefined();
expect(typeof itemProperties.outputSchema).toBe("object");
expect(itemProperties.schemaMode).toBeDefined();
});
it("hides effort by default and exposes it when task.enableEffort is enabled", async () => {
mockDiscovery();
const flatSession = createSession({ settings: { "task.batch": false } });
const flat = await TaskTool.create(flatSession);
expect(getSchemaProperties(flat).effort).toBeUndefined();
expect(flat.description).not.toContain("`effort`");
flatSession.settings.override("task.enableEffort", true);
expect(getSchemaProperties(flat).effort).toBeDefined();
expect(flat.description).toContain("`effort`");
const batchSession = createSession({ settings: { "task.batch": true } });
const batch = await TaskTool.create(batchSession);
expect(getBatchItemProperties(batch).effort).toBeUndefined();
expect(batch.description).not.toContain("`effort`");
batchSession.settings.override("task.enableEffort", true);
expect(getBatchItemProperties(batch).effort).toBeDefined();
expect(batch.description).toContain("`effort`");
});
it("keeps isolation boolean-only and describes the configured apply behavior", async () => {
@@ -133,13 +162,13 @@ describe("task.batch schema gating", () => {
);
const properties = getSchemaProperties(tool);
expect(properties.isolated).toBeUndefined();
const items = (properties.tasks as { items?: { properties?: Record<string, unknown> } }).items;
const isolatedSchema = items?.properties?.isolated;
const itemProperties = getBatchItemProperties(tool);
const isolatedSchema = itemProperties.isolated;
if (!isolatedSchema || typeof isolatedSchema !== "object" || !("type" in isolatedSchema)) {
throw new Error("Expected isolated to be a boolean schema");
}
expect(isolatedSchema.type).toBe("boolean");
expect(items?.properties?.apply).toBeUndefined();
expect(itemProperties.apply).toBeUndefined();
expect(tool.description).toContain("automatically applied to the parent checkout");
const captureTool = await TaskTool.create(
@@ -162,9 +191,8 @@ describe("task.batch schema gating", () => {
settings: { "task.batch": true, "task.isolation.mode": "auto" },
}),
);
const properties = getSchemaProperties(tool);
const items = (properties.tasks as { items?: { properties?: Record<string, unknown> } }).items;
expect(items?.properties?.isolated).toBeUndefined();
const itemProperties = getBatchItemProperties(tool);
expect(itemProperties.isolated).toBeUndefined();
expect(tool.description).not.toContain("`isolated`");
});