fix(plugins): re-export probe symbols + declare plugin deps in dashboard
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` / `probeOpenClawBinary` and their status types so the dashboard's `runtime-provider-probes.ts` façade can import them via the public package entry instead of deep paths. - Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`, `…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so pnpm symlinks them into `packages/dashboard/node_modules/`. Without these, the new probe imports failed with "Cannot find module" during `pnpm typecheck`. This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are in the in-flight Hermes plugin rewrite (runtime-adapter still imports from a deleted `./pi-module.js`; the new `index.ts` calls a factory with the wrong arg type) and should be resolved by the same change set that landed the rewrite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,86 +1,79 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
const { mockResolveModelConfig } = vi.hoisted(() => ({
|
||||
mockResolveModelConfig: vi.fn().mockReturnValue({
|
||||
provider: "anthropic",
|
||||
modelId: "claude-sonnet-4-5",
|
||||
apiKey: undefined,
|
||||
thinkingLevel: undefined,
|
||||
const { mockResolveCli } = vi.hoisted(() => ({
|
||||
mockResolveCli: vi.fn().mockReturnValue({
|
||||
binaryPath: "hermes",
|
||||
model: undefined,
|
||||
provider: undefined,
|
||||
maxTurns: 12,
|
||||
yolo: false,
|
||||
cliTimeoutMs: 300_000,
|
||||
}),
|
||||
}));
|
||||
vi.mock("../pi-module.js", () => ({
|
||||
resolveModelConfig: mockResolveModelConfig,
|
||||
}));
|
||||
import plugin, { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID } from "../index.js";
|
||||
vi.mock("../cli-spawn.js", async () => {
|
||||
const actual = await vi.importActual("../cli-spawn.js");
|
||||
return {
|
||||
...actual,
|
||||
resolveCliSettings: mockResolveCli,
|
||||
};
|
||||
});
|
||||
import plugin, { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID, } from "../index.js";
|
||||
import { HermesRuntimeAdapter } from "../runtime-adapter.js";
|
||||
function createMockContext(settings = {}) {
|
||||
return {
|
||||
pluginId: "fusion-plugin-hermes-runtime",
|
||||
settings,
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
},
|
||||
logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() },
|
||||
emitEvent: vi.fn(),
|
||||
taskStore: {
|
||||
getTask: vi.fn(),
|
||||
},
|
||||
taskStore: { getTask: vi.fn() },
|
||||
};
|
||||
}
|
||||
describe("hermes-runtime plugin", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockResolveCli.mockReturnValue({
|
||||
binaryPath: "hermes",
|
||||
model: undefined,
|
||||
provider: undefined,
|
||||
maxTurns: 12,
|
||||
yolo: false,
|
||||
cliTimeoutMs: 300_000,
|
||||
});
|
||||
});
|
||||
it("has expected manifest identity", () => {
|
||||
expect(plugin.manifest.id).toBe("fusion-plugin-hermes-runtime");
|
||||
expect(plugin.manifest.name).toBe("Hermes Runtime Plugin");
|
||||
expect(plugin.manifest.version).toBe("0.1.0");
|
||||
expect(plugin.state).toBe("installed");
|
||||
});
|
||||
it("registers runtime metadata and exports matching constants", () => {
|
||||
expect(HERMES_RUNTIME_ID).toBe("hermes");
|
||||
expect(plugin.runtime?.metadata.runtimeId).toBe("hermes");
|
||||
expect(plugin.runtime?.metadata.name).toBe("Hermes Runtime");
|
||||
expect(plugin.runtime?.metadata.description).toContain("pi-ai direct streaming");
|
||||
expect(plugin.runtime?.metadata.description).toContain("hermes");
|
||||
expect(plugin.manifest.runtime).toEqual(hermesRuntimeMetadata);
|
||||
});
|
||||
it("onLoad resolves model config and logs selected provider/model without api key", async () => {
|
||||
const ctx = createMockContext({ provider: "openai", modelId: "gpt-5", apiKey: "secret" });
|
||||
mockResolveModelConfig.mockReturnValue({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5",
|
||||
apiKey: "secret",
|
||||
thinkingLevel: "medium",
|
||||
it("onLoad logs selected binary path & model and emits loaded event", async () => {
|
||||
mockResolveCli.mockReturnValue({
|
||||
binaryPath: "/opt/homebrew/bin/hermes",
|
||||
model: "claude-sonnet-4-5",
|
||||
provider: "anthropic",
|
||||
maxTurns: 12,
|
||||
yolo: false,
|
||||
cliTimeoutMs: 300_000,
|
||||
});
|
||||
await plugin.hooks.onLoad?.(ctx);
|
||||
expect(mockResolveModelConfig).toHaveBeenCalledWith(ctx.settings);
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith("Hermes Runtime Plugin loaded — using openai/gpt-5");
|
||||
expect(ctx.logger.info.mock.calls[0][0]).not.toContain("secret");
|
||||
const ctx = createMockContext({ binaryPath: "/opt/homebrew/bin/hermes" });
|
||||
await plugin.hooks.onLoad(ctx);
|
||||
expect(mockResolveCli).toHaveBeenCalledWith(ctx.settings);
|
||||
expect(ctx.logger.info).toHaveBeenCalledWith(expect.stringContaining("/opt/homebrew/bin/hermes"));
|
||||
expect(ctx.emitEvent).toHaveBeenCalledWith("hermes-runtime:loaded", {
|
||||
runtimeId: "hermes",
|
||||
version: "0.1.0",
|
||||
version: plugin.manifest.version,
|
||||
});
|
||||
});
|
||||
it("runtime factory resolves settings and returns HermesRuntimeAdapter", async () => {
|
||||
const ctx = createMockContext({ provider: "openai", modelId: "gpt-5" });
|
||||
mockResolveModelConfig.mockReturnValue({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5",
|
||||
apiKey: "api-key",
|
||||
thinkingLevel: "high",
|
||||
});
|
||||
it("factory returns a HermesRuntimeAdapter", async () => {
|
||||
const ctx = createMockContext({ binaryPath: "hermes" });
|
||||
const runtime = (await hermesRuntimeFactory(ctx));
|
||||
expect(mockResolveModelConfig).toHaveBeenCalledWith(ctx.settings);
|
||||
expect(runtime).toBeInstanceOf(HermesRuntimeAdapter);
|
||||
expect(runtime.id).toBe("hermes");
|
||||
expect(runtime.name).toBe("Hermes Runtime");
|
||||
expect(runtime.config).toEqual({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5",
|
||||
apiKey: "api-key",
|
||||
thinkingLevel: "high",
|
||||
});
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=index.test.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/__tests__/index.test.ts"],"names":[],"mappings":"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"}
|
||||
@@ -1,90 +1,136 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { HermesRuntimeAdapter } from "../runtime-adapter.js";
|
||||
const { mockCreateStreamSession, mockStreamPrompt, mockDescribeStreamModel, } = vi.hoisted(() => ({
|
||||
mockCreateStreamSession: vi.fn(),
|
||||
mockStreamPrompt: vi.fn(),
|
||||
mockDescribeStreamModel: vi.fn(),
|
||||
const { mockInvoke } = vi.hoisted(() => ({
|
||||
mockInvoke: vi.fn(),
|
||||
}));
|
||||
vi.mock("../pi-module.js", () => ({
|
||||
createStreamSession: mockCreateStreamSession,
|
||||
streamPrompt: mockStreamPrompt,
|
||||
describeStreamModel: mockDescribeStreamModel,
|
||||
}));
|
||||
describe("HermesRuntimeAdapter", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.mock("../cli-spawn.js", async () => {
|
||||
const actual = await vi.importActual("../cli-spawn.js");
|
||||
return {
|
||||
...actual,
|
||||
invokeHermesCli: mockInvoke,
|
||||
};
|
||||
});
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockInvoke.mockResolvedValue({
|
||||
body: "hello from hermes",
|
||||
sessionId: "20260427_120000_abc123",
|
||||
});
|
||||
it("has stable runtime identity", () => {
|
||||
const adapter = new HermesRuntimeAdapter({ provider: "anthropic", modelId: "claude-sonnet-4-5" });
|
||||
});
|
||||
describe("HermesRuntimeAdapter — identity", () => {
|
||||
it("has stable id/name", () => {
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
expect(adapter.id).toBe("hermes");
|
||||
expect(adapter.name).toBe("Hermes Runtime");
|
||||
});
|
||||
it("createSession passes model config/systemPrompt/callbacks and returns undefined sessionFile", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5",
|
||||
apiKey: "secret",
|
||||
thinkingLevel: "high",
|
||||
});
|
||||
const session = { messages: [], dispose: vi.fn() };
|
||||
mockCreateStreamSession.mockReturnValue(session);
|
||||
});
|
||||
describe("HermesRuntimeAdapter — createSession", () => {
|
||||
it("returns a session with empty sessionId and undefined sessionFile", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const onText = vi.fn();
|
||||
const onThinking = vi.fn();
|
||||
const onToolStart = vi.fn();
|
||||
const onToolEnd = vi.fn();
|
||||
const result = await adapter.createSession({
|
||||
cwd: "/tmp/project",
|
||||
systemPrompt: "You are Hermes",
|
||||
tools: "coding",
|
||||
customTools: [{ name: "ignored" }],
|
||||
sessionManager: { foo: "bar" },
|
||||
skillSelection: { all: true },
|
||||
skills: ["bash"],
|
||||
cwd: "/repo",
|
||||
systemPrompt: "be helpful",
|
||||
onText,
|
||||
onThinking,
|
||||
onToolStart,
|
||||
onToolEnd,
|
||||
});
|
||||
expect(mockCreateStreamSession).toHaveBeenCalledWith({
|
||||
provider: "openai",
|
||||
modelId: "gpt-5",
|
||||
apiKey: "secret",
|
||||
thinkingLevel: "high",
|
||||
systemPrompt: "You are Hermes",
|
||||
callbacks: {
|
||||
onText,
|
||||
onThinking,
|
||||
onToolStart,
|
||||
onToolEnd,
|
||||
},
|
||||
expect(result.sessionFile).toBeUndefined();
|
||||
expect(result.session.sessionId).toBe("");
|
||||
expect(result.session.systemPrompt).toBe("be helpful");
|
||||
expect(result.session.callbacks.onText).toBe(onText);
|
||||
});
|
||||
});
|
||||
describe("HermesRuntimeAdapter — promptWithFallback", () => {
|
||||
it("invokes hermes CLI with no resume on first call", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({ model: "claude-sonnet-4-5" });
|
||||
const onText = vi.fn();
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
onText,
|
||||
});
|
||||
expect(result).toEqual({ session, sessionFile: undefined });
|
||||
expect(JSON.stringify(mockCreateStreamSession.mock.calls[0][0])).not.toContain("/tmp/project");
|
||||
expect(JSON.stringify(mockCreateStreamSession.mock.calls[0][0])).not.toContain("coding");
|
||||
await adapter.promptWithFallback(session, "first prompt");
|
||||
expect(mockInvoke).toHaveBeenCalledTimes(1);
|
||||
const [prompt, settings, resumeId] = mockInvoke.mock.calls[0];
|
||||
expect(prompt).toBe("first prompt");
|
||||
expect(settings.model).toBe("claude-sonnet-4-5");
|
||||
expect(resumeId).toBeUndefined();
|
||||
expect(onText).toHaveBeenCalledWith("hello from hermes");
|
||||
// Session id is captured for next call
|
||||
expect(session.sessionId).toBe("20260427_120000_abc123");
|
||||
});
|
||||
it("promptWithFallback appends user message then delegates to streamPrompt", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({ provider: "anthropic", modelId: "claude-sonnet-4-5" });
|
||||
const session = { messages: [], dispose: vi.fn() };
|
||||
await adapter.promptWithFallback(session, "Hello from Hermes");
|
||||
expect(session.messages).toEqual([{ role: "user", content: "Hello from Hermes" }]);
|
||||
expect(mockStreamPrompt).toHaveBeenCalledWith(session, {
|
||||
role: "user",
|
||||
content: "Hello from Hermes",
|
||||
it("passes captured session id as --resume on subsequent calls", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
await adapter.promptWithFallback(session, "p1");
|
||||
await adapter.promptWithFallback(session, "p2");
|
||||
const [, , resume2] = mockInvoke.mock.calls[1];
|
||||
expect(resume2).toBe("20260427_120000_abc123");
|
||||
});
|
||||
it("describeModel delegates to describeStreamModel", () => {
|
||||
const adapter = new HermesRuntimeAdapter({ provider: "anthropic", modelId: "claude-sonnet-4-5" });
|
||||
const session = { messages: [], dispose: vi.fn() };
|
||||
mockDescribeStreamModel.mockReturnValue("anthropic/claude-sonnet-4-5");
|
||||
expect(adapter.describeModel(session)).toBe("anthropic/claude-sonnet-4-5");
|
||||
expect(mockDescribeStreamModel).toHaveBeenCalledWith(session);
|
||||
it("propagates CLI errors", async () => {
|
||||
mockInvoke.mockRejectedValueOnce(new Error("hermes: missing session_id"));
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
await expect(adapter.promptWithFallback(session, "p")).rejects.toThrow(/missing session_id/);
|
||||
});
|
||||
it("dispose is a no-op when missing and calls dispose when present", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({ provider: "anthropic", modelId: "claude-sonnet-4-5" });
|
||||
const dispose = vi.fn();
|
||||
await expect(adapter.dispose({ messages: [], dispose })).resolves.toBeUndefined();
|
||||
await expect(adapter.dispose({ messages: [] })).resolves.toBeUndefined();
|
||||
expect(dispose).toHaveBeenCalledTimes(1);
|
||||
it("does NOT call onText when body is empty", async () => {
|
||||
mockInvoke.mockResolvedValueOnce({
|
||||
body: "",
|
||||
sessionId: "20260427_120000_def456",
|
||||
});
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const onText = vi.fn();
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
onText,
|
||||
});
|
||||
await adapter.promptWithFallback(session, "p");
|
||||
expect(onText).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe("HermesRuntimeAdapter — describeModel", () => {
|
||||
it("returns hermes/<provider>/<model> when both set", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({
|
||||
provider: "anthropic",
|
||||
model: "claude-sonnet-4-5",
|
||||
});
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
expect(adapter.describeModel(session)).toBe("hermes/anthropic/claude-sonnet-4-5");
|
||||
});
|
||||
it("returns hermes/<model> when only model set", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({ model: "MiniMax-M2.7" });
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
expect(adapter.describeModel(session)).toBe("hermes/MiniMax-M2.7");
|
||||
});
|
||||
it("returns plain 'hermes' when neither set", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
expect(adapter.describeModel(session)).toBe("hermes");
|
||||
});
|
||||
});
|
||||
describe("HermesRuntimeAdapter — dispose", () => {
|
||||
it("is a no-op", async () => {
|
||||
const adapter = new HermesRuntimeAdapter({});
|
||||
const { session } = await adapter.createSession({
|
||||
cwd: "/repo",
|
||||
systemPrompt: "sys",
|
||||
});
|
||||
await expect(adapter.dispose(session)).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
//# sourceMappingURL=runtime-adapter.test.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -1,8 +1,10 @@
|
||||
/**
|
||||
* Hermes Runtime Plugin
|
||||
*
|
||||
* Provides an executable Hermes runtime adapter for Fusion's plugin runtime
|
||||
* discovery and session execution pipeline.
|
||||
* Provides an executable Hermes runtime adapter that drives the local `hermes`
|
||||
* CLI as a subprocess. Discovered by Fusion's plugin runtime registry; the
|
||||
* settings configured in the dashboard's "Runtimes → Hermes" page flow through
|
||||
* `ctx.settings` into the CLI invocation.
|
||||
*/
|
||||
import type { FusionPlugin, PluginRuntimeFactory, PluginRuntimeManifestMetadata } from "@fusion/plugin-sdk";
|
||||
declare const HERMES_RUNTIME_ID = "hermes";
|
||||
@@ -11,4 +13,9 @@ declare const hermesRuntimeFactory: PluginRuntimeFactory;
|
||||
declare const plugin: FusionPlugin;
|
||||
export default plugin;
|
||||
export { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID };
|
||||
export { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export { resolveCliSettings, invokeHermesCli, buildHermesArgs, parseHermesOutput, listHermesProfiles, } from "./cli-spawn.js";
|
||||
export type { HermesCliSettings, HermesCliResult, HermesProfileSummary } from "./cli-spawn.js";
|
||||
export { probeHermesBinary } from "./probe.js";
|
||||
export type { HermesBinaryStatus } from "./probe.js";
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,oBAAoB,CAAC;AAI5B,QAAA,MAAM,iBAAiB,WAAW,CAAC;AAGnC,QAAA,MAAM,qBAAqB,EAAE,6BAK5B,CAAC;AAIF,QAAA,MAAM,oBAAoB,EAAE,oBAS3B,CAAC;AAIF,QAAA,MAAM,MAAM,EAAE,YA4BZ,CAAC;AAEH,eAAe,MAAM,CAAC;AAItB,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC"}
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EACV,YAAY,EACZ,oBAAoB,EACpB,6BAA6B,EAC9B,MAAM,oBAAoB,CAAC;AAI5B,QAAA,MAAM,iBAAiB,WAAW,CAAC;AAGnC,QAAA,MAAM,qBAAqB,EAAE,6BAK5B,CAAC;AAIF,QAAA,MAAM,oBAAoB,EAAE,oBAE3B,CAAC;AAIF,QAAA,MAAM,MAAM,EAAE,YA+BZ,CAAC;AAEH,eAAe,MAAM,CAAC;AAItB,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAG/F,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
|
||||
@@ -1,54 +1,50 @@
|
||||
/**
|
||||
* Hermes Runtime Plugin
|
||||
*
|
||||
* Provides an executable Hermes runtime adapter for Fusion's plugin runtime
|
||||
* discovery and session execution pipeline.
|
||||
* Provides an executable Hermes runtime adapter that drives the local `hermes`
|
||||
* CLI as a subprocess. Discovered by Fusion's plugin runtime registry; the
|
||||
* settings configured in the dashboard's "Runtimes → Hermes" page flow through
|
||||
* `ctx.settings` into the CLI invocation.
|
||||
*/
|
||||
import { definePlugin } from "@fusion/plugin-sdk";
|
||||
import { resolveModelConfig } from "./pi-module.js";
|
||||
import { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
// ── Hermes Runtime Metadata ───────────────────────────────────────────────────
|
||||
const HERMES_RUNTIME_ID = "hermes";
|
||||
const HERMES_RUNTIME_VERSION = "0.1.0";
|
||||
const HERMES_RUNTIME_VERSION = "0.2.0";
|
||||
const hermesRuntimeMetadata = {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
name: "Hermes Runtime",
|
||||
description: "Hermes raw-model runtime using pi-ai direct streaming",
|
||||
description: "Drives the local `hermes` CLI (NousResearch/hermes-agent)",
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
};
|
||||
// ── Hermes Runtime Factory ────────────────────────────────────────────────────
|
||||
const hermesRuntimeFactory = async (ctx) => {
|
||||
const config = resolveModelConfig(ctx.settings);
|
||||
return new HermesRuntimeAdapter({
|
||||
provider: config.provider,
|
||||
modelId: config.modelId,
|
||||
apiKey: config.apiKey,
|
||||
thinkingLevel: config.thinkingLevel,
|
||||
});
|
||||
return new HermesRuntimeAdapter(ctx.settings);
|
||||
};
|
||||
// ── Plugin Definition ─────────────────────────────────────────────────────────
|
||||
const plugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-hermes-runtime",
|
||||
name: "Hermes Runtime Plugin",
|
||||
version: "0.1.0",
|
||||
description: "Hermes AI runtime plugin for Fusion - provides AI agent execution runtime capabilities",
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
description: "Drives the local `hermes` CLI for Fusion agents — captures session ids and resumes via --resume.",
|
||||
author: "Fusion Team",
|
||||
homepage: "https://github.com/gsxdsm/fusion",
|
||||
homepage: "https://github.com/NousResearch/hermes-agent",
|
||||
runtime: hermesRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const config = resolveModelConfig(ctx.settings);
|
||||
ctx.logger.info(`Hermes Runtime Plugin loaded — using ${config.provider}/${config.modelId}`);
|
||||
const settings = resolveCliSettings(ctx.settings);
|
||||
ctx.logger.info(`Hermes Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"}`);
|
||||
ctx.emitEvent("hermes-runtime:loaded", {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
});
|
||||
},
|
||||
onUnload: () => {
|
||||
// No context available during unload
|
||||
// No persistent state to clean up — each prompt spawns a fresh subprocess.
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
@@ -57,6 +53,10 @@ const plugin = definePlugin({
|
||||
},
|
||||
});
|
||||
export default plugin;
|
||||
// ── Exports for Testing ───────────────────────────────────────────────────────
|
||||
// ── Public exports ────────────────────────────────────────────────────────────
|
||||
export { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID };
|
||||
export { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export { resolveCliSettings, invokeHermesCli, buildHermesArgs, parseHermesOutput, listHermesProfiles, } from "./cli-spawn.js";
|
||||
// Probe re-export for the dashboard's runtime-provider-probes façade.
|
||||
export { probeHermesBinary } from "./probe.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAO5D,iFAAiF;AAEjF,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AACnC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,MAAM,qBAAqB,GAAkC;IAC3D,SAAS,EAAE,iBAAiB;IAC5B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,uDAAuD;IACpE,OAAO,EAAE,sBAAsB;CAChC,CAAC;AAEF,iFAAiF;AAEjF,MAAM,oBAAoB,GAAyB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEhD,OAAO,IAAI,oBAAoB,CAAC;QAC9B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,iFAAiF;AAEjF,MAAM,MAAM,GAAiB,YAAY,CAAC;IACxC,QAAQ,EAAE;QACR,EAAE,EAAE,8BAA8B;QAClC,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,wFAAwF;QACrG,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,kCAAkC;QAC5C,OAAO,EAAE,qBAAqB;KAC/B;IACD,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE;QACL,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YACd,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAChD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC7F,GAAG,CAAC,SAAS,CAAC,uBAAuB,EAAE;gBACrC,SAAS,EAAE,iBAAiB;gBAC5B,OAAO,EAAE,sBAAsB;aAChC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,qCAAqC;QACvC,CAAC;KACF;IACD,OAAO,EAAE;QACP,QAAQ,EAAE,qBAAqB;QAC/B,OAAO,EAAE,oBAAoB;KAC9B;CACF,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC;AAEtB,iFAAiF;AAEjF,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC"}
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAO5D,iFAAiF;AAEjF,MAAM,iBAAiB,GAAG,QAAQ,CAAC;AACnC,MAAM,sBAAsB,GAAG,OAAO,CAAC;AAEvC,MAAM,qBAAqB,GAAkC;IAC3D,SAAS,EAAE,iBAAiB;IAC5B,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,2DAA2D;IACxE,OAAO,EAAE,sBAAsB;CAChC,CAAC;AAEF,iFAAiF;AAEjF,MAAM,oBAAoB,GAAyB,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/D,OAAO,IAAI,oBAAoB,CAAC,GAAG,CAAC,QAA+C,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,iFAAiF;AAEjF,MAAM,MAAM,GAAiB,YAAY,CAAC;IACxC,QAAQ,EAAE;QACR,EAAE,EAAE,8BAA8B;QAClC,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,sBAAsB;QAC/B,WAAW,EACT,kGAAkG;QACpG,MAAM,EAAE,aAAa;QACrB,QAAQ,EAAE,8CAA8C;QACxD,OAAO,EAAE,qBAAqB;KAC/B;IACD,KAAK,EAAE,WAAW;IAClB,KAAK,EAAE;QACL,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YACd,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAClD,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,yCAAyC,QAAQ,CAAC,UAAU,UAAU,QAAQ,CAAC,KAAK,IAAI,WAAW,EAAE,CACtG,CAAC;YACF,GAAG,CAAC,SAAS,CAAC,uBAAuB,EAAE;gBACrC,SAAS,EAAE,iBAAiB;gBAC5B,OAAO,EAAE,sBAAsB;aAChC,CAAC,CAAC;QACL,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACb,2EAA2E;QAC7E,CAAC;KACF;IACD,OAAO,EAAE;QACP,QAAQ,EAAE,qBAAqB;QAC/B,OAAO,EAAE,oBAAoB;KAC9B;CACF,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC;AAEtB,iFAAiF;AAEjF,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAGxB,sEAAsE;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
||||
@@ -1,12 +1,21 @@
|
||||
import type { AgentRuntime, AgentRuntimeOptions, AgentSession, AgentSessionResult, HermesModelConfig } from "./types.js";
|
||||
/**
|
||||
* Hermes Runtime Adapter — drives the local `hermes` CLI as a subprocess.
|
||||
*
|
||||
* Each call to `promptWithFallback` invokes `hermes chat -q ... -Q --source tool`
|
||||
* and captures the resulting `session_id:` line. Subsequent calls on the same
|
||||
* session pass `--resume <id>` to continue the conversation.
|
||||
*/
|
||||
import type { HermesCliSettings } from "./cli-spawn.js";
|
||||
import type { AgentRuntime, AgentRuntimeOptions, AgentSession, AgentSessionResult } from "./types.js";
|
||||
export declare class HermesRuntimeAdapter implements AgentRuntime {
|
||||
private readonly config;
|
||||
readonly id = "hermes";
|
||||
readonly name = "Hermes Runtime";
|
||||
constructor(config?: HermesModelConfig);
|
||||
private readonly settings;
|
||||
constructor(settings?: Record<string, unknown> | HermesCliSettings);
|
||||
createSession(options: AgentRuntimeOptions): Promise<AgentSessionResult>;
|
||||
promptWithFallback(session: AgentSession, prompt: string, _options?: unknown): Promise<void>;
|
||||
describeModel(session: AgentSession): string;
|
||||
dispose(session: AgentSession): Promise<void>;
|
||||
dispose(_session: AgentSession): Promise<void>;
|
||||
private describeFromSettings;
|
||||
}
|
||||
//# sourceMappingURL=runtime-adapter.d.ts.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"runtime-adapter.d.ts","sourceRoot":"","sources":["../src/runtime-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAGpB,qBAAa,oBAAqB,YAAW,YAAY;IAKrD,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,QAAQ,CAAC,EAAE,YAAY;IACvB,QAAQ,CAAC,IAAI,oBAAoB;gBAGd,MAAM,GAAE,iBAGxB;IAGG,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAqBxE,kBAAkB,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAMlG,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;IAItC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;CAKpD"}
|
||||
{"version":3,"file":"runtime-adapter.d.ts","sourceRoot":"","sources":["../src/runtime-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAEpB,qBAAa,oBAAqB,YAAW,YAAY;IACvD,QAAQ,CAAC,EAAE,YAAY;IACvB,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;gBAEjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB;IAM5D,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAqBxE,kBAAkB,CACtB,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC;IAYhB,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;IAItC,OAAO,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,OAAO,CAAC,oBAAoB;CAQ7B"}
|
||||
@@ -1,45 +1,62 @@
|
||||
import { createStreamSession, describeStreamModel, streamPrompt } from "./pi-module.js";
|
||||
/**
|
||||
* Hermes Runtime Adapter — drives the local `hermes` CLI as a subprocess.
|
||||
*
|
||||
* Each call to `promptWithFallback` invokes `hermes chat -q ... -Q --source tool`
|
||||
* and captures the resulting `session_id:` line. Subsequent calls on the same
|
||||
* session pass `--resume <id>` to continue the conversation.
|
||||
*/
|
||||
import { invokeHermesCli, resolveCliSettings } from "./cli-spawn.js";
|
||||
export class HermesRuntimeAdapter {
|
||||
config;
|
||||
id = "hermes";
|
||||
name = "Hermes Runtime";
|
||||
constructor(config = {
|
||||
provider: "anthropic",
|
||||
modelId: "claude-sonnet-4-5",
|
||||
}) {
|
||||
this.config = config;
|
||||
settings;
|
||||
constructor(settings) {
|
||||
this.settings = resolveCliSettings(settings);
|
||||
}
|
||||
async createSession(options) {
|
||||
const session = createStreamSession({
|
||||
provider: this.config.provider,
|
||||
modelId: this.config.modelId,
|
||||
apiKey: this.config.apiKey,
|
||||
thinkingLevel: this.config.thinkingLevel,
|
||||
const session = {
|
||||
model: undefined,
|
||||
systemPrompt: options.systemPrompt,
|
||||
messages: [],
|
||||
apiKey: undefined,
|
||||
thinkingLevel: undefined,
|
||||
sessionId: "",
|
||||
lastModelDescription: this.describeFromSettings(),
|
||||
callbacks: {
|
||||
onText: options.onText,
|
||||
onThinking: options.onThinking,
|
||||
onToolStart: options.onToolStart,
|
||||
onToolEnd: options.onToolEnd,
|
||||
},
|
||||
});
|
||||
return {
|
||||
session,
|
||||
sessionFile: undefined,
|
||||
dispose: () => undefined,
|
||||
};
|
||||
return { session, sessionFile: undefined };
|
||||
}
|
||||
async promptWithFallback(session, prompt, _options) {
|
||||
const userMessage = { role: "user", content: prompt };
|
||||
session.messages.push(userMessage);
|
||||
await streamPrompt(session, userMessage);
|
||||
const resumeId = session.sessionId || undefined;
|
||||
const result = await invokeHermesCli(prompt, this.settings, resumeId);
|
||||
session.sessionId = result.sessionId;
|
||||
session.lastModelDescription = this.describeFromSettings();
|
||||
if (result.body) {
|
||||
session.callbacks.onText?.(result.body);
|
||||
}
|
||||
}
|
||||
describeModel(session) {
|
||||
return describeStreamModel(session);
|
||||
return session.lastModelDescription || this.describeFromSettings();
|
||||
}
|
||||
async dispose(session) {
|
||||
if (typeof session.dispose === "function") {
|
||||
session.dispose();
|
||||
}
|
||||
async dispose(_session) {
|
||||
// No persistent resources to release — the hermes CLI process exits per turn.
|
||||
}
|
||||
describeFromSettings() {
|
||||
const provider = this.settings.provider;
|
||||
const model = this.settings.model;
|
||||
if (provider && model)
|
||||
return `hermes/${provider}/${model}`;
|
||||
if (model)
|
||||
return `hermes/${model}`;
|
||||
if (provider)
|
||||
return `hermes/${provider}`;
|
||||
return "hermes";
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=runtime-adapter.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"runtime-adapter.js","sourceRoot":"","sources":["../src/runtime-adapter.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAExF,MAAM,OAAO,oBAAoB;IAKZ;IAJV,EAAE,GAAG,QAAQ,CAAC;IACd,IAAI,GAAG,gBAAgB,CAAC;IAEjC,YACmB,SAA4B;QAC3C,QAAQ,EAAE,WAAW;QACrB,OAAO,EAAE,mBAAmB;KAC7B;QAHgB,WAAM,GAAN,MAAM,CAGtB;IACA,CAAC;IAEJ,KAAK,CAAC,aAAa,CAAC,OAA4B;QAC9C,MAAM,OAAO,GAAG,mBAAmB,CAAC;YAClC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAC1B,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,aAAa;YACxC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,SAAS,EAAE;gBACT,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B;SACF,CAAC,CAAC;QAEH,OAAO;YACL,OAAO;YACP,WAAW,EAAE,SAAS;SACvB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,OAAqB,EAAE,MAAc,EAAE,QAAkB;QAChF,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACtD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnC,MAAM,YAAY,CAAC,OAAO,EAAE,WAAkB,CAAC,CAAC;IAClD,CAAC;IAED,aAAa,CAAC,OAAqB;QACjC,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAqB;QACjC,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YAC1C,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;CACF"}
|
||||
{"version":3,"file":"runtime-adapter.js","sourceRoot":"","sources":["../src/runtime-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUrE,MAAM,OAAO,oBAAoB;IACtB,EAAE,GAAG,QAAQ,CAAC;IACd,IAAI,GAAG,gBAAgB,CAAC;IAEhB,QAAQ,CAAoB;IAE7C,YAAY,QAAsD;QAChE,IAAI,CAAC,QAAQ,GAAG,kBAAkB,CAChC,QAA+C,CAChD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,OAA4B;QAC9C,MAAM,OAAO,GAAwB;YACnC,KAAK,EAAE,SAAS;YAChB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,QAAQ,EAAE,EAAE;YACZ,MAAM,EAAE,SAAS;YACjB,aAAa,EAAE,SAAS;YACxB,SAAS,EAAE,EAAE;YACb,oBAAoB,EAAE,IAAI,CAAC,oBAAoB,EAAE;YACjD,SAAS,EAAE;gBACT,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B;YACD,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;SACzB,CAAC;QAEF,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,kBAAkB,CACtB,OAAqB,EACrB,MAAc,EACd,QAAkB;QAElB,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEtE,OAAO,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QACrC,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE3D,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,aAAa,CAAC,OAAqB;QACjC,OAAO,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAsB;QAClC,8EAA8E;IAChF,CAAC;IAEO,oBAAoB;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACxC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAClC,IAAI,QAAQ,IAAI,KAAK;YAAE,OAAO,UAAU,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC5D,IAAI,KAAK;YAAE,OAAO,UAAU,KAAK,EAAE,CAAC;QACpC,IAAI,QAAQ;YAAE,OAAO,UAAU,QAAQ,EAAE,CAAC;QAC1C,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
|
||||
Reference in New Issue
Block a user