diff --git a/src/agents/pi-embedded-runner/compact.ts b/src/agents/pi-embedded-runner/compact.ts index 7d2f8815c7d..5b78971037f 100644 --- a/src/agents/pi-embedded-runner/compact.ts +++ b/src/agents/pi-embedded-runner/compact.ts @@ -1,3 +1,5 @@ +import fs from "node:fs/promises"; +import os from "node:os"; import type { AgentMessage } from "@mariozechner/pi-agent-core"; import { createAgentSession, @@ -5,14 +7,10 @@ import { SessionManager, SettingsManager, } from "@mariozechner/pi-coding-agent"; -import fs from "node:fs/promises"; -import os from "node:os"; -import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js"; -import type { OpenClawConfig } from "../../config/config.js"; -import type { ExecElevatedDefaults } from "../bash-tools.js"; -import type { EmbeddedPiCompactResult } from "./types.js"; import { resolveHeartbeatPrompt } from "../../auto-reply/heartbeat.js"; +import type { ReasoningLevel, ThinkLevel } from "../../auto-reply/thinking.js"; import { resolveChannelCapabilities } from "../../config/channel-capabilities.js"; +import type { OpenClawConfig } from "../../config/config.js"; import { getMachineDisplayName } from "../../infra/machine-name.js"; import { getGlobalHookRunner } from "../../plugins/hook-runner-global.js"; import { type enqueueCommand, enqueueCommandInLane } from "../../process/command-queue.js"; @@ -26,6 +24,7 @@ import { normalizeMessageChannel } from "../../utils/message-channel.js"; import { isReasoningTagProvider } from "../../utils/provider-utils.js"; import { resolveOpenClawAgentDir } from "../agent-paths.js"; import { resolveSessionAgentIds } from "../agent-scope.js"; +import type { ExecElevatedDefaults } from "../bash-tools.js"; import { makeBootstrapWarn, resolveBootstrapContextForRun } from "../bootstrap-files.js"; import { listChannelSupportedActions, resolveChannelMessageToolHints } from "../channel-tools.js"; import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone } from "../date-time.js"; @@ -82,6 +81,7 @@ import { createSystemPromptOverride, } from "./system-prompt.js"; import { splitSdkTools } from "./tool-split.js"; +import type { EmbeddedPiCompactResult } from "./types.js"; import { describeUnknownError, mapThinkingLevel } from "./utils.js"; import { flushPendingToolResultsAfterIdle } from "./wait-for-idle-before-flush.js"; diff --git a/src/agents/pi-embedded-runner/run/attempt.ts b/src/agents/pi-embedded-runner/run/attempt.ts index e70aeb0e671..dcc4a216498 100644 --- a/src/agents/pi-embedded-runner/run/attempt.ts +++ b/src/agents/pi-embedded-runner/run/attempt.ts @@ -1,10 +1,9 @@ +import fs from "node:fs/promises"; +import os from "node:os"; import type { AgentMessage } from "@mariozechner/pi-agent-core"; import type { ImageContent } from "@mariozechner/pi-ai"; import { streamSimple } from "@mariozechner/pi-ai"; import { createAgentSession, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent"; -import fs from "node:fs/promises"; -import os from "node:os"; -import type { EmbeddedRunAttemptParams, EmbeddedRunAttemptResult } from "./types.js"; import { resolveHeartbeatPrompt } from "../../../auto-reply/heartbeat.js"; import { resolveChannelCapabilities } from "../../../config/channel-capabilities.js"; import { getMachineDisplayName } from "../../../infra/machine-name.js"; @@ -104,6 +103,7 @@ import { shouldFlagCompactionTimeout, } from "./compaction-timeout.js"; import { detectAndLoadPromptImages } from "./images.js"; +import type { EmbeddedRunAttemptParams, EmbeddedRunAttemptResult } from "./types.js"; export function injectHistoryImagesIntoMessages( messages: AgentMessage[], diff --git a/src/agents/pi-embedded-subscribe.handlers.tools.ts b/src/agents/pi-embedded-subscribe.handlers.tools.ts index 916d0e4f9f1..2a9c1ce57f9 100644 --- a/src/agents/pi-embedded-subscribe.handlers.tools.ts +++ b/src/agents/pi-embedded-subscribe.handlers.tools.ts @@ -5,8 +5,8 @@ import type { PluginHookAfterToolCallEvent } from "../plugins/types.js"; import { normalizeTextForComparison } from "./pi-embedded-helpers.js"; import { isMessagingTool, isMessagingToolSendAction } from "./pi-embedded-messaging.js"; import type { - EmbeddedPiSubscribeContext, ToolCallSummary, + ToolHandlerContext, } from "./pi-embedded-subscribe.handlers.types.js"; import { extractToolErrorMessage, @@ -64,7 +64,7 @@ function extendExecMeta(toolName: string, args: unknown, meta?: string): string } export async function handleToolExecutionStart( - ctx: EmbeddedPiSubscribeContext, + ctx: ToolHandlerContext, evt: AgentEvent & { toolName: string; toolCallId: string; args: unknown }, ) { // Flush pending block replies to preserve message boundaries before tool execution. @@ -155,7 +155,7 @@ export async function handleToolExecutionStart( } export function handleToolExecutionUpdate( - ctx: EmbeddedPiSubscribeContext, + ctx: ToolHandlerContext, evt: AgentEvent & { toolName: string; toolCallId: string; @@ -187,7 +187,7 @@ export function handleToolExecutionUpdate( } export async function handleToolExecutionEnd( - ctx: EmbeddedPiSubscribeContext, + ctx: ToolHandlerContext, evt: AgentEvent & { toolName: string; toolCallId: string; diff --git a/src/agents/pi-embedded-subscribe.handlers.types.ts b/src/agents/pi-embedded-subscribe.handlers.types.ts index 5de8cf8a926..9fc20f00799 100644 --- a/src/agents/pi-embedded-subscribe.handlers.types.ts +++ b/src/agents/pi-embedded-subscribe.handlers.types.ts @@ -147,6 +147,7 @@ export type ToolHandlerState = Pick< | "messagingToolSentTextsNormalized" | "messagingToolSentMediaUrls" | "messagingToolSentTargets" + | "successfulCronAdds" >; export type ToolHandlerContext = { diff --git a/src/agents/tools/session-status-tool.ts b/src/agents/tools/session-status-tool.ts index b67de007f7a..6edbc841a93 100644 --- a/src/agents/tools/session-status-tool.ts +++ b/src/agents/tools/session-status-tool.ts @@ -1,9 +1,8 @@ import { Type } from "@sinclair/typebox"; -import type { OpenClawConfig } from "../../config/config.js"; -import type { AnyAgentTool } from "./common.js"; import { normalizeGroupActivation } from "../../auto-reply/group-activation.js"; import { getFollowupQueueDepth, resolveQueueSettings } from "../../auto-reply/reply/queue.js"; import { buildStatusMessage } from "../../auto-reply/status.js"; +import type { OpenClawConfig } from "../../config/config.js"; import { loadConfig } from "../../config/config.js"; import { loadSessionStore, @@ -34,6 +33,7 @@ import { resolveDefaultModelForAgent, resolveModelRefFromString, } from "../model-selection.js"; +import type { AnyAgentTool } from "./common.js"; import { readStringParam } from "./common.js"; import { shouldResolveSessionIdInput, diff --git a/src/agents/tools/telegram-actions.ts b/src/agents/tools/telegram-actions.ts index 6dd624f5d74..26a871556ae 100644 --- a/src/agents/tools/telegram-actions.ts +++ b/src/agents/tools/telegram-actions.ts @@ -1,7 +1,7 @@ import type { AgentToolResult } from "@mariozechner/pi-agent-core"; import type { OpenClawConfig } from "../../config/config.js"; -import type { TelegramButtonStyle, TelegramInlineButtons } from "../../telegram/button-types.js"; import { createTelegramActionGate } from "../../telegram/accounts.js"; +import type { TelegramButtonStyle, TelegramInlineButtons } from "../../telegram/button-types.js"; import { resolveTelegramInlineButtonsScope, resolveTelegramTargetChatType, diff --git a/src/agents/tools/web-fetch.cf-markdown.test.ts b/src/agents/tools/web-fetch.cf-markdown.test.ts index 5dcfe3ccf00..2afdd24346c 100644 --- a/src/agents/tools/web-fetch.cf-markdown.test.ts +++ b/src/agents/tools/web-fetch.cf-markdown.test.ts @@ -37,7 +37,6 @@ function htmlResponse(body: string): Response { describe("web_fetch Cloudflare Markdown for Agents", () => { it("sends Accept header preferring text/markdown", async () => { const fetchSpy = vi.fn().mockResolvedValue(markdownResponse("# Test Page\n\nHello world.")); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); @@ -52,34 +51,36 @@ describe("web_fetch Cloudflare Markdown for Agents", () => { it("uses cf-markdown extractor for text/markdown responses", async () => { const md = "# CF Markdown\n\nThis is server-rendered markdown."; const fetchSpy = vi.fn().mockResolvedValue(markdownResponse(md)); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); const result = await tool?.execute?.("call", { url: "https://example.com/cf" }); - expect(result?.details).toMatchObject({ + const details = result?.details as + | { status?: number; extractor?: string; contentType?: string; text?: string } + | undefined; + expect(details).toMatchObject({ status: 200, extractor: "cf-markdown", contentType: "text/markdown", }); // The body should contain the original markdown (wrapped with security markers) - expect(result?.details?.text).toContain("CF Markdown"); - expect(result?.details?.text).toContain("server-rendered markdown"); + expect(details?.text).toContain("CF Markdown"); + expect(details?.text).toContain("server-rendered markdown"); }); it("falls back to readability for text/html responses", async () => { const html = "

HTML Page

Content here.

"; const fetchSpy = vi.fn().mockResolvedValue(htmlResponse(html)); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); const result = await tool?.execute?.("call", { url: "https://example.com/html" }); - expect(result?.details?.extractor).toBe("readability"); - expect(result?.details?.contentType).toBe("text/html"); + const details = result?.details as { extractor?: string; contentType?: string } | undefined; + expect(details?.extractor).toBe("readability"); + expect(details?.contentType).toBe("text/html"); }); it("logs x-markdown-tokens when header is present", async () => { @@ -87,7 +88,6 @@ describe("web_fetch Cloudflare Markdown for Agents", () => { const fetchSpy = vi .fn() .mockResolvedValue(markdownResponse("# Tokens Test", { "x-markdown-tokens": "1500" })); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); @@ -108,7 +108,6 @@ describe("web_fetch Cloudflare Markdown for Agents", () => { it("converts markdown to text when extractMode is text", async () => { const md = "# Heading\n\n**Bold text** and [a link](https://example.com)."; const fetchSpy = vi.fn().mockResolvedValue(markdownResponse(md)); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); @@ -117,20 +116,22 @@ describe("web_fetch Cloudflare Markdown for Agents", () => { url: "https://example.com/text-mode", extractMode: "text", }); - expect(result?.details).toMatchObject({ + const details = result?.details as + | { extractor?: string; extractMode?: string; text?: string } + | undefined; + expect(details).toMatchObject({ extractor: "cf-markdown", extractMode: "text", }); // Text mode strips header markers (#) and link syntax - expect(result?.details?.text).not.toContain("# Heading"); - expect(result?.details?.text).toContain("Heading"); - expect(result?.details?.text).not.toContain("[a link](https://example.com)"); + expect(details?.text).not.toContain("# Heading"); + expect(details?.text).toContain("Heading"); + expect(details?.text).not.toContain("[a link](https://example.com)"); }); it("does not log x-markdown-tokens when header is absent", async () => { const logSpy = vi.spyOn(logger, "logDebug").mockImplementation(() => {}); const fetchSpy = vi.fn().mockResolvedValue(markdownResponse("# No tokens")); - // @ts-expect-error mock fetch global.fetch = fetchSpy; const tool = createWebFetchTool(baseToolConfig); diff --git a/src/agents/tools/web-fetch.ts b/src/agents/tools/web-fetch.ts index fc0aaead98e..2bb3837c669 100644 --- a/src/agents/tools/web-fetch.ts +++ b/src/agents/tools/web-fetch.ts @@ -1,12 +1,12 @@ import { Type } from "@sinclair/typebox"; import type { OpenClawConfig } from "../../config/config.js"; -import type { AnyAgentTool } from "./common.js"; import { fetchWithSsrFGuard } from "../../infra/net/fetch-guard.js"; import { SsrFBlockedError } from "../../infra/net/ssrf.js"; import { logDebug } from "../../logger.js"; import { wrapExternalContent, wrapWebContent } from "../../security/external-content.js"; import { normalizeSecretInput } from "../../utils/normalize-secret-input.js"; import { stringEnum } from "../schema/typebox.js"; +import type { AnyAgentTool } from "./common.js"; import { jsonResult, readNumberParam, readStringParam } from "./common.js"; import { extractReadableContent, diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index be174b951d3..52cf9f2575a 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -1,9 +1,9 @@ import { Type } from "@sinclair/typebox"; -import type { OpenClawConfig } from "../../config/config.js"; -import type { AnyAgentTool } from "./common.js"; import { formatCliCommand } from "../../cli/command-format.js"; +import type { OpenClawConfig } from "../../config/config.js"; import { wrapWebContent } from "../../security/external-content.js"; import { normalizeSecretInput } from "../../utils/normalize-secret-input.js"; +import type { AnyAgentTool } from "./common.js"; import { jsonResult, readNumberParam, readStringParam } from "./common.js"; import { CacheEntry,