feat: plugin system + voice-call
This commit is contained in:
@@ -23,6 +23,19 @@ export type ConfigSchemaResponse = {
|
||||
generatedAt: string;
|
||||
};
|
||||
|
||||
export type PluginUiMetadata = {
|
||||
id: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
configUiHints?: Record<
|
||||
string,
|
||||
Pick<
|
||||
ConfigUiHint,
|
||||
"label" | "help" | "advanced" | "sensitive" | "placeholder"
|
||||
>
|
||||
>;
|
||||
};
|
||||
|
||||
const GROUP_LABELS: Record<string, string> = {
|
||||
wizard: "Wizard",
|
||||
logging: "Logging",
|
||||
@@ -327,10 +340,52 @@ function applySensitiveHints(hints: ConfigUiHints): ConfigUiHints {
|
||||
return next;
|
||||
}
|
||||
|
||||
let cached: ConfigSchemaResponse | null = null;
|
||||
function applyPluginHints(
|
||||
hints: ConfigUiHints,
|
||||
plugins: PluginUiMetadata[],
|
||||
): ConfigUiHints {
|
||||
const next: ConfigUiHints = { ...hints };
|
||||
for (const plugin of plugins) {
|
||||
const id = plugin.id.trim();
|
||||
if (!id) continue;
|
||||
const name = (plugin.name ?? id).trim() || id;
|
||||
const basePath = `plugins.entries.${id}`;
|
||||
|
||||
export function buildConfigSchema(): ConfigSchemaResponse {
|
||||
if (cached) return cached;
|
||||
next[basePath] = {
|
||||
...next[basePath],
|
||||
label: name,
|
||||
help: plugin.description
|
||||
? `${plugin.description} (plugin: ${id})`
|
||||
: `Plugin entry for ${id}.`,
|
||||
};
|
||||
next[`${basePath}.enabled`] = {
|
||||
...next[`${basePath}.enabled`],
|
||||
label: `Enable ${name}`,
|
||||
};
|
||||
next[`${basePath}.config`] = {
|
||||
...next[`${basePath}.config`],
|
||||
label: `${name} Config`,
|
||||
help: `Plugin-defined config payload for ${id}.`,
|
||||
};
|
||||
|
||||
const uiHints = plugin.configUiHints ?? {};
|
||||
for (const [relPathRaw, hint] of Object.entries(uiHints)) {
|
||||
const relPath = relPathRaw.trim().replace(/^\./, "");
|
||||
if (!relPath) continue;
|
||||
const key = `${basePath}.config.${relPath}`;
|
||||
next[key] = {
|
||||
...next[key],
|
||||
...hint,
|
||||
};
|
||||
}
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
let cachedBase: ConfigSchemaResponse | null = null;
|
||||
|
||||
function buildBaseConfigSchema(): ConfigSchemaResponse {
|
||||
if (cachedBase) return cachedBase;
|
||||
const schema = ClawdbotSchema.toJSONSchema({
|
||||
target: "draft-07",
|
||||
unrepresentable: "any",
|
||||
@@ -343,6 +398,19 @@ export function buildConfigSchema(): ConfigSchemaResponse {
|
||||
version: VERSION,
|
||||
generatedAt: new Date().toISOString(),
|
||||
};
|
||||
cached = next;
|
||||
cachedBase = next;
|
||||
return next;
|
||||
}
|
||||
|
||||
export function buildConfigSchema(params?: {
|
||||
plugins?: PluginUiMetadata[];
|
||||
}): ConfigSchemaResponse {
|
||||
const base = buildBaseConfigSchema();
|
||||
const plugins = params?.plugins ?? [];
|
||||
if (plugins.length === 0) return base;
|
||||
const merged = applySensitiveHints(applyPluginHints(base.uiHints, plugins));
|
||||
return {
|
||||
...base,
|
||||
uiHints: merged,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user