Merge pull request #599 from mcinteerj/fix/gemini-tool-schemas
fix: simplify tool schemas for Gemini compatibility
This commit is contained in:
@@ -23,6 +23,43 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
import { createClawdbotTools } from "./clawdbot-tools.js";
|
||||
|
||||
describe("sessions tools", () => {
|
||||
it("uses number (not integer) in tool schemas for Gemini compatibility", () => {
|
||||
const tools = createClawdbotTools();
|
||||
const byName = (name: string) => {
|
||||
const tool = tools.find((candidate) => candidate.name === name);
|
||||
expect(tool).toBeDefined();
|
||||
if (!tool) throw new Error(`missing ${name} tool`);
|
||||
return tool;
|
||||
};
|
||||
|
||||
const schemaProp = (toolName: string, prop: string) => {
|
||||
const tool = byName(toolName);
|
||||
const schema = tool.parameters as {
|
||||
anyOf?: unknown;
|
||||
oneOf?: unknown;
|
||||
properties?: Record<string, unknown>;
|
||||
};
|
||||
expect(schema.anyOf).toBeUndefined();
|
||||
expect(schema.oneOf).toBeUndefined();
|
||||
|
||||
const properties = schema.properties ?? {};
|
||||
const value = properties[prop] as { type?: unknown } | undefined;
|
||||
expect(value).toBeDefined();
|
||||
if (!value) throw new Error(`missing ${toolName} schema prop: ${prop}`);
|
||||
return value;
|
||||
};
|
||||
|
||||
expect(schemaProp("sessions_history", "limit").type).toBe("number");
|
||||
expect(schemaProp("sessions_list", "limit").type).toBe("number");
|
||||
expect(schemaProp("sessions_list", "activeMinutes").type).toBe("number");
|
||||
expect(schemaProp("sessions_list", "messageLimit").type).toBe("number");
|
||||
expect(schemaProp("sessions_send", "timeoutSeconds").type).toBe("number");
|
||||
expect(schemaProp("sessions_spawn", "runTimeoutSeconds").type).toBe(
|
||||
"number",
|
||||
);
|
||||
expect(schemaProp("sessions_spawn", "timeoutSeconds").type).toBe("number");
|
||||
});
|
||||
|
||||
it("sessions_list filters kinds and includes messages", async () => {
|
||||
callGatewayMock.mockReset();
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
|
||||
const SessionsHistoryToolSchema = Type.Object({
|
||||
sessionKey: Type.String(),
|
||||
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
||||
limit: Type.Optional(Type.Number({ minimum: 1 })),
|
||||
includeTools: Type.Optional(Type.Boolean()),
|
||||
});
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ type SessionListRow = {
|
||||
|
||||
const SessionsListToolSchema = Type.Object({
|
||||
kinds: Type.Optional(Type.Array(Type.String())),
|
||||
limit: Type.Optional(Type.Integer({ minimum: 1 })),
|
||||
activeMinutes: Type.Optional(Type.Integer({ minimum: 1 })),
|
||||
messageLimit: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
limit: Type.Optional(Type.Number({ minimum: 1 })),
|
||||
activeMinutes: Type.Optional(Type.Number({ minimum: 1 })),
|
||||
messageLimit: Type.Optional(Type.Number({ minimum: 0 })),
|
||||
});
|
||||
|
||||
function resolveSandboxSessionToolsVisibility(
|
||||
|
||||
@@ -30,25 +30,15 @@ import {
|
||||
resolvePingPongTurns,
|
||||
} from "./sessions-send-helpers.js";
|
||||
|
||||
const SessionsSendToolSchema = Type.Union([
|
||||
Type.Object(
|
||||
{
|
||||
sessionKey: Type.String(),
|
||||
message: Type.String(),
|
||||
timeoutSeconds: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
},
|
||||
{ additionalProperties: false },
|
||||
const SessionsSendToolSchema = Type.Object({
|
||||
sessionKey: Type.Optional(Type.String()),
|
||||
label: Type.Optional(
|
||||
Type.String({ minLength: 1, maxLength: SESSION_LABEL_MAX_LENGTH }),
|
||||
),
|
||||
Type.Object(
|
||||
{
|
||||
label: Type.String({ minLength: 1, maxLength: SESSION_LABEL_MAX_LENGTH }),
|
||||
agentId: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),
|
||||
message: Type.String(),
|
||||
timeoutSeconds: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
},
|
||||
{ additionalProperties: false },
|
||||
),
|
||||
]);
|
||||
agentId: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),
|
||||
message: Type.String(),
|
||||
timeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
|
||||
});
|
||||
|
||||
export function createSessionsSendTool(opts?: {
|
||||
agentSessionKey?: string;
|
||||
|
||||
@@ -25,9 +25,9 @@ const SessionsSpawnToolSchema = Type.Object({
|
||||
label: Type.Optional(Type.String()),
|
||||
agentId: Type.Optional(Type.String()),
|
||||
model: Type.Optional(Type.String()),
|
||||
runTimeoutSeconds: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
runTimeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
|
||||
// Back-compat alias. Prefer runTimeoutSeconds.
|
||||
timeoutSeconds: Type.Optional(Type.Integer({ minimum: 0 })),
|
||||
timeoutSeconds: Type.Optional(Type.Number({ minimum: 0 })),
|
||||
cleanup: Type.Optional(
|
||||
Type.Union([Type.Literal("delete"), Type.Literal("keep")]),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user