feat(plugins): add memory slot plugin
This commit is contained in:
@@ -31,6 +31,9 @@ type NormalizedPluginsConfig = {
|
||||
allow: string[];
|
||||
deny: string[];
|
||||
loadPaths: string[];
|
||||
slots: {
|
||||
memory?: string | null;
|
||||
};
|
||||
entries: Record<string, { enabled?: boolean; config?: Record<string, unknown> }>;
|
||||
};
|
||||
|
||||
@@ -43,6 +46,14 @@ const normalizeList = (value: unknown): string[] => {
|
||||
return value.map((entry) => (typeof entry === "string" ? entry.trim() : "")).filter(Boolean);
|
||||
};
|
||||
|
||||
const normalizeSlotValue = (value: unknown): string | null | undefined => {
|
||||
if (typeof value !== "string") return undefined;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return undefined;
|
||||
if (trimmed.toLowerCase() === "none") return null;
|
||||
return trimmed;
|
||||
};
|
||||
|
||||
const normalizePluginEntries = (entries: unknown): NormalizedPluginsConfig["entries"] => {
|
||||
if (!entries || typeof entries !== "object" || Array.isArray(entries)) {
|
||||
return {};
|
||||
@@ -67,11 +78,15 @@ const normalizePluginEntries = (entries: unknown): NormalizedPluginsConfig["entr
|
||||
};
|
||||
|
||||
const normalizePluginsConfig = (config?: ClawdbotConfig["plugins"]): NormalizedPluginsConfig => {
|
||||
const memorySlot = normalizeSlotValue(config?.slots?.memory);
|
||||
return {
|
||||
enabled: config?.enabled !== false,
|
||||
allow: normalizeList(config?.allow),
|
||||
deny: normalizeList(config?.deny),
|
||||
loadPaths: normalizeList(config?.load?.paths),
|
||||
slots: {
|
||||
memory: memorySlot ?? "memory-core",
|
||||
},
|
||||
entries: normalizePluginEntries(config?.entries),
|
||||
};
|
||||
};
|
||||
@@ -84,6 +99,34 @@ function buildCacheKey(params: {
|
||||
return `${workspaceKey}::${JSON.stringify(params.plugins)}`;
|
||||
}
|
||||
|
||||
function resolveMemorySlotDecision(params: {
|
||||
id: string;
|
||||
kind?: string;
|
||||
slot: string | null | undefined;
|
||||
selectedId: string | null;
|
||||
}): { enabled: boolean; reason?: string; selected?: boolean } {
|
||||
if (params.kind !== "memory") return { enabled: true };
|
||||
if (params.slot === null) {
|
||||
return { enabled: false, reason: "memory slot disabled" };
|
||||
}
|
||||
if (typeof params.slot === "string") {
|
||||
if (params.slot === params.id) {
|
||||
return { enabled: true, selected: true };
|
||||
}
|
||||
return {
|
||||
enabled: false,
|
||||
reason: `memory slot set to "${params.slot}"`,
|
||||
};
|
||||
}
|
||||
if (params.selectedId && params.selectedId !== params.id) {
|
||||
return {
|
||||
enabled: false,
|
||||
reason: `memory slot already filled by "${params.selectedId}"`,
|
||||
};
|
||||
}
|
||||
return { enabled: true, selected: true };
|
||||
}
|
||||
|
||||
function resolveEnableState(
|
||||
id: string,
|
||||
origin: PluginRecord["origin"],
|
||||
@@ -98,6 +141,9 @@ function resolveEnableState(
|
||||
if (config.allow.length > 0 && !config.allow.includes(id)) {
|
||||
return { enabled: false, reason: "not in allowlist" };
|
||||
}
|
||||
if (config.slots.memory === id) {
|
||||
return { enabled: true };
|
||||
}
|
||||
const entry = config.entries[id];
|
||||
if (entry?.enabled === true) {
|
||||
return { enabled: true };
|
||||
@@ -245,6 +291,9 @@ export function loadClawdbotPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
});
|
||||
|
||||
const seenIds = new Map<string, PluginRecord["origin"]>();
|
||||
const memorySlot = normalized.slots.memory;
|
||||
let selectedMemoryPluginId: string | null = null;
|
||||
let memorySlotMatched = false;
|
||||
|
||||
for (const candidate of discovery.candidates) {
|
||||
const existingOrigin = seenIds.get(candidate.idHint);
|
||||
@@ -321,6 +370,7 @@ export function loadClawdbotPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
record.name = definition?.name ?? record.name;
|
||||
record.description = definition?.description ?? record.description;
|
||||
record.version = definition?.version ?? record.version;
|
||||
record.kind = definition?.kind;
|
||||
record.configSchema = Boolean(definition?.configSchema);
|
||||
record.configUiHints =
|
||||
definition?.configSchema &&
|
||||
@@ -345,6 +395,30 @@ export function loadClawdbotPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
>)
|
||||
: undefined;
|
||||
|
||||
if (record.kind === "memory" && memorySlot === record.id) {
|
||||
memorySlotMatched = true;
|
||||
}
|
||||
|
||||
const memoryDecision = resolveMemorySlotDecision({
|
||||
id: record.id,
|
||||
kind: record.kind,
|
||||
slot: memorySlot,
|
||||
selectedId: selectedMemoryPluginId,
|
||||
});
|
||||
|
||||
if (!memoryDecision.enabled) {
|
||||
record.enabled = false;
|
||||
record.status = "disabled";
|
||||
record.error = memoryDecision.reason;
|
||||
registry.plugins.push(record);
|
||||
seenIds.set(candidate.idHint, candidate.origin);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (memoryDecision.selected && record.kind === "memory") {
|
||||
selectedMemoryPluginId = record.id;
|
||||
}
|
||||
|
||||
const validatedConfig = validatePluginConfig({
|
||||
schema: definition?.configSchema,
|
||||
value: entry?.config,
|
||||
@@ -409,6 +483,13 @@ export function loadClawdbotPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof memorySlot === "string" && !memorySlotMatched) {
|
||||
registry.diagnostics.push({
|
||||
level: "warn",
|
||||
message: `memory slot plugin not found or not marked as memory: ${memorySlot}`,
|
||||
});
|
||||
}
|
||||
|
||||
if (cacheEnabled) {
|
||||
registryCache.set(cacheKey, registry);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user