refactor: lint cleanups and helpers

This commit is contained in:
Peter Steinberger
2025-12-23 00:28:40 +00:00
parent f5837dff9c
commit 918cbdcf03
39 changed files with 679 additions and 338 deletions

View File

@@ -3,16 +3,6 @@ import fs from "node:fs/promises";
import type { AgentTool, AgentToolResult } from "@mariozechner/pi-ai";
import { type TSchema, Type } from "@sinclair/typebox";
import {
browserAct,
browserArmDialog,
browserArmFileChooser,
browserConsoleMessages,
browserNavigate,
browserPdfSave,
browserScreenshotAction,
} from "../browser/client-actions.js";
import {
browserCloseTab,
browserFocusTab,
@@ -23,13 +13,22 @@ import {
browserStop,
browserTabs,
} from "../browser/client.js";
import {
browserAct,
browserArmDialog,
browserArmFileChooser,
browserConsoleMessages,
browserNavigate,
browserPdfSave,
browserScreenshotAction,
} from "../browser/client-actions.js";
import { resolveBrowserConfig } from "../browser/config.js";
import {
type CameraFacing,
cameraTempPath,
parseCameraClipPayload,
parseCameraSnapPayload,
writeBase64ToFile,
type CameraFacing,
} from "../cli/nodes-camera.js";
import {
canvasSnapshotTempPath,
@@ -72,6 +71,31 @@ function resolveGatewayOptions(opts?: GatewayCallOptions) {
return { url, token, timeoutMs };
}
type StringParamOptions = {
required?: boolean;
trim?: boolean;
label?: string;
};
function readStringParam(
params: Record<string, unknown>,
key: string,
options: StringParamOptions = {},
) {
const { required = false, trim = true, label = key } = options;
const raw = params[key];
if (typeof raw !== "string") {
if (required) throw new Error(`${label} required`);
return undefined;
}
const value = trim ? raw.trim() : raw;
if (!value) {
if (required) throw new Error(`${label} required`);
return undefined;
}
return value;
}
async function callGatewayTool<T = unknown>(
method: string,
opts: GatewayCallOptions,
@@ -342,10 +366,22 @@ const BrowserActSchema = Type.Object({
});
const BrowserToolSchema = Type.Union([
Type.Object({ action: Type.Literal("status"), controlUrl: Type.Optional(Type.String()) }),
Type.Object({ action: Type.Literal("start"), controlUrl: Type.Optional(Type.String()) }),
Type.Object({ action: Type.Literal("stop"), controlUrl: Type.Optional(Type.String()) }),
Type.Object({ action: Type.Literal("tabs"), controlUrl: Type.Optional(Type.String()) }),
Type.Object({
action: Type.Literal("status"),
controlUrl: Type.Optional(Type.String()),
}),
Type.Object({
action: Type.Literal("start"),
controlUrl: Type.Optional(Type.String()),
}),
Type.Object({
action: Type.Literal("stop"),
controlUrl: Type.Optional(Type.String()),
}),
Type.Object({
action: Type.Literal("tabs"),
controlUrl: Type.Optional(Type.String()),
}),
Type.Object({
action: Type.Literal("open"),
controlUrl: Type.Optional(Type.String()),
@@ -364,7 +400,9 @@ const BrowserToolSchema = Type.Union([
Type.Object({
action: Type.Literal("snapshot"),
controlUrl: Type.Optional(Type.String()),
format: Type.Optional(Type.Union([Type.Literal("aria"), Type.Literal("ai")])),
format: Type.Optional(
Type.Union([Type.Literal("aria"), Type.Literal("ai")]),
),
targetId: Type.Optional(Type.String()),
limit: Type.Optional(Type.Number()),
}),
@@ -375,7 +413,9 @@ const BrowserToolSchema = Type.Union([
fullPage: Type.Optional(Type.Boolean()),
ref: Type.Optional(Type.String()),
element: Type.Optional(Type.String()),
type: Type.Optional(Type.Union([Type.Literal("png"), Type.Literal("jpeg")])),
type: Type.Optional(
Type.Union([Type.Literal("png"), Type.Literal("jpeg")]),
),
}),
Type.Object({
action: Type.Literal("navigate"),
@@ -425,9 +465,8 @@ function createBrowserTool(): AnyAgentTool {
parameters: BrowserToolSchema,
execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>;
const action = String(params.action ?? "");
const controlUrl =
typeof params.controlUrl === "string" ? params.controlUrl : undefined;
const action = readStringParam(params, "action", { required: true });
const controlUrl = readStringParam(params, "controlUrl");
const baseUrl = resolveBrowserBaseUrl(controlUrl);
switch (action) {
@@ -442,19 +481,20 @@ function createBrowserTool(): AnyAgentTool {
case "tabs":
return jsonResult({ tabs: await browserTabs(baseUrl) });
case "open": {
const targetUrl = String(params.targetUrl ?? "").trim();
if (!targetUrl) throw new Error("targetUrl required");
const targetUrl = readStringParam(params, "targetUrl", {
required: true,
});
return jsonResult(await browserOpenTab(baseUrl, targetUrl));
}
case "focus": {
const targetId = String(params.targetId ?? "").trim();
if (!targetId) throw new Error("targetId required");
const targetId = readStringParam(params, "targetId", {
required: true,
});
await browserFocusTab(baseUrl, targetId);
return jsonResult({ ok: true });
}
case "close": {
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : "";
const targetId = readStringParam(params, "targetId");
if (targetId) await browserCloseTab(baseUrl, targetId);
else await browserAct(baseUrl, { kind: "close" });
return jsonResult({ ok: true });
@@ -465,7 +505,9 @@ function createBrowserTool(): AnyAgentTool {
? (params.format as "ai" | "aria")
: "aria";
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
typeof params.targetId === "string"
? params.targetId.trim()
: undefined;
const limit =
typeof params.limit === "number" && Number.isFinite(params.limit)
? params.limit
@@ -484,13 +526,10 @@ function createBrowserTool(): AnyAgentTool {
return jsonResult(snapshot);
}
case "screenshot": {
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
const targetId = readStringParam(params, "targetId");
const fullPage = Boolean(params.fullPage);
const ref =
typeof params.ref === "string" ? params.ref.trim() : undefined;
const element =
typeof params.element === "string" ? params.element.trim() : undefined;
const ref = readStringParam(params, "ref");
const element = readStringParam(params, "element");
const type = params.type === "jpeg" ? "jpeg" : "png";
const result = await browserScreenshotAction(baseUrl, {
targetId,
@@ -506,10 +545,10 @@ function createBrowserTool(): AnyAgentTool {
});
}
case "navigate": {
const targetUrl = String(params.targetUrl ?? "").trim();
if (!targetUrl) throw new Error("targetUrl required");
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
const targetUrl = readStringParam(params, "targetUrl", {
required: true,
});
const targetId = readStringParam(params, "targetId");
return jsonResult(
await browserNavigate(baseUrl, { url: targetUrl, targetId }),
);
@@ -518,14 +557,18 @@ function createBrowserTool(): AnyAgentTool {
const level =
typeof params.level === "string" ? params.level.trim() : undefined;
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
typeof params.targetId === "string"
? params.targetId.trim()
: undefined;
return jsonResult(
await browserConsoleMessages(baseUrl, { level, targetId }),
);
}
case "pdf": {
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
typeof params.targetId === "string"
? params.targetId.trim()
: undefined;
const result = await browserPdfSave(baseUrl, { targetId });
return {
content: [{ type: "text", text: `FILE:${result.path}` }],
@@ -538,23 +581,35 @@ function createBrowserTool(): AnyAgentTool {
: [];
if (paths.length === 0) throw new Error("paths required");
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
typeof params.targetId === "string"
? params.targetId.trim()
: undefined;
const timeoutMs =
typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs)
typeof params.timeoutMs === "number" &&
Number.isFinite(params.timeoutMs)
? params.timeoutMs
: undefined;
return jsonResult(
await browserArmFileChooser(baseUrl, { paths, targetId, timeoutMs }),
await browserArmFileChooser(baseUrl, {
paths,
targetId,
timeoutMs,
}),
);
}
case "dialog": {
const accept = Boolean(params.accept);
const promptText =
typeof params.promptText === "string" ? params.promptText : undefined;
typeof params.promptText === "string"
? params.promptText
: undefined;
const targetId =
typeof params.targetId === "string" ? params.targetId.trim() : undefined;
typeof params.targetId === "string"
? params.targetId.trim()
: undefined;
const timeoutMs =
typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs)
typeof params.timeoutMs === "number" &&
Number.isFinite(params.timeoutMs)
? params.timeoutMs
: undefined;
return jsonResult(
@@ -571,7 +626,10 @@ function createBrowserTool(): AnyAgentTool {
if (!request || typeof request !== "object") {
throw new Error("request required");
}
const result = await browserAct(baseUrl, request as Parameters<typeof browserAct>[1]);
const result = await browserAct(
baseUrl,
request as Parameters<typeof browserAct>[1],
);
return jsonResult(result);
}
default:
@@ -623,7 +681,13 @@ const CanvasToolSchema = Type.Union([
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
node: Type.Optional(Type.String()),
format: Type.Optional(Type.Union([Type.Literal("png"), Type.Literal("jpg"), Type.Literal("jpeg")])),
format: Type.Optional(
Type.Union([
Type.Literal("png"),
Type.Literal("jpg"),
Type.Literal("jpeg"),
]),
),
maxWidth: Type.Optional(Type.Number()),
quality: Type.Optional(Type.Number()),
}),
@@ -654,25 +718,24 @@ function createCanvasTool(): AnyAgentTool {
parameters: CanvasToolSchema,
execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>;
const action = String(params.action ?? "");
const action = readStringParam(params, "action", { required: true });
const gatewayOpts: GatewayCallOptions = {
gatewayUrl:
typeof params.gatewayUrl === "string" ? params.gatewayUrl : undefined,
gatewayToken:
typeof params.gatewayToken === "string"
? params.gatewayToken
: undefined,
gatewayUrl: readStringParam(params, "gatewayUrl", { trim: false }),
gatewayToken: readStringParam(params, "gatewayToken", { trim: false }),
timeoutMs:
typeof params.timeoutMs === "number" ? params.timeoutMs : undefined,
};
const nodeId = await resolveNodeId(
gatewayOpts,
typeof params.node === "string" ? params.node : undefined,
readStringParam(params, "node", { trim: true }),
true,
);
const invoke = async (command: string, invokeParams?: Record<string, unknown>) =>
const invoke = async (
command: string,
invokeParams?: Record<string, unknown>,
) =>
await callGatewayTool("node.invoke", gatewayOpts, {
nodeId,
command,
@@ -686,7 +749,8 @@ function createCanvasTool(): AnyAgentTool {
x: typeof params.x === "number" ? params.x : undefined,
y: typeof params.y === "number" ? params.y : undefined,
width: typeof params.width === "number" ? params.width : undefined,
height: typeof params.height === "number" ? params.height : undefined,
height:
typeof params.height === "number" ? params.height : undefined,
};
const invokeParams: Record<string, unknown> = {};
if (typeof params.target === "string" && params.target.trim()) {
@@ -707,14 +771,14 @@ function createCanvasTool(): AnyAgentTool {
await invoke("canvas.hide", undefined);
return jsonResult({ ok: true });
case "navigate": {
const url = String(params.url ?? "").trim();
if (!url) throw new Error("url required");
const url = readStringParam(params, "url", { required: true });
await invoke("canvas.navigate", { url });
return jsonResult({ ok: true });
}
case "eval": {
const javaScript = String(params.javaScript ?? "").trim();
if (!javaScript) throw new Error("javaScript required");
const javaScript = readStringParam(params, "javaScript", {
required: true,
});
const raw = (await invoke("canvas.eval", { javaScript })) as {
payload?: { result?: string };
};
@@ -724,15 +788,19 @@ function createCanvasTool(): AnyAgentTool {
}
case "snapshot": {
const formatRaw =
typeof params.format === "string" ? params.format.toLowerCase() : "png";
typeof params.format === "string"
? params.format.toLowerCase()
: "png";
const format =
formatRaw === "jpg" || formatRaw === "jpeg" ? "jpeg" : "png";
const maxWidth =
typeof params.maxWidth === "number" && Number.isFinite(params.maxWidth)
typeof params.maxWidth === "number" &&
Number.isFinite(params.maxWidth)
? params.maxWidth
: undefined;
const quality =
typeof params.quality === "number" && Number.isFinite(params.quality)
typeof params.quality === "number" &&
Number.isFinite(params.quality)
? params.quality
: undefined;
const raw = (await invoke("canvas.snapshot", {
@@ -819,16 +887,20 @@ const NodesToolSchema = Type.Union([
title: Type.Optional(Type.String()),
body: Type.Optional(Type.String()),
sound: Type.Optional(Type.String()),
priority: Type.Optional(Type.Union([
Type.Literal("passive"),
Type.Literal("active"),
Type.Literal("timeSensitive"),
])),
delivery: Type.Optional(Type.Union([
Type.Literal("system"),
Type.Literal("overlay"),
Type.Literal("auto"),
])),
priority: Type.Optional(
Type.Union([
Type.Literal("passive"),
Type.Literal("active"),
Type.Literal("timeSensitive"),
]),
),
delivery: Type.Optional(
Type.Union([
Type.Literal("system"),
Type.Literal("overlay"),
Type.Literal("auto"),
]),
),
}),
Type.Object({
action: Type.Literal("camera_snap"),
@@ -836,7 +908,13 @@ const NodesToolSchema = Type.Union([
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
node: Type.String(),
facing: Type.Optional(Type.Union([Type.Literal("front"), Type.Literal("back"), Type.Literal("both")])),
facing: Type.Optional(
Type.Union([
Type.Literal("front"),
Type.Literal("back"),
Type.Literal("both"),
]),
),
maxWidth: Type.Optional(Type.Number()),
quality: Type.Optional(Type.Number()),
}),
@@ -846,7 +924,9 @@ const NodesToolSchema = Type.Union([
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
node: Type.String(),
facing: Type.Optional(Type.Union([Type.Literal("front"), Type.Literal("back")])),
facing: Type.Optional(
Type.Union([Type.Literal("front"), Type.Literal("back")]),
),
duration: Type.Optional(Type.String()),
durationMs: Type.Optional(Type.Number()),
includeAudio: Type.Optional(Type.Boolean()),
@@ -875,24 +955,21 @@ function createNodesTool(): AnyAgentTool {
parameters: NodesToolSchema,
execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>;
const action = String(params.action ?? "");
const action = readStringParam(params, "action", { required: true });
const gatewayOpts: GatewayCallOptions = {
gatewayUrl:
typeof params.gatewayUrl === "string" ? params.gatewayUrl : undefined,
gatewayToken:
typeof params.gatewayToken === "string"
? params.gatewayToken
: undefined,
gatewayUrl: readStringParam(params, "gatewayUrl", { trim: false }),
gatewayToken: readStringParam(params, "gatewayToken", { trim: false }),
timeoutMs:
typeof params.timeoutMs === "number" ? params.timeoutMs : undefined,
};
switch (action) {
case "status":
return jsonResult(await callGatewayTool("node.list", gatewayOpts, {}));
return jsonResult(
await callGatewayTool("node.list", gatewayOpts, {}),
);
case "describe": {
const node = String(params.node ?? "").trim();
if (!node) throw new Error("node required");
const node = readStringParam(params, "node", { required: true });
const nodeId = await resolveNodeId(gatewayOpts, node);
return jsonResult(
await callGatewayTool("node.describe", gatewayOpts, { nodeId }),
@@ -903,8 +980,9 @@ function createNodesTool(): AnyAgentTool {
await callGatewayTool("node.pair.list", gatewayOpts, {}),
);
case "approve": {
const requestId = String(params.requestId ?? "").trim();
if (!requestId) throw new Error("requestId required");
const requestId = readStringParam(params, "requestId", {
required: true,
});
return jsonResult(
await callGatewayTool("node.pair.approve", gatewayOpts, {
requestId,
@@ -912,8 +990,9 @@ function createNodesTool(): AnyAgentTool {
);
}
case "reject": {
const requestId = String(params.requestId ?? "").trim();
if (!requestId) throw new Error("requestId required");
const requestId = readStringParam(params, "requestId", {
required: true,
});
return jsonResult(
await callGatewayTool("node.pair.reject", gatewayOpts, {
requestId,
@@ -921,8 +1000,7 @@ function createNodesTool(): AnyAgentTool {
);
}
case "notify": {
const node = String(params.node ?? "").trim();
if (!node) throw new Error("node required");
const node = readStringParam(params, "node", { required: true });
const title = typeof params.title === "string" ? params.title : "";
const body = typeof params.body === "string" ? params.body : "";
if (!title.trim() && !body.trim()) {
@@ -935,22 +1013,28 @@ function createNodesTool(): AnyAgentTool {
params: {
title: title.trim() || undefined,
body: body.trim() || undefined,
sound: typeof params.sound === "string" ? params.sound : undefined,
sound:
typeof params.sound === "string" ? params.sound : undefined,
priority:
typeof params.priority === "string" ? params.priority : undefined,
typeof params.priority === "string"
? params.priority
: undefined,
delivery:
typeof params.delivery === "string" ? params.delivery : undefined,
typeof params.delivery === "string"
? params.delivery
: undefined,
},
idempotencyKey: crypto.randomUUID(),
});
return jsonResult({ ok: true });
}
case "camera_snap": {
const node = String(params.node ?? "").trim();
if (!node) throw new Error("node required");
const node = readStringParam(params, "node", { required: true });
const nodeId = await resolveNodeId(gatewayOpts, node);
const facingRaw =
typeof params.facing === "string" ? params.facing.toLowerCase() : "both";
typeof params.facing === "string"
? params.facing.toLowerCase()
: "both";
const facings: CameraFacing[] =
facingRaw === "both"
? ["front", "back"]
@@ -960,11 +1044,13 @@ function createNodesTool(): AnyAgentTool {
throw new Error("invalid facing (front|back|both)");
})();
const maxWidth =
typeof params.maxWidth === "number" && Number.isFinite(params.maxWidth)
typeof params.maxWidth === "number" &&
Number.isFinite(params.maxWidth)
? params.maxWidth
: undefined;
const quality =
typeof params.quality === "number" && Number.isFinite(params.quality)
typeof params.quality === "number" &&
Number.isFinite(params.quality)
? params.quality
: undefined;
@@ -994,8 +1080,7 @@ function createNodesTool(): AnyAgentTool {
content.push({
type: "image",
data: payload.base64,
mimeType:
payload.format === "jpeg" ? "image/jpeg" : "image/png",
mimeType: payload.format === "jpeg" ? "image/jpeg" : "image/png",
});
details.push({
facing,
@@ -1009,22 +1094,26 @@ function createNodesTool(): AnyAgentTool {
return await sanitizeToolResultImages(result, "nodes:camera_snap");
}
case "camera_clip": {
const node = String(params.node ?? "").trim();
if (!node) throw new Error("node required");
const node = readStringParam(params, "node", { required: true });
const nodeId = await resolveNodeId(gatewayOpts, node);
const facing =
typeof params.facing === "string" ? params.facing.toLowerCase() : "front";
typeof params.facing === "string"
? params.facing.toLowerCase()
: "front";
if (facing !== "front" && facing !== "back") {
throw new Error("invalid facing (front|back)");
}
const durationMs =
typeof params.durationMs === "number" && Number.isFinite(params.durationMs)
typeof params.durationMs === "number" &&
Number.isFinite(params.durationMs)
? params.durationMs
: typeof params.duration === "string"
? parseDurationMs(params.duration)
: 3000;
const includeAudio =
typeof params.includeAudio === "boolean" ? params.includeAudio : true;
typeof params.includeAudio === "boolean"
? params.includeAudio
: true;
const raw = (await callGatewayTool("node.invoke", gatewayOpts, {
nodeId,
command: "camera.clip",
@@ -1054,11 +1143,11 @@ function createNodesTool(): AnyAgentTool {
};
}
case "screen_record": {
const node = String(params.node ?? "").trim();
if (!node) throw new Error("node required");
const node = readStringParam(params, "node", { required: true });
const nodeId = await resolveNodeId(gatewayOpts, node);
const durationMs =
typeof params.durationMs === "number" && Number.isFinite(params.durationMs)
typeof params.durationMs === "number" &&
Number.isFinite(params.durationMs)
? params.durationMs
: typeof params.duration === "string"
? parseDurationMs(params.duration)
@@ -1068,11 +1157,14 @@ function createNodesTool(): AnyAgentTool {
? params.fps
: 10;
const screenIndex =
typeof params.screenIndex === "number" && Number.isFinite(params.screenIndex)
typeof params.screenIndex === "number" &&
Number.isFinite(params.screenIndex)
? params.screenIndex
: 0;
const includeAudio =
typeof params.includeAudio === "boolean" ? params.includeAudio : true;
typeof params.includeAudio === "boolean"
? params.includeAudio
: true;
const raw = (await callGatewayTool("node.invoke", gatewayOpts, {
nodeId,
command: "screen.record",
@@ -1168,7 +1260,9 @@ const CronToolSchema = Type.Union([
gatewayToken: Type.Optional(Type.String()),
timeoutMs: Type.Optional(Type.Number()),
text: Type.String(),
mode: Type.Optional(Type.Union([Type.Literal("now"), Type.Literal("next-heartbeat")])),
mode: Type.Optional(
Type.Union([Type.Literal("now"), Type.Literal("next-heartbeat")]),
),
}),
]);
@@ -1181,21 +1275,19 @@ function createCronTool(): AnyAgentTool {
parameters: CronToolSchema,
execute: async (_toolCallId, args) => {
const params = args as Record<string, unknown>;
const action = String(params.action ?? "");
const action = readStringParam(params, "action", { required: true });
const gatewayOpts: GatewayCallOptions = {
gatewayUrl:
typeof params.gatewayUrl === "string" ? params.gatewayUrl : undefined,
gatewayToken:
typeof params.gatewayToken === "string"
? params.gatewayToken
: undefined,
gatewayUrl: readStringParam(params, "gatewayUrl", { trim: false }),
gatewayToken: readStringParam(params, "gatewayToken", { trim: false }),
timeoutMs:
typeof params.timeoutMs === "number" ? params.timeoutMs : undefined,
};
switch (action) {
case "status":
return jsonResult(await callGatewayTool("cron.status", gatewayOpts, {}));
return jsonResult(
await callGatewayTool("cron.status", gatewayOpts, {}),
);
case "list":
return jsonResult(
await callGatewayTool("cron.list", gatewayOpts, {
@@ -1211,8 +1303,7 @@ function createCronTool(): AnyAgentTool {
);
}
case "update": {
const jobId = String(params.jobId ?? "").trim();
if (!jobId) throw new Error("jobId required");
const jobId = readStringParam(params, "jobId", { required: true });
if (!params.patch || typeof params.patch !== "object") {
throw new Error("patch required");
}
@@ -1224,29 +1315,25 @@ function createCronTool(): AnyAgentTool {
);
}
case "remove": {
const jobId = String(params.jobId ?? "").trim();
if (!jobId) throw new Error("jobId required");
const jobId = readStringParam(params, "jobId", { required: true });
return jsonResult(
await callGatewayTool("cron.remove", gatewayOpts, { jobId }),
);
}
case "run": {
const jobId = String(params.jobId ?? "").trim();
if (!jobId) throw new Error("jobId required");
const jobId = readStringParam(params, "jobId", { required: true });
return jsonResult(
await callGatewayTool("cron.run", gatewayOpts, { jobId }),
);
}
case "runs": {
const jobId = String(params.jobId ?? "").trim();
if (!jobId) throw new Error("jobId required");
const jobId = readStringParam(params, "jobId", { required: true });
return jsonResult(
await callGatewayTool("cron.runs", gatewayOpts, { jobId }),
);
}
case "wake": {
const text = String(params.text ?? "").trim();
if (!text) throw new Error("text required");
const text = readStringParam(params, "text", { required: true });
const mode =
params.mode === "now" || params.mode === "next-heartbeat"
? params.mode
@@ -1268,5 +1355,10 @@ function createCronTool(): AnyAgentTool {
}
export function createClawdisTools(): AnyAgentTool[] {
return [createBrowserTool(), createCanvasTool(), createNodesTool(), createCronTool()];
return [
createBrowserTool(),
createCanvasTool(),
createNodesTool(),
createCronTool(),
];
}

View File

@@ -418,7 +418,7 @@ export async function runEmbeddedPiAgent(params: {
params.abortSignal.addEventListener("abort", onAbort, { once: true });
}
}
let promptError: unknown | null = null;
let promptError: unknown = null;
try {
try {
await session.prompt(params.prompt);