feat(FN-1779): merge fusion/fn-1779
This commit is contained in:
@@ -6,6 +6,18 @@
|
||||
"author": "Fusion Team",
|
||||
"homepage": "https://github.com/gsxdsm/fusion",
|
||||
"settingsSchema": {
|
||||
"webhookSecret": {
|
||||
"type": "password",
|
||||
"label": "Webhook Secret",
|
||||
"description": "Secret for webhook signatures"
|
||||
},
|
||||
"customMessage": {
|
||||
"type": "string",
|
||||
"label": "Custom Message",
|
||||
"description": "Multi-line message shown on load",
|
||||
"multiline": true,
|
||||
"defaultValue": "Hello from Settings Demo!"
|
||||
},
|
||||
"greetingMessage": {
|
||||
"type": "string",
|
||||
"label": "Greeting Message",
|
||||
@@ -30,6 +42,13 @@
|
||||
"description": "Minimum log level to output",
|
||||
"enumValues": ["debug", "info", "warn", "error"],
|
||||
"defaultValue": "info"
|
||||
},
|
||||
"priorityTags": {
|
||||
"type": "array",
|
||||
"label": "Priority Tags",
|
||||
"description": "Tags to prioritize in suggestions",
|
||||
"itemType": "string",
|
||||
"defaultValue": ["bug", "feature"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@ function createMockContext(overrides: Partial<MockContext> = {}): MockContext {
|
||||
return {
|
||||
pluginId: "fusion-plugin-settings-demo",
|
||||
settings: {
|
||||
webhookSecret: undefined,
|
||||
customMessage: "Hello from Settings Demo!",
|
||||
greetingMessage: "Hello from Settings Demo!",
|
||||
maxTags: 3,
|
||||
enableLogging: true,
|
||||
logLevel: "info",
|
||||
priorityTags: ["bug", "feature"],
|
||||
},
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
@@ -86,10 +89,21 @@ describe("settings demo plugin", () => {
|
||||
expect(plugin.manifest.version).toBe("0.1.0");
|
||||
});
|
||||
|
||||
it("should have settings schema defined with all four types", () => {
|
||||
it("should have settings schema defined with all field types", () => {
|
||||
expect(plugin.manifest.settingsSchema).toBeDefined();
|
||||
const schema = plugin.manifest.settingsSchema!;
|
||||
|
||||
// Password type
|
||||
expect(schema.webhookSecret).toBeDefined();
|
||||
expect(schema.webhookSecret.type).toBe("password");
|
||||
expect(schema.webhookSecret.label).toBe("Webhook Secret");
|
||||
|
||||
// String type with multiline
|
||||
expect(schema.customMessage).toBeDefined();
|
||||
expect(schema.customMessage.type).toBe("string");
|
||||
expect(schema.customMessage.label).toBe("Custom Message");
|
||||
expect(schema.customMessage.multiline).toBe(true);
|
||||
|
||||
// String type
|
||||
expect(schema.greetingMessage).toBeDefined();
|
||||
expect(schema.greetingMessage.type).toBe("string");
|
||||
@@ -109,15 +123,23 @@ describe("settings demo plugin", () => {
|
||||
expect(schema.logLevel).toBeDefined();
|
||||
expect(schema.logLevel.type).toBe("enum");
|
||||
expect(schema.logLevel.enumValues).toEqual(["debug", "info", "warn", "error"]);
|
||||
|
||||
// Array type
|
||||
expect(schema.priorityTags).toBeDefined();
|
||||
expect(schema.priorityTags.type).toBe("array");
|
||||
expect(schema.priorityTags.label).toBe("Priority Tags");
|
||||
expect(schema.priorityTags.itemType).toBe("string");
|
||||
});
|
||||
|
||||
it("should have default values in settings schema", () => {
|
||||
const schema = plugin.manifest.settingsSchema!;
|
||||
|
||||
expect(schema.customMessage.defaultValue).toBe("Hello from Settings Demo!");
|
||||
expect(schema.greetingMessage.defaultValue).toBe("Hello from Settings Demo!");
|
||||
expect(schema.maxTags.defaultValue).toBe(3);
|
||||
expect(schema.enableLogging.defaultValue).toBe(true);
|
||||
expect(schema.logLevel.defaultValue).toBe("info");
|
||||
expect(schema.priorityTags.defaultValue).toEqual(["bug", "feature"]);
|
||||
});
|
||||
|
||||
it("should have tools defined", () => {
|
||||
@@ -140,19 +162,26 @@ describe("settings demo plugin", () => {
|
||||
it("should log greeting message when logging is enabled", async () => {
|
||||
const ctx = createMockContext({
|
||||
settings: {
|
||||
webhookSecret: "secret123",
|
||||
customMessage: "Custom Message",
|
||||
greetingMessage: "Custom Greeting",
|
||||
maxTags: 3,
|
||||
enableLogging: true,
|
||||
logLevel: "info",
|
||||
priorityTags: ["urgent"],
|
||||
},
|
||||
});
|
||||
|
||||
await plugin.hooks.onLoad?.(ctx as any);
|
||||
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith("Custom Greeting");
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith("Webhook secret is configured");
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith("Custom Message");
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining("maxTags: 3"),
|
||||
);
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Priority tags: urgent"),
|
||||
);
|
||||
});
|
||||
|
||||
it("should not log when logging is disabled", async () => {
|
||||
@@ -379,10 +408,13 @@ describe("settings demo plugin", () => {
|
||||
it("should return current configuration status", async () => {
|
||||
const ctx = createMockContext({
|
||||
settings: {
|
||||
webhookSecret: "secret123",
|
||||
customMessage: "Custom Message",
|
||||
greetingMessage: "Custom Greeting",
|
||||
maxTags: 5,
|
||||
enableLogging: true,
|
||||
logLevel: "debug",
|
||||
priorityTags: ["urgent", "critical"],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -390,24 +422,33 @@ describe("settings demo plugin", () => {
|
||||
const result = await tool.execute({}, ctx as any);
|
||||
|
||||
expect(result.content[0].text).toContain("Settings Demo Plugin Status:");
|
||||
expect(result.content[0].text).toContain("Custom Greeting");
|
||||
expect(result.content[0].text).toContain("Webhook Secret: configured");
|
||||
expect(result.content[0].text).toContain("Custom Message: Custom Message");
|
||||
expect(result.content[0].text).toContain("Greeting: Custom Greeting");
|
||||
expect(result.content[0].text).toContain("Max Tags: 5");
|
||||
expect(result.content[0].text).toContain("Logging: enabled");
|
||||
expect(result.content[0].text).toContain("Log Level: debug");
|
||||
expect(result.content[0].text).toContain("Priority Tags: urgent, critical");
|
||||
|
||||
expect(result.details!.webhookSecret).toBe("(configured)");
|
||||
expect(result.details!.customMessage).toBe("Custom Message");
|
||||
expect(result.details!.greetingMessage).toBe("Custom Greeting");
|
||||
expect(result.details!.maxTags).toBe(5);
|
||||
expect(result.details!.enableLogging).toBe(true);
|
||||
expect(result.details!.logLevel).toBe("debug");
|
||||
expect(result.details!.priorityTags).toEqual(["urgent", "critical"]);
|
||||
});
|
||||
|
||||
it("should return raw settings values including undefined", async () => {
|
||||
const ctx = createMockContext({
|
||||
settings: {
|
||||
webhookSecret: undefined,
|
||||
customMessage: "",
|
||||
greetingMessage: "",
|
||||
maxTags: undefined,
|
||||
enableLogging: undefined,
|
||||
logLevel: undefined,
|
||||
priorityTags: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -415,16 +456,42 @@ describe("settings demo plugin", () => {
|
||||
const result = await tool.execute({}, ctx as any);
|
||||
|
||||
// Details returns raw values (not resolved defaults)
|
||||
expect(result.details!.webhookSecret).toBeUndefined();
|
||||
expect(result.details!.customMessage).toBe("");
|
||||
expect(result.details!.greetingMessage).toBe("");
|
||||
expect(result.details!.maxTags).toBeUndefined();
|
||||
expect(result.details!.enableLogging).toBeUndefined();
|
||||
expect(result.details!.logLevel).toBeUndefined();
|
||||
expect(result.details!.priorityTags).toBeUndefined();
|
||||
|
||||
// But display text uses resolved defaults
|
||||
expect(result.content[0].text).toContain("Not configured");
|
||||
expect(result.content[0].text).toContain("Webhook Secret: not configured");
|
||||
expect(result.content[0].text).toContain("Custom Message: Not configured");
|
||||
expect(result.content[0].text).toContain("Greeting: Not configured");
|
||||
expect(result.content[0].text).toContain("Max Tags: 3");
|
||||
expect(result.content[0].text).toContain("Logging: enabled");
|
||||
expect(result.content[0].text).toContain("Log Level: info");
|
||||
expect(result.content[0].text).toContain("Priority Tags: bug, feature");
|
||||
});
|
||||
|
||||
it("should verify priorityTags array default is used when not configured", async () => {
|
||||
const ctx = createMockContext({
|
||||
settings: {
|
||||
webhookSecret: undefined,
|
||||
customMessage: undefined,
|
||||
greetingMessage: undefined,
|
||||
maxTags: undefined,
|
||||
enableLogging: false,
|
||||
logLevel: undefined,
|
||||
priorityTags: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
const tool = plugin.tools!.find((t) => t.name === "settings_demo_status")!;
|
||||
const result = await tool.execute({}, ctx as any);
|
||||
|
||||
// Priority tags should use the schema default
|
||||
expect(result.content[0].text).toContain("Priority Tags: bug, feature");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -26,6 +26,18 @@ import type {
|
||||
* Users can configure these values via the dashboard Settings → Plugins UI.
|
||||
*/
|
||||
const settingsSchema: Record<string, PluginSettingSchema> = {
|
||||
webhookSecret: {
|
||||
type: "password",
|
||||
label: "Webhook Secret",
|
||||
description: "Secret for webhook signatures",
|
||||
},
|
||||
customMessage: {
|
||||
type: "string",
|
||||
label: "Custom Message",
|
||||
description: "Multi-line message shown on load",
|
||||
multiline: true,
|
||||
defaultValue: "Hello from Settings Demo!",
|
||||
},
|
||||
greetingMessage: {
|
||||
type: "string",
|
||||
label: "Greeting Message",
|
||||
@@ -51,6 +63,13 @@ const settingsSchema: Record<string, PluginSettingSchema> = {
|
||||
enumValues: ["debug", "info", "warn", "error"],
|
||||
defaultValue: "info",
|
||||
},
|
||||
priorityTags: {
|
||||
type: "array",
|
||||
label: "Priority Tags",
|
||||
description: "Tags to prioritize in suggestions",
|
||||
itemType: "string",
|
||||
defaultValue: ["bug", "feature"],
|
||||
},
|
||||
};
|
||||
|
||||
// ── Tag Keywords Configuration ─────────────────────────────────────────────────
|
||||
@@ -184,16 +203,22 @@ const statusTool: PluginToolDefinition = {
|
||||
ctx: PluginContext,
|
||||
): Promise<PluginToolResult> => {
|
||||
// Return raw settings values for status display
|
||||
const webhookSecret = ctx.settings.webhookSecret as string | undefined;
|
||||
const customMessage = ctx.settings.customMessage as string | undefined;
|
||||
const greetingMessage = ctx.settings.greetingMessage as string | undefined;
|
||||
const maxTags = ctx.settings.maxTags as number | undefined;
|
||||
const enableLogging = ctx.settings.enableLogging as boolean | undefined;
|
||||
const logLevel = ctx.settings.logLevel as string | undefined;
|
||||
const priorityTags = ctx.settings.priorityTags as string[] | undefined;
|
||||
|
||||
// Use resolved values for display text
|
||||
const webhookConfigured = webhookSecret ? "configured" : "not configured";
|
||||
const displayCustomMessage = customMessage || "Not configured";
|
||||
const greeting = greetingMessage || "Not configured";
|
||||
const displayMaxTags = maxTags ?? 3;
|
||||
const displayEnableLogging = enableLogging ?? true;
|
||||
const displayLogLevel = logLevel || "info";
|
||||
const displayPriorityTags = priorityTags?.join(", ") || "bug, feature";
|
||||
|
||||
return {
|
||||
content: [
|
||||
@@ -201,18 +226,24 @@ const statusTool: PluginToolDefinition = {
|
||||
type: "text",
|
||||
text: [
|
||||
"Settings Demo Plugin Status:",
|
||||
`- Webhook Secret: ${webhookConfigured}`,
|
||||
`- Custom Message: ${displayCustomMessage}`,
|
||||
`- Greeting: ${greeting}`,
|
||||
`- Max Tags: ${displayMaxTags}`,
|
||||
`- Logging: ${displayEnableLogging ? "enabled" : "disabled"}`,
|
||||
`- Log Level: ${displayLogLevel}`,
|
||||
`- Priority Tags: ${displayPriorityTags}`,
|
||||
].join("\n"),
|
||||
},
|
||||
],
|
||||
details: {
|
||||
webhookSecret: webhookSecret ? "(configured)" : undefined,
|
||||
customMessage,
|
||||
greetingMessage,
|
||||
maxTags,
|
||||
enableLogging,
|
||||
logLevel,
|
||||
priorityTags,
|
||||
},
|
||||
};
|
||||
},
|
||||
@@ -232,14 +263,22 @@ const plugin: FusionPlugin = definePlugin({
|
||||
tools: [suggestTagsTool, statusTool],
|
||||
hooks: {
|
||||
onLoad: (ctx: PluginContext) => {
|
||||
const webhookSecret = ctx.settings.webhookSecret as string | undefined;
|
||||
const customMessage =
|
||||
(ctx.settings.customMessage as string) || "Hello from Settings Demo!";
|
||||
const greeting =
|
||||
(ctx.settings.greetingMessage as string) || "Hello from Settings Demo!";
|
||||
const enableLogging = (ctx.settings.enableLogging as boolean) ?? true;
|
||||
const logLevel = (ctx.settings.logLevel as string) || "info";
|
||||
const priorityTags = (ctx.settings.priorityTags as string[] | undefined) || ["bug", "feature"];
|
||||
|
||||
if (enableLogging && shouldLog(logLevel, "info")) {
|
||||
ctx.logger.info(greeting);
|
||||
if (webhookSecret) {
|
||||
ctx.logger.info("Webhook secret is configured");
|
||||
}
|
||||
ctx.logger.info(customMessage);
|
||||
ctx.logger.info(`Plugin configured with maxTags: ${ctx.settings.maxTags || 3}`);
|
||||
ctx.logger.info(`Priority tags: ${priorityTags.join(", ")}`);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user