import type { OpenClawConfig } from "../config/types.js"; import { defaultSlotIdForKey } from "../plugins/slots.js"; import { resolveGlobalSingleton } from "../shared/global-singleton.js"; import { sanitizeForLog } from "../terminal/ansi.js"; import type { ContextEngine } from "./types.js";
type SessionKeyCompatMethodName = (typeof SESSION_KEY_COMPAT_METHODS)[number];
type SessionKeyCompatParams = {
sessionKey?: string;
prompt?: string;
};
type LegacyCompatKey = (typeof LEGACY_COMPAT_PARAMS)[number];
type LegacyCompatParamMap = Partial<Record<LegacyCompatKey, unknown>>;
function isSessionKeyCompatMethodName(value: PropertyKey): value is SessionKeyCompatMethodName { return ( typeof value === "string" && (SESSION_KEY_COMPAT_METHODS as readonly string[]).includes(value)
);
}
function* iterateErrorChain(error: unknown) {
let current = error; const seen = new Set<unknown>(); while (current !== undefined && current !== null && !seen.has(current)) {
yield current;
seen.add(current); if (typeof current !== "object") { break;
}
current = (current as { cause?: unknown }).cause;
}
}
const LEGACY_UNKNOWN_FIELD_PATTERNS: Record<LegacyCompatKey, readonly RegExp[]> = {
sessionKey: [
/\bunrecognized key(?:\(s\)|s)? in object:.*['"`]sessionKey['"`]/i,
/\badditional propert(?:y|ies)\b.*['"`]sessionKey['"`]/i,
/\bmust not have additional propert(?:y|ies)\b.*['"`]sessionKey['"`]/i,
/\b(?:unexpected|extraneous)\s+(?:property|properties|field|fields|key|keys)\b.*['"`]sessionKey['"`]/i,
/\b(?:unknown|invalid)\s+(?:property|properties|field|fields|key|keys)\b.*['"`]sessionKey['"`]/i,
/['"`]sessionKey['"`].*\b(?:was|is)\s+not allowed\b/i,
/"code"\s*:\s*"unrecognized_keys"[^]*"sessionKey"/i,
],
prompt: [
/\bunrecognized key(?:\(s\)|s)? in object:.*['"`]prompt['"`]/i,
/\badditional propert(?:y|ies)\b.*['"`]prompt['"`]/i,
/\bmust not have additional propert(?:y|ies)\b.*['"`]prompt['"`]/i,
/\b(?:unexpected|extraneous)\s+(?:property|properties|field|fields|key|keys)\b.*['"`]prompt['"`]/i,
/\b(?:unknown|invalid)\s+(?:property|properties|field|fields|key|keys)\b.*['"`]prompt['"`]/i,
/['"`]prompt['"`].*\b(?:was|is)\s+not allowed\b/i,
/"code"\s*:\s*"unrecognized_keys"[^]*"prompt"/i,
],
} as const;
export function clearContextEnginesForOwner(owner: string): void { const normalizedOwner = requireContextEngineOwner(owner); const registry = getContextEngineRegistryState().engines; for (const [id, entry] of registry.entries()) { if (entry.owner === normalizedOwner) {
registry.delete(id);
}
}
}
function describeResolvedContextEngineContractError(
engineId: string,
engine: unknown,
): string | null { if (!engine || typeof engine !== "object") { return `Context engine "${engineId}" factory returned ${JSON.stringify(engine)} instead of a ContextEngine object.`;
}
const candidate = engine as Record<string, unknown>; const issues: string[] = []; const info = candidate.info; if (!info || typeof info !== "object") {
issues.push("missing info");
} else { const infoRecord = info as Record<string, unknown>; // Engines own their internal info.id; it is metadata, not a handle into the // registry. The registered id (plugin slot id) and the engine's own id are // allowed to differ, so we only require that info.id is a non-empty string // for display/logging purposes and do not enforce equality with engineId. const infoId = typeof infoRecord.id === "string" ? infoRecord.id.trim() : ""; if (!infoId) {
issues.push("missing info.id");
} if (typeof infoRecord.name !== "string" || !infoRecord.name.trim()) {
issues.push("missing info.name");
}
}
if (typeof candidate.ingest !== "function") {
issues.push("missing ingest()");
} if (typeof candidate.assemble !== "function") {
issues.push("missing assemble()");
} if (typeof candidate.compact !== "function") {
issues.push("missing compact()");
}
if (issues.length === 0) { returnnull;
}
return `Context engine "${engineId}" factory returned an invalid ContextEngine: ${issues.join(", ")}.`;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.