feat(FN-3998): add task lineage commit associations API, UI, and tests
Adds task lineage commit associations: a new API route stores and exposes which commits belong to which task, the `TaskChangesTab` surfaces these lineage links visually, and documentation covers the reconciliation model. Includes comprehensive tests for both the route and component. Fusion-Task-Id: FN-3998
This commit is contained in:
84
plugins/fusion-plugin-droid-runtime/src/.index.reload-1.ts
Normal file
84
plugins/fusion-plugin-droid-runtime/src/.index.reload-1.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { definePlugin } from "@fusion/plugin-sdk";
|
||||
import type { FusionPlugin, PluginRuntimeFactory, PluginRuntimeManifestMetadata } from "@fusion/plugin-sdk";
|
||||
import { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { DroidRuntimeAdapter } from "./runtime-adapter.js";
|
||||
|
||||
export const DROID_RUNTIME_ID = "droid";
|
||||
const DROID_RUNTIME_VERSION = "0.1.0";
|
||||
|
||||
export const droidRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: DROID_RUNTIME_ID,
|
||||
name: "Droid Runtime",
|
||||
description: "Drives the Droid CLI for Fusion agents",
|
||||
version: DROID_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
export const droidRuntimeFactory: PluginRuntimeFactory = async (ctx) =>
|
||||
new DroidRuntimeAdapter(ctx.settings as Record<string, unknown> | undefined);
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-droid-runtime",
|
||||
name: "Droid Runtime Plugin",
|
||||
version: DROID_RUNTIME_VERSION,
|
||||
description: "Drives the Droid CLI for Fusion agents",
|
||||
runtime: droidRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const settings = resolveCliSettings(ctx.settings as Record<string, unknown>);
|
||||
ctx.logger.info(`Droid Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"}`);
|
||||
},
|
||||
},
|
||||
uiSlots: [
|
||||
{
|
||||
slotId: "settings-provider-card",
|
||||
label: "Droid CLI Provider",
|
||||
componentPath: "./components/settings-provider-card.js",
|
||||
order: 10,
|
||||
},
|
||||
{
|
||||
slotId: "settings-integration-card",
|
||||
label: "Droid CLI Integration",
|
||||
componentPath: "./components/settings-integration-card.js",
|
||||
order: 20,
|
||||
},
|
||||
{
|
||||
slotId: "onboarding-provider-card",
|
||||
label: "Droid CLI Provider",
|
||||
componentPath: "./components/onboarding-provider-card.js",
|
||||
order: 10,
|
||||
},
|
||||
{
|
||||
slotId: "onboarding-setup-help",
|
||||
label: "Droid CLI Setup Help",
|
||||
componentPath: "./components/onboarding-setup-help.js",
|
||||
order: 20,
|
||||
},
|
||||
{
|
||||
slotId: "post-onboarding-recommendation",
|
||||
label: "Droid CLI Recommendation",
|
||||
componentPath: "./components/post-onboarding-recommendation.js",
|
||||
order: 10,
|
||||
},
|
||||
],
|
||||
runtime: {
|
||||
metadata: droidRuntimeMetadata,
|
||||
factory: droidRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
export { DroidRuntimeAdapter };
|
||||
export { probeDroidBinary } from "./probe.js";
|
||||
export type { DroidBinaryStatus } from "./probe.js";
|
||||
export { streamViaCli } from "./provider.js";
|
||||
export {
|
||||
discoverDroidModels,
|
||||
validateCliPresenceAsync,
|
||||
validateCliAuthAsync,
|
||||
killAllProcesses,
|
||||
} from "./process-manager.js";
|
||||
export { getCustomToolDefs, toolsFromContext, writeMcpConfig } from "./mcp-config.js";
|
||||
export type { McpToolDef } from "./mcp-config.js";
|
||||
84
plugins/fusion-plugin-droid-runtime/src/.index.reload-2.ts
Normal file
84
plugins/fusion-plugin-droid-runtime/src/.index.reload-2.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { definePlugin } from "@fusion/plugin-sdk";
|
||||
import type { FusionPlugin, PluginRuntimeFactory, PluginRuntimeManifestMetadata } from "@fusion/plugin-sdk";
|
||||
import { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { DroidRuntimeAdapter } from "./runtime-adapter.js";
|
||||
|
||||
export const DROID_RUNTIME_ID = "droid";
|
||||
const DROID_RUNTIME_VERSION = "0.1.0";
|
||||
|
||||
export const droidRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: DROID_RUNTIME_ID,
|
||||
name: "Droid Runtime",
|
||||
description: "Drives the Droid CLI for Fusion agents",
|
||||
version: DROID_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
export const droidRuntimeFactory: PluginRuntimeFactory = async (ctx) =>
|
||||
new DroidRuntimeAdapter(ctx.settings as Record<string, unknown> | undefined);
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-droid-runtime",
|
||||
name: "Droid Runtime Plugin",
|
||||
version: DROID_RUNTIME_VERSION,
|
||||
description: "Drives the Droid CLI for Fusion agents",
|
||||
runtime: droidRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const settings = resolveCliSettings(ctx.settings as Record<string, unknown>);
|
||||
ctx.logger.info(`Droid Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"}`);
|
||||
},
|
||||
},
|
||||
uiSlots: [
|
||||
{
|
||||
slotId: "settings-provider-card",
|
||||
label: "Droid CLI Provider",
|
||||
componentPath: "./components/settings-provider-card.js",
|
||||
order: 10,
|
||||
},
|
||||
{
|
||||
slotId: "settings-integration-card",
|
||||
label: "Droid CLI Integration",
|
||||
componentPath: "./components/settings-integration-card.js",
|
||||
order: 20,
|
||||
},
|
||||
{
|
||||
slotId: "onboarding-provider-card",
|
||||
label: "Droid CLI Provider",
|
||||
componentPath: "./components/onboarding-provider-card.js",
|
||||
order: 10,
|
||||
},
|
||||
{
|
||||
slotId: "onboarding-setup-help",
|
||||
label: "Droid CLI Setup Help",
|
||||
componentPath: "./components/onboarding-setup-help.js",
|
||||
order: 20,
|
||||
},
|
||||
{
|
||||
slotId: "post-onboarding-recommendation",
|
||||
label: "Droid CLI Recommendation",
|
||||
componentPath: "./components/post-onboarding-recommendation.js",
|
||||
order: 10,
|
||||
},
|
||||
],
|
||||
runtime: {
|
||||
metadata: droidRuntimeMetadata,
|
||||
factory: droidRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
export { DroidRuntimeAdapter };
|
||||
export { probeDroidBinary } from "./probe.js";
|
||||
export type { DroidBinaryStatus } from "./probe.js";
|
||||
export { streamViaCli } from "./provider.js";
|
||||
export {
|
||||
discoverDroidModels,
|
||||
validateCliPresenceAsync,
|
||||
validateCliAuthAsync,
|
||||
killAllProcesses,
|
||||
} from "./process-manager.js";
|
||||
export { getCustomToolDefs, toolsFromContext, writeMcpConfig } from "./mcp-config.js";
|
||||
export type { McpToolDef } from "./mcp-config.js";
|
||||
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-1.ts
Normal file
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-1.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Hermes Runtime Plugin
|
||||
*
|
||||
* 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 { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { installFusionSkillIntoHermesHome } from "./fusion-skill-install.js";
|
||||
import { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
import type {
|
||||
FusionPlugin,
|
||||
PluginRuntimeFactory,
|
||||
PluginRuntimeManifestMetadata,
|
||||
} from "@fusion/plugin-sdk";
|
||||
|
||||
// ── Hermes Runtime Metadata ───────────────────────────────────────────────────
|
||||
|
||||
const HERMES_RUNTIME_ID = "hermes";
|
||||
const HERMES_RUNTIME_VERSION = "0.2.0";
|
||||
|
||||
const hermesRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
name: "Hermes Runtime",
|
||||
description: "Drives the local `hermes` CLI (NousResearch/hermes-agent)",
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
// ── Hermes Runtime Factory ────────────────────────────────────────────────────
|
||||
|
||||
const hermesRuntimeFactory: PluginRuntimeFactory = async (ctx) => {
|
||||
return new HermesRuntimeAdapter(ctx.settings as Record<string, unknown> | undefined);
|
||||
};
|
||||
|
||||
// ── Plugin Definition ─────────────────────────────────────────────────────────
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-hermes-runtime",
|
||||
name: "Hermes Runtime Plugin",
|
||||
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/NousResearch/hermes-agent",
|
||||
runtime: hermesRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const settings = resolveCliSettings(ctx.settings);
|
||||
const skillInstall = installFusionSkillIntoHermesHome({ profile: settings.profile });
|
||||
|
||||
if (skillInstall.outcome === "warning") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install warning: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
} else if (skillInstall.outcome === "skipped") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install skipped: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.logger.info(
|
||||
`Hermes Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"} fusionSkill=${skillInstall.outcome}`,
|
||||
);
|
||||
ctx.emitEvent("hermes-runtime:loaded", {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
});
|
||||
},
|
||||
onUnload: () => {
|
||||
// No persistent state to clean up — each prompt spawns a fresh subprocess.
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
metadata: hermesRuntimeMetadata,
|
||||
factory: hermesRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
|
||||
// ── Public exports ────────────────────────────────────────────────────────────
|
||||
|
||||
export { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID };
|
||||
export { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export {
|
||||
resolveCliSettings,
|
||||
invokeHermesCli,
|
||||
buildHermesArgs,
|
||||
parseHermesOutput,
|
||||
listHermesProfiles,
|
||||
} from "./cli-spawn.js";
|
||||
export {
|
||||
installFusionSkillIntoHermesHome,
|
||||
resolveBundledFusionSkillSource,
|
||||
resolveHermesHome,
|
||||
} from "./fusion-skill-install.js";
|
||||
export type { HermesCliSettings, HermesCliResult, HermesProfileSummary } from "./cli-spawn.js";
|
||||
|
||||
// Probe re-export for the dashboard's runtime-provider-probes façade.
|
||||
export { probeHermesBinary } from "./probe.js";
|
||||
export type { HermesBinaryStatus } from "./probe.js";
|
||||
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-2.ts
Normal file
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-2.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Hermes Runtime Plugin
|
||||
*
|
||||
* 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 { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { installFusionSkillIntoHermesHome } from "./fusion-skill-install.js";
|
||||
import { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
import type {
|
||||
FusionPlugin,
|
||||
PluginRuntimeFactory,
|
||||
PluginRuntimeManifestMetadata,
|
||||
} from "@fusion/plugin-sdk";
|
||||
|
||||
// ── Hermes Runtime Metadata ───────────────────────────────────────────────────
|
||||
|
||||
const HERMES_RUNTIME_ID = "hermes";
|
||||
const HERMES_RUNTIME_VERSION = "0.2.0";
|
||||
|
||||
const hermesRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
name: "Hermes Runtime",
|
||||
description: "Drives the local `hermes` CLI (NousResearch/hermes-agent)",
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
// ── Hermes Runtime Factory ────────────────────────────────────────────────────
|
||||
|
||||
const hermesRuntimeFactory: PluginRuntimeFactory = async (ctx) => {
|
||||
return new HermesRuntimeAdapter(ctx.settings as Record<string, unknown> | undefined);
|
||||
};
|
||||
|
||||
// ── Plugin Definition ─────────────────────────────────────────────────────────
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-hermes-runtime",
|
||||
name: "Hermes Runtime Plugin",
|
||||
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/NousResearch/hermes-agent",
|
||||
runtime: hermesRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const settings = resolveCliSettings(ctx.settings);
|
||||
const skillInstall = installFusionSkillIntoHermesHome({ profile: settings.profile });
|
||||
|
||||
if (skillInstall.outcome === "warning") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install warning: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
} else if (skillInstall.outcome === "skipped") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install skipped: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.logger.info(
|
||||
`Hermes Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"} fusionSkill=${skillInstall.outcome}`,
|
||||
);
|
||||
ctx.emitEvent("hermes-runtime:loaded", {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
});
|
||||
},
|
||||
onUnload: () => {
|
||||
// No persistent state to clean up — each prompt spawns a fresh subprocess.
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
metadata: hermesRuntimeMetadata,
|
||||
factory: hermesRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
|
||||
// ── Public exports ────────────────────────────────────────────────────────────
|
||||
|
||||
export { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID };
|
||||
export { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export {
|
||||
resolveCliSettings,
|
||||
invokeHermesCli,
|
||||
buildHermesArgs,
|
||||
parseHermesOutput,
|
||||
listHermesProfiles,
|
||||
} from "./cli-spawn.js";
|
||||
export {
|
||||
installFusionSkillIntoHermesHome,
|
||||
resolveBundledFusionSkillSource,
|
||||
resolveHermesHome,
|
||||
} from "./fusion-skill-install.js";
|
||||
export type { HermesCliSettings, HermesCliResult, HermesProfileSummary } from "./cli-spawn.js";
|
||||
|
||||
// Probe re-export for the dashboard's runtime-provider-probes façade.
|
||||
export { probeHermesBinary } from "./probe.js";
|
||||
export type { HermesBinaryStatus } from "./probe.js";
|
||||
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-3.ts
Normal file
107
plugins/fusion-plugin-hermes-runtime/src/.index.reload-3.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* Hermes Runtime Plugin
|
||||
*
|
||||
* 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 { resolveCliSettings } from "./cli-spawn.js";
|
||||
import { installFusionSkillIntoHermesHome } from "./fusion-skill-install.js";
|
||||
import { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
import type {
|
||||
FusionPlugin,
|
||||
PluginRuntimeFactory,
|
||||
PluginRuntimeManifestMetadata,
|
||||
} from "@fusion/plugin-sdk";
|
||||
|
||||
// ── Hermes Runtime Metadata ───────────────────────────────────────────────────
|
||||
|
||||
const HERMES_RUNTIME_ID = "hermes";
|
||||
const HERMES_RUNTIME_VERSION = "0.2.0";
|
||||
|
||||
const hermesRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
name: "Hermes Runtime",
|
||||
description: "Drives the local `hermes` CLI (NousResearch/hermes-agent)",
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
// ── Hermes Runtime Factory ────────────────────────────────────────────────────
|
||||
|
||||
const hermesRuntimeFactory: PluginRuntimeFactory = async (ctx) => {
|
||||
return new HermesRuntimeAdapter(ctx.settings as Record<string, unknown> | undefined);
|
||||
};
|
||||
|
||||
// ── Plugin Definition ─────────────────────────────────────────────────────────
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-hermes-runtime",
|
||||
name: "Hermes Runtime Plugin",
|
||||
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/NousResearch/hermes-agent",
|
||||
runtime: hermesRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: (ctx) => {
|
||||
const settings = resolveCliSettings(ctx.settings);
|
||||
const skillInstall = installFusionSkillIntoHermesHome({ profile: settings.profile });
|
||||
|
||||
if (skillInstall.outcome === "warning") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install warning: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
} else if (skillInstall.outcome === "skipped") {
|
||||
ctx.logger.warn(
|
||||
`Hermes Runtime Plugin: Fusion skill auto-install skipped: ${skillInstall.reason ?? "unknown"}`,
|
||||
);
|
||||
}
|
||||
|
||||
ctx.logger.info(
|
||||
`Hermes Runtime Plugin loaded — binary=${settings.binaryPath} model=${settings.model ?? "(default)"} fusionSkill=${skillInstall.outcome}`,
|
||||
);
|
||||
ctx.emitEvent("hermes-runtime:loaded", {
|
||||
runtimeId: HERMES_RUNTIME_ID,
|
||||
version: HERMES_RUNTIME_VERSION,
|
||||
});
|
||||
},
|
||||
onUnload: () => {
|
||||
// No persistent state to clean up — each prompt spawns a fresh subprocess.
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
metadata: hermesRuntimeMetadata,
|
||||
factory: hermesRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
|
||||
// ── Public exports ────────────────────────────────────────────────────────────
|
||||
|
||||
export { hermesRuntimeMetadata, hermesRuntimeFactory, HERMES_RUNTIME_ID };
|
||||
export { HermesRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export {
|
||||
resolveCliSettings,
|
||||
invokeHermesCli,
|
||||
buildHermesArgs,
|
||||
parseHermesOutput,
|
||||
listHermesProfiles,
|
||||
} from "./cli-spawn.js";
|
||||
export {
|
||||
installFusionSkillIntoHermesHome,
|
||||
resolveBundledFusionSkillSource,
|
||||
resolveHermesHome,
|
||||
} from "./fusion-skill-install.js";
|
||||
export type { HermesCliSettings, HermesCliResult, HermesProfileSummary } from "./cli-spawn.js";
|
||||
|
||||
// Probe re-export for the dashboard's runtime-provider-probes façade.
|
||||
export { probeHermesBinary } from "./probe.js";
|
||||
export type { HermesBinaryStatus } from "./probe.js";
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* OpenClaw Runtime Plugin
|
||||
*
|
||||
* Drives the local `openclaw` CLI as a subprocess (via
|
||||
* `openclaw --no-color agent --local --json`). No daemon required.
|
||||
*/
|
||||
|
||||
import { definePlugin } from "@fusion/plugin-sdk";
|
||||
import { OpenClawRuntimeAdapter } from "./runtime-adapter.js";
|
||||
import { resolveCliConfig } from "./pi-module.js";
|
||||
import { probeOpenClawBinary } from "./probe.js";
|
||||
import type {
|
||||
FusionPlugin,
|
||||
PluginContext,
|
||||
PluginRuntimeFactory,
|
||||
PluginRuntimeManifestMetadata,
|
||||
} from "@fusion/plugin-sdk";
|
||||
|
||||
const OPENCLAW_RUNTIME_ID = "openclaw";
|
||||
const OPENCLAW_RUNTIME_VERSION = "0.2.0";
|
||||
|
||||
const openclawRuntimeMetadata: PluginRuntimeManifestMetadata = {
|
||||
runtimeId: OPENCLAW_RUNTIME_ID,
|
||||
name: "OpenClaw Runtime",
|
||||
description: "Drives the local `openclaw` CLI (openclaw/openclaw)",
|
||||
version: OPENCLAW_RUNTIME_VERSION,
|
||||
};
|
||||
|
||||
const openclawRuntimeFactory: PluginRuntimeFactory = async (ctx?: PluginContext) => {
|
||||
return new OpenClawRuntimeAdapter(ctx?.settings as Record<string, unknown> | undefined);
|
||||
};
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-openclaw-runtime",
|
||||
name: "OpenClaw Runtime Plugin",
|
||||
version: OPENCLAW_RUNTIME_VERSION,
|
||||
description:
|
||||
"Drives the local `openclaw` CLI for Fusion agents — embedded `--local` mode by default; gateway optional.",
|
||||
author: "Fusion Team",
|
||||
homepage: "https://docs.openclaw.ai/",
|
||||
runtime: openclawRuntimeMetadata,
|
||||
},
|
||||
state: "installed",
|
||||
hooks: {
|
||||
onLoad: async (ctx) => {
|
||||
const config = resolveCliConfig(ctx.settings);
|
||||
const probe = await probeOpenClawBinary({ binaryPath: config.binaryPath });
|
||||
|
||||
ctx.logger.info(
|
||||
probe.available
|
||||
? `OpenClaw Runtime Plugin loaded — binary=${config.binaryPath}${probe.version ? ` (${probe.version})` : ""}`
|
||||
: `OpenClaw Runtime Plugin loaded but binary not detected: ${probe.reason ?? "unknown"}`,
|
||||
);
|
||||
ctx.emitEvent("openclaw-runtime:loaded", {
|
||||
runtimeId: OPENCLAW_RUNTIME_ID,
|
||||
version: OPENCLAW_RUNTIME_VERSION,
|
||||
binaryAvailable: probe.available,
|
||||
binaryPath: probe.binaryPath ?? config.binaryPath,
|
||||
});
|
||||
},
|
||||
onUnload: () => {
|
||||
// No persistent state to clean up — each prompt spawns a fresh subprocess.
|
||||
},
|
||||
},
|
||||
runtime: {
|
||||
metadata: openclawRuntimeMetadata,
|
||||
factory: openclawRuntimeFactory,
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
|
||||
// ── Public exports ────────────────────────────────────────────────────────────
|
||||
|
||||
export { openclawRuntimeMetadata, openclawRuntimeFactory, OPENCLAW_RUNTIME_ID };
|
||||
export { OpenClawRuntimeAdapter } from "./runtime-adapter.js";
|
||||
export {
|
||||
resolveCliConfig,
|
||||
buildOpenClawArgs,
|
||||
createCliSession,
|
||||
promptCli,
|
||||
describeCliModel,
|
||||
extractStderrError,
|
||||
configureOpenClawMcpServer,
|
||||
} from "./pi-module.js";
|
||||
export type { CliConfig, GatewaySession, OpenClawAgentJson } from "./types.js";
|
||||
export {
|
||||
toolsToMcpToolDefs,
|
||||
writeOpenClawMcpBridgeFiles,
|
||||
} from "./mcp-config.js";
|
||||
|
||||
// Probe re-export for the dashboard's runtime-provider-probes façade.
|
||||
export { probeOpenClawBinary } from "./probe.js";
|
||||
export type { OpenClawBinaryStatus } from "./probe.js";
|
||||
111
plugins/fusion-plugin-paperclip-runtime/src/.index.reload-1.ts
Normal file
111
plugins/fusion-plugin-paperclip-runtime/src/.index.reload-1.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { definePlugin } from "@fusion/plugin-sdk";
|
||||
import {
|
||||
probePaperclipConnection,
|
||||
resolvePaperclipConfig,
|
||||
} from "./paperclip-client.js";
|
||||
import { PaperclipRuntimeAdapter } from "./runtime-adapter.js";
|
||||
import type {
|
||||
FusionPlugin,
|
||||
PluginRuntimeRegistration,
|
||||
RuntimeLogger,
|
||||
} from "./types.js";
|
||||
|
||||
// Public exports — consumed by the dashboard probe façade and tests.
|
||||
export type {
|
||||
PaperclipAgentSummary,
|
||||
PaperclipCliDiscovery,
|
||||
PaperclipCliDiscoveryResult,
|
||||
PaperclipCompanySummary,
|
||||
PaperclipConnectionStatus,
|
||||
} from "./paperclip-client.js";
|
||||
export {
|
||||
agentsMe,
|
||||
agentsMeViaCli,
|
||||
createIssueViaCli,
|
||||
discoverPaperclipCliConfig,
|
||||
getIssueViaCli,
|
||||
listCompanies,
|
||||
listCompaniesViaCli,
|
||||
listCompanyAgents,
|
||||
listCompanyAgentsViaCli,
|
||||
mintAgentApiKeyViaCli,
|
||||
probePaperclipConnection,
|
||||
probePaperclipViaCli,
|
||||
} from "./paperclip-client.js";
|
||||
export type { MintCliKeyOptions, MintedApiKey } from "./paperclip-client.js";
|
||||
export { PaperclipRuntimeAdapter } from "./runtime-adapter.js";
|
||||
|
||||
function getSettingsConfig(settings: unknown) {
|
||||
return resolvePaperclipConfig((settings ?? {}) as Record<string, unknown>);
|
||||
}
|
||||
|
||||
async function paperclipRuntimeFactory(ctx: {
|
||||
settings?: unknown;
|
||||
logger?: RuntimeLogger;
|
||||
}): Promise<unknown> {
|
||||
const config = getSettingsConfig(ctx.settings);
|
||||
// resolvePaperclipConfig returns `mode: string`; the adapter narrows it.
|
||||
return new PaperclipRuntimeAdapter(
|
||||
config as unknown as Record<string, unknown>,
|
||||
ctx.logger,
|
||||
);
|
||||
}
|
||||
|
||||
const paperclipRuntime: PluginRuntimeRegistration = {
|
||||
metadata: {
|
||||
runtimeId: "paperclip",
|
||||
name: "Paperclip Runtime",
|
||||
description: "Drives a Paperclip agent via the wakeup + heartbeat-run REST API",
|
||||
version: "1.0.0",
|
||||
},
|
||||
factory: paperclipRuntimeFactory,
|
||||
};
|
||||
|
||||
const plugin: FusionPlugin = definePlugin({
|
||||
manifest: {
|
||||
id: "fusion-plugin-paperclip-runtime",
|
||||
name: "Paperclip Runtime Plugin",
|
||||
version: "1.0.0",
|
||||
description: "Drives a Paperclip agent via the wakeup + heartbeat-run REST API",
|
||||
author: "Fusion Team",
|
||||
homepage: "https://paperclip.ing/",
|
||||
fusionVersion: ">=0.1.0",
|
||||
runtime: {
|
||||
runtimeId: "paperclip",
|
||||
name: "Paperclip Runtime",
|
||||
description: "Drives a Paperclip agent via the wakeup + heartbeat-run REST API",
|
||||
version: "1.0.0",
|
||||
},
|
||||
},
|
||||
state: "installed",
|
||||
runtime: paperclipRuntime,
|
||||
hooks: {
|
||||
onLoad: async (ctx) => {
|
||||
const config = getSettingsConfig(ctx.settings);
|
||||
ctx.logger.info(`Paperclip Runtime Plugin loaded (apiUrl=${config.apiUrl})`);
|
||||
|
||||
// Best-effort connectivity probe; failures are warnings, not errors.
|
||||
try {
|
||||
const status = await probePaperclipConnection({
|
||||
apiUrl: config.apiUrl,
|
||||
apiKey: config.apiKey,
|
||||
});
|
||||
if (status.available) {
|
||||
const ident = status.identity;
|
||||
ctx.logger.info(
|
||||
ident
|
||||
? `Paperclip reachable as ${ident.agentName} (${ident.role ?? "agent"}) at ${ident.companyName ?? ident.companyId}`
|
||||
: `Paperclip reachable at ${config.apiUrl}`,
|
||||
);
|
||||
} else {
|
||||
ctx.logger.warn(`Paperclip probe failed: ${status.reason ?? "unknown"}`);
|
||||
}
|
||||
} catch (error) {
|
||||
const reason = error instanceof Error ? error.message : String(error);
|
||||
ctx.logger.warn(`Paperclip probe threw: ${reason}`);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default plugin;
|
||||
Reference in New Issue
Block a user