mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 03:47:26 +00:00
172 lines
4.7 KiB
TypeScript
172 lines
4.7 KiB
TypeScript
export type {
|
|
AgentToAgentPolicy,
|
|
SessionAccessAction,
|
|
SessionAccessResult,
|
|
SessionToolsVisibility,
|
|
} from "./sessions-access.js";
|
|
export {
|
|
createAgentToAgentPolicy,
|
|
createSessionVisibilityGuard,
|
|
resolveEffectiveSessionToolsVisibility,
|
|
resolveSandboxSessionToolsVisibility,
|
|
resolveSandboxedSessionToolContext,
|
|
resolveSessionToolsVisibility,
|
|
} from "./sessions-access.js";
|
|
export type { SessionReferenceResolution } from "./sessions-resolution.js";
|
|
export {
|
|
isRequesterSpawnedSessionVisible,
|
|
isResolvedSessionVisibleToRequester,
|
|
listSpawnedSessionKeys,
|
|
looksLikeSessionId,
|
|
looksLikeSessionKey,
|
|
resolveDisplaySessionKey,
|
|
resolveInternalSessionKey,
|
|
resolveMainSessionAlias,
|
|
resolveSessionReference,
|
|
resolveVisibleSessionReference,
|
|
shouldResolveSessionIdInput,
|
|
shouldVerifyRequesterSpawnedSessionVisibility,
|
|
} from "./sessions-resolution.js";
|
|
import { extractTextFromChatContent } from "../../shared/chat-content.js";
|
|
import { sanitizeUserFacingText } from "../pi-embedded-helpers.js";
|
|
import {
|
|
stripDowngradedToolCallText,
|
|
stripMinimaxToolCallXml,
|
|
stripThinkingTagsFromText,
|
|
} from "../pi-embedded-utils.js";
|
|
|
|
export type SessionKind = "main" | "group" | "cron" | "hook" | "node" | "other";
|
|
|
|
export type SessionListDeliveryContext = {
|
|
channel?: string;
|
|
to?: string;
|
|
accountId?: string;
|
|
};
|
|
|
|
export type SessionListRow = {
|
|
key: string;
|
|
kind: SessionKind;
|
|
channel: string;
|
|
label?: string;
|
|
displayName?: string;
|
|
deliveryContext?: SessionListDeliveryContext;
|
|
updatedAt?: number | null;
|
|
sessionId?: string;
|
|
model?: string;
|
|
contextTokens?: number | null;
|
|
totalTokens?: number | null;
|
|
thinkingLevel?: string;
|
|
verboseLevel?: string;
|
|
systemSent?: boolean;
|
|
abortedLastRun?: boolean;
|
|
sendPolicy?: string;
|
|
lastChannel?: string;
|
|
lastTo?: string;
|
|
lastAccountId?: string;
|
|
transcriptPath?: string;
|
|
messages?: unknown[];
|
|
};
|
|
|
|
function normalizeKey(value?: string) {
|
|
const trimmed = value?.trim();
|
|
return trimmed ? trimmed : undefined;
|
|
}
|
|
|
|
export function classifySessionKind(params: {
|
|
key: string;
|
|
gatewayKind?: string | null;
|
|
alias: string;
|
|
mainKey: string;
|
|
}): SessionKind {
|
|
const key = params.key;
|
|
if (key === params.alias || key === params.mainKey) {
|
|
return "main";
|
|
}
|
|
if (key.startsWith("cron:")) {
|
|
return "cron";
|
|
}
|
|
if (key.startsWith("hook:")) {
|
|
return "hook";
|
|
}
|
|
if (key.startsWith("node-") || key.startsWith("node:")) {
|
|
return "node";
|
|
}
|
|
if (params.gatewayKind === "group") {
|
|
return "group";
|
|
}
|
|
if (key.includes(":group:") || key.includes(":channel:")) {
|
|
return "group";
|
|
}
|
|
return "other";
|
|
}
|
|
|
|
export function deriveChannel(params: {
|
|
key: string;
|
|
kind: SessionKind;
|
|
channel?: string | null;
|
|
lastChannel?: string | null;
|
|
}): string {
|
|
if (params.kind === "cron" || params.kind === "hook" || params.kind === "node") {
|
|
return "internal";
|
|
}
|
|
const channel = normalizeKey(params.channel ?? undefined);
|
|
if (channel) {
|
|
return channel;
|
|
}
|
|
const lastChannel = normalizeKey(params.lastChannel ?? undefined);
|
|
if (lastChannel) {
|
|
return lastChannel;
|
|
}
|
|
const parts = params.key.split(":").filter(Boolean);
|
|
if (parts.length >= 3 && (parts[1] === "group" || parts[1] === "channel")) {
|
|
return parts[0];
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
export function stripToolMessages(messages: unknown[]): unknown[] {
|
|
return messages.filter((msg) => {
|
|
if (!msg || typeof msg !== "object") {
|
|
return true;
|
|
}
|
|
const role = (msg as { role?: unknown }).role;
|
|
return role !== "toolResult" && role !== "tool";
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Sanitize text content to strip tool call markers and thinking tags.
|
|
* This ensures user-facing text doesn't leak internal tool representations.
|
|
*/
|
|
export function sanitizeTextContent(text: string): string {
|
|
if (!text) {
|
|
return text;
|
|
}
|
|
return stripThinkingTagsFromText(stripDowngradedToolCallText(stripMinimaxToolCallXml(text)));
|
|
}
|
|
|
|
export function extractAssistantText(message: unknown): string | undefined {
|
|
if (!message || typeof message !== "object") {
|
|
return undefined;
|
|
}
|
|
if ((message as { role?: unknown }).role !== "assistant") {
|
|
return undefined;
|
|
}
|
|
const content = (message as { content?: unknown }).content;
|
|
if (!Array.isArray(content)) {
|
|
return undefined;
|
|
}
|
|
const joined =
|
|
extractTextFromChatContent(content, {
|
|
sanitizeText: sanitizeTextContent,
|
|
joinWith: "",
|
|
normalizeText: (text) => text.trim(),
|
|
}) ?? "";
|
|
const stopReason = (message as { stopReason?: unknown }).stopReason;
|
|
const errorMessage = (message as { errorMessage?: unknown }).errorMessage;
|
|
const errorContext =
|
|
stopReason === "error" || (typeof errorMessage === "string" && Boolean(errorMessage.trim()));
|
|
|
|
return joined ? sanitizeUserFacingText(joined, { errorContext }) : undefined;
|
|
}
|