fix: resolve plugin tool meta typing

This commit is contained in:
Peter Steinberger
2026-01-18 04:24:16 +00:00
parent fabc2882aa
commit 82e49af5a7
10 changed files with 78 additions and 67 deletions

View File

@@ -3,7 +3,8 @@ import type { SessionManager } from "@mariozechner/pi-coding-agent";
import { beforeEach, describe, expect, it, vi } from "vitest";
import * as helpers from "./pi-embedded-helpers.js";
type SanitizeSessionHistory = typeof import("./pi-embedded-runner/google.js").sanitizeSessionHistory;
type SanitizeSessionHistory =
typeof import("./pi-embedded-runner/google.js").sanitizeSessionHistory;
let sanitizeSessionHistory: SanitizeSessionHistory;
// Mock dependencies

View File

@@ -262,20 +262,11 @@ export function createClawdbotCodingTools(options?: {
toolMeta: (tool) => getPluginToolMeta(tool),
});
const profilePolicyExpanded = expandPolicyWithPluginGroups(profilePolicy, pluginGroups);
const providerProfileExpanded = expandPolicyWithPluginGroups(
providerProfilePolicy,
pluginGroups,
);
const providerProfileExpanded = expandPolicyWithPluginGroups(providerProfilePolicy, pluginGroups);
const globalPolicyExpanded = expandPolicyWithPluginGroups(globalPolicy, pluginGroups);
const globalProviderExpanded = expandPolicyWithPluginGroups(
globalProviderPolicy,
pluginGroups,
);
const globalProviderExpanded = expandPolicyWithPluginGroups(globalProviderPolicy, pluginGroups);
const agentPolicyExpanded = expandPolicyWithPluginGroups(agentPolicy, pluginGroups);
const agentProviderExpanded = expandPolicyWithPluginGroups(
agentProviderPolicy,
pluginGroups,
);
const agentProviderExpanded = expandPolicyWithPluginGroups(agentProviderPolicy, pluginGroups);
const sandboxPolicyExpanded = expandPolicyWithPluginGroups(sandbox?.tools, pluginGroups);
const subagentPolicyExpanded = expandPolicyWithPluginGroups(subagentPolicy, pluginGroups);

View File

@@ -109,9 +109,7 @@ export function expandToolGroups(list?: string[]) {
return Array.from(new Set(expanded));
}
export function collectExplicitAllowlist(
policies: Array<ToolPolicyLike | undefined>,
): string[] {
export function collectExplicitAllowlist(policies: Array<ToolPolicyLike | undefined>): string[] {
const entries: string[] = [];
for (const policy of policies) {
if (!policy?.allow) continue;
@@ -124,9 +122,9 @@ export function collectExplicitAllowlist(
return entries;
}
export function buildPluginToolGroups(params: {
tools: Array<{ name: string }>;
toolMeta: (tool: { name: string }) => { pluginId: string } | undefined;
export function buildPluginToolGroups<T extends { name: string }>(params: {
tools: T[];
toolMeta: (tool: T) => { pluginId: string } | undefined;
}): PluginToolGroups {
const all: string[] = [];
const byPlugin = new Map<string, string[]>();

View File

@@ -73,13 +73,11 @@ export function deriveGroupSessionPatch(params: {
const normalizedChannel = normalizeChannelId(channel);
const isChannelProvider = Boolean(
normalizedChannel &&
getChannelDock(normalizedChannel)?.capabilities.chatTypes.includes("channel"),
getChannelDock(normalizedChannel)?.capabilities.chatTypes.includes("channel"),
);
const nextGroupChannel =
explicitChannel ??
((resolution.chatType === "channel" || isChannelProvider) &&
subject &&
subject.startsWith("#")
((resolution.chatType === "channel" || isChannelProvider) && subject && subject.startsWith("#")
? subject
: undefined);
const nextSubject = nextGroupChannel ? undefined : subject;

View File

@@ -406,7 +406,10 @@ export async function updateLastRoute(params: {
lastTo: normalized.lastTo,
lastAccountId: normalized.lastAccountId,
};
const next = mergeSessionEntry(existing, metaPatch ? { ...basePatch, ...metaPatch } : basePatch);
const next = mergeSessionEntry(
existing,
metaPatch ? { ...basePatch, ...metaPatch } : basePatch,
);
store[sessionKey] = next;
await saveSessionStoreUnlocked(storePath, store);
return next;

View File

@@ -107,9 +107,16 @@ export {
} from "../channels/plugins/channel-config.js";
export type { AllowlistMatch } from "../channels/plugins/allowlist-match.js";
export { formatAllowlistMatchMeta } from "../channels/plugins/allowlist-match.js";
export { readChannelAllowFromStore, upsertChannelPairingRequest } from "../pairing/pairing-store.js";
export {
readChannelAllowFromStore,
upsertChannelPairingRequest,
} from "../pairing/pairing-store.js";
export { resolveAgentRoute } from "../routing/resolve-route.js";
export { recordSessionMetaFromInbound, resolveStorePath, updateLastRoute } from "../config/sessions.js";
export {
recordSessionMetaFromInbound,
resolveStorePath,
updateLastRoute,
} from "../config/sessions.js";
export { resolveStateDir } from "../config/paths.js";
export { loadConfig } from "../config/config.js";
export { danger } from "../globals.js";
@@ -130,7 +137,10 @@ export {
deleteAccountFromConfigSection,
setAccountEnabledInConfigSection,
} from "../channels/plugins/config-helpers.js";
export { applyAccountNameToChannelSection, migrateBaseNameToDefaultAccount } from "../channels/plugins/setup-helpers.js";
export {
applyAccountNameToChannelSection,
migrateBaseNameToDefaultAccount,
} from "../channels/plugins/setup-helpers.js";
export { formatPairingApproveHint } from "../channels/plugins/helpers.js";
export { PAIRING_APPROVED_MESSAGE } from "../channels/plugins/pairing-message.js";

View File

@@ -2,20 +2,29 @@ import { createRequire } from "node:module";
import { chunkMarkdownText, resolveTextChunkLimit } from "../../auto-reply/chunk.js";
import { hasControlCommand } from "../../auto-reply/command-detection.js";
import { createInboundDebouncer, resolveInboundDebounceMs } from "../../auto-reply/inbound-debounce.js";
import {
createInboundDebouncer,
resolveInboundDebounceMs,
} from "../../auto-reply/inbound-debounce.js";
import { buildMentionRegexes, matchesMentionPatterns } from "../../auto-reply/reply/mentions.js";
import { dispatchReplyWithBufferedBlockDispatcher } from "../../auto-reply/reply/provider-dispatcher.js";
import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
import { resolveEffectiveMessagesConfig, resolveHumanDelayConfig } from "../../agents/identity.js";
import { resolveCommandAuthorizedFromAuthorizers } from "../../channels/command-gating.js";
import { resolveChannelGroupPolicy, resolveChannelGroupRequireMention } from "../../config/group-policy.js";
import {
resolveChannelGroupPolicy,
resolveChannelGroupRequireMention,
} from "../../config/group-policy.js";
import { resolveStateDir } from "../../config/paths.js";
import { shouldLogVerbose } from "../../globals.js";
import { getChildLogger } from "../../logging.js";
import { fetchRemoteMedia } from "../../media/fetch.js";
import { saveMediaBuffer } from "../../media/store.js";
import { buildPairingReply } from "../../pairing/pairing-messages.js";
import { readChannelAllowFromStore, upsertChannelPairingRequest } from "../../pairing/pairing-store.js";
import {
readChannelAllowFromStore,
upsertChannelPairingRequest,
} from "../../pairing/pairing-store.js";
import { resolveAgentRoute } from "../../routing/resolve-route.js";
import type { PluginRuntime } from "./types.js";

View File

@@ -51,7 +51,10 @@ export type PluginRuntime = {
};
logging: {
shouldLogVerbose: typeof import("../../globals.js").shouldLogVerbose;
getChildLogger: (bindings?: Record<string, unknown>, opts?: { level?: LogLevel }) => RuntimeLogger;
getChildLogger: (
bindings?: Record<string, unknown>,
opts?: { level?: LogLevel },
) => RuntimeLogger;
};
state: {
resolveStateDir: typeof import("../../config/paths.js").resolveStateDir;

View File

@@ -52,9 +52,7 @@ export function resolvePluginTools(params: {
const tools: AnyAgentTool[] = [];
const existing = params.existingToolNames ?? new Set<string>();
const existingNormalized = new Set(
Array.from(existing, (tool) => normalizeToolName(tool)),
);
const existingNormalized = new Set(Array.from(existing, (tool) => normalizeToolName(tool)));
const allowlist = normalizeAllowlist(params.toolAllowlist);
const blockedPlugins = new Set<string>();

View File

@@ -240,39 +240,39 @@ export async function processMessage(params: {
};
const ctxPayload = finalizeInboundContext({
Body: combinedBody,
RawBody: params.msg.body,
CommandBody: params.msg.body,
From: params.msg.from,
To: params.msg.to,
SessionKey: params.route.sessionKey,
AccountId: params.route.accountId,
MessageSid: params.msg.id,
ReplyToId: params.msg.replyToId,
ReplyToBody: params.msg.replyToBody,
ReplyToSender: params.msg.replyToSender,
MediaPath: params.msg.mediaPath,
MediaUrl: params.msg.mediaUrl,
MediaType: params.msg.mediaType,
ChatType: params.msg.chatType,
ConversationLabel: params.msg.chatType === "group" ? conversationId : params.msg.from,
GroupSubject: params.msg.groupSubject,
GroupMembers: formatGroupMembers({
participants: params.msg.groupParticipants,
roster: params.groupMemberNames.get(params.groupHistoryKey),
fallbackE164: params.msg.senderE164,
}),
SenderName: params.msg.senderName,
SenderId: params.msg.senderJid?.trim() || params.msg.senderE164,
SenderE164: params.msg.senderE164,
CommandAuthorized: commandAuthorized,
WasMentioned: params.msg.wasMentioned,
...(params.msg.location ? toLocationContext(params.msg.location) : {}),
Provider: "whatsapp",
Surface: "whatsapp",
OriginatingChannel: "whatsapp",
OriginatingTo: params.msg.from,
});
Body: combinedBody,
RawBody: params.msg.body,
CommandBody: params.msg.body,
From: params.msg.from,
To: params.msg.to,
SessionKey: params.route.sessionKey,
AccountId: params.route.accountId,
MessageSid: params.msg.id,
ReplyToId: params.msg.replyToId,
ReplyToBody: params.msg.replyToBody,
ReplyToSender: params.msg.replyToSender,
MediaPath: params.msg.mediaPath,
MediaUrl: params.msg.mediaUrl,
MediaType: params.msg.mediaType,
ChatType: params.msg.chatType,
ConversationLabel: params.msg.chatType === "group" ? conversationId : params.msg.from,
GroupSubject: params.msg.groupSubject,
GroupMembers: formatGroupMembers({
participants: params.msg.groupParticipants,
roster: params.groupMemberNames.get(params.groupHistoryKey),
fallbackE164: params.msg.senderE164,
}),
SenderName: params.msg.senderName,
SenderId: params.msg.senderJid?.trim() || params.msg.senderE164,
SenderE164: params.msg.senderE164,
CommandAuthorized: commandAuthorized,
WasMentioned: params.msg.wasMentioned,
...(params.msg.location ? toLocationContext(params.msg.location) : {}),
Provider: "whatsapp",
Surface: "whatsapp",
OriginatingChannel: "whatsapp",
OriginatingTo: params.msg.from,
});
if (dmRouteTarget) {
updateLastRouteInBackground({