Files
fusion/plugins/fusion-plugin-claude-runtime/src/index.ts
gsxdsm adb3eb3a37 FN-8224: add Claude ACP runtime support
Add a bundled Claude Code ACP runtime with model discovery and CLI distribution integration.

- Add the Claude ACP runtime plugin, bridge, tool forwarding, and tests.
- Register Claude model discovery and cached picker support in the dashboard.
- Stage the plugin in CLI and desktop packaging with its pinned dependency.
- Add workspace, lockfile, and release metadata.

Files changed:
 .changeset/fn-8224-claude-acp-runtime.md           |   7 +
 packages/cli/package.json                          |   1 +
 packages/cli/src/__tests__/bundle-output.test.ts   |  32 +-
 .../cli/src/plugins/staged-bundled-plugin-ids.ts   |   1 +
 packages/cli/tsup.config.ts                        |  40 +-
 .../core/src/plugins/bundled-plugin-install.ts     |   2 +
 packages/dashboard/package.json                    |   3 +-
 packages/dashboard/src/claude-model-cache.ts       | 185 +++++++
 packages/dashboard/src/routes.ts                   |   1 +
 .../dashboard/src/routes/register-model-routes.ts  |  11 +
 packages/dashboard/src/runtime-provider-probes.ts  |  15 +
 packages/dashboard/vitest.config.ts                |   4 +
 packages/desktop/scripts/workspace-tools.ts        |   1 +
 plugins/fusion-plugin-claude-runtime/README.md     |   7 +
 plugins/fusion-plugin-claude-runtime/manifest.json |   1 +
 plugins/fusion-plugin-claude-runtime/package.json  |   1 +
 .../src/__tests__/cli-spawn.test.ts                |   3 +
 .../src/__tests__/index.test.ts                    |   3 +
 .../src/__tests__/provider.test.ts                 |   8 +
 .../src/__tests__/runtime-adapter.test.ts          |   7 +
 .../src/__tests__/tool-bridge.test.ts              |  79 +++
 .../src/acp-settings.ts                            |  21 +
 .../src/acp/VENDORED.md                            |  30 ++
 .../src/acp/cli-spawn.ts                           | 188 +++++++
 .../src/acp/control-handler.ts                     | 302 ++++++++++++
 .../src/acp/event-bridge.ts                        | 308 ++++++++++++
 .../src/acp/fs-capabilities.ts                     | 263 ++++++++++
 .../fusion-plugin-claude-runtime/src/acp/index.ts  |  16 +
 .../src/acp/path-jail.ts                           | 229 +++++++++
 .../src/acp/process-manager.ts                     | 177 +++++++
 .../src/acp/prompt-builder.ts                      |  87 ++++
 .../src/acp/provider.ts                            | 542 +++++++++++++++++++++
 .../src/acp/runtime-adapter.ts                     | 190 ++++++++
 .../src/acp/sanitize.ts                            |  81 +++
 .../src/acp/tool-mapping.ts                        |  47 ++
 .../fusion-plugin-claude-runtime/src/acp/types.ts  | 189 +++++++
 .../fusion-plugin-claude-runtime/src/cli-spawn.ts  |  31 ++
 plugins/fusion-plugin-claude-runtime/src/index.ts  |  95 ++++
 .../src/mcp-forwarding.ts                          | 114 +++++
 .../src/mcp-schema-server.cjs                      | 155 ++++++
 plugins/fusion-plugin-claude-runtime/src/probe.ts  |   8 +
 .../fusion-plugin-claude-runtime/src/provider.ts   |   8 +
 .../src/runtime-adapter.ts                         | 424 ++++++++++++++++
 .../src/skill-loader.ts                            | 290 +++++++++++
 .../src/tool-bridge.ts                             | 264 ++++++++++
 plugins/fusion-plugin-claude-runtime/src/types.ts  | 142 ++++++
 plugins/fusion-plugin-claude-runtime/tsconfig.json |  10 +
 .../fusion-plugin-claude-runtime/vitest.config.ts  |  22 +
 pnpm-lock.yaml                                     | 131 ++++-
 pnpm-workspace.yaml                                |   1 +
 50 files changed, 4753 insertions(+), 24 deletions(-)

Fusion-Task-Id: FN-8224

Fusion-Task-Lineage: 4e626913-32bb-4baa-a142-816c7f4ee7c4

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-17 12:00:26 -07:00

96 lines
3.4 KiB
TypeScript

import { definePlugin } from "@fusion/plugin-sdk";
import type { FusionPlugin } from "@fusion/plugin-sdk";
import { killAllProcesses } from "./acp/index.js";
import { probeClaudeBinary } from "./probe.js";
import { discoverClaudeProviderModels } from "./provider.js";
import { ClaudeRuntimeAdapter } from "./runtime-adapter.js";
/*
FNXC:ClaudeAcpRuntime 2026-07-17-12:00:
FN-8224 adds a first-class Claude ACP runtime. It composes the reviewed,
identity-pinned claude-code-cli-acp bridge, mirrors the bundled Grok runtime,
and is additive to the existing experimental pi-claude-cli Route A.
*/
/*
FNXC:ProcessLifecycle 2026-07-16-07:00:
The dashboard backfill worker repeatedly evaluates this plugin through
`vi.resetModules()` while retaining the process singleton. Install one exit
listener per Claude lifecycle owner and use the process-shared registry in the
ACP manager so it reaps children from every evaluation. Do not appease this
with `setMaxListeners`; the listener must stay bounded.
*/
const PROCESS_EXIT_HOOK_KEY = Symbol.for("fusion.plugin.claude-runtime.exitCleanup");
const processWithExitHook = process as typeof process & { [key: symbol]: boolean | undefined };
if (!processWithExitHook[PROCESS_EXIT_HOOK_KEY]) {
process.on("exit", killAllProcesses);
processWithExitHook[PROCESS_EXIT_HOOK_KEY] = true;
}
const plugin: FusionPlugin = definePlugin({
manifest: {
id: "fusion-plugin-claude-runtime",
name: "Claude Runtime Plugin",
version: "0.1.0",
description: "Claude CLI runtime support for Fusion (ACP agent stdio)",
runtime: {
runtimeId: "claude",
name: "Claude Runtime",
version: "0.1.0",
},
},
state: "installed",
hooks: {
onLoad: (ctx) => {
ctx.logger.info(
"Claude Runtime Plugin loaded — transport=ACP (claude-code-cli-acp); probe uses claude --version",
);
},
},
runtime: {
metadata: {
runtimeId: "claude",
name: "Claude Runtime",
version: "0.1.0",
},
factory: async () => new ClaudeRuntimeAdapter(),
},
cliProviders: [
{
providerId: "claude-cli",
displayName: "Claude CLI",
binaryName: "claude",
providerType: "cli",
statusRoute: "/providers/claude-cli/status",
authRoute: "/auth/claude-cli",
actions: [
{ actionId: "enable", label: "Enable", actionType: "enable", method: "POST", route: "/auth/claude-cli" },
{ actionId: "disable", label: "Disable", actionType: "disable", method: "POST", route: "/auth/claude-cli" },
{ actionId: "test", label: "Test", actionType: "test", method: "GET", route: "/providers/claude-cli/status" }
],
probe: async () => {
const status = await probeClaudeBinary();
return {
available: status.available,
authenticated: status.authenticated,
binaryPath: status.binaryPath,
binaryName: status.binaryName,
version: status.version,
reason: status.reason,
};
},
discoverModels: discoverClaudeProviderModels,
runtime: {
runtimeId: "claude",
createAdapter: async () => new ClaudeRuntimeAdapter(),
},
},
],
});
export default plugin;
export { probeClaudeBinary } from "./probe.js";
export { discoverClaudeProviderModels } from "./provider.js";
export { ClaudeRuntimeAdapter } from "./runtime-adapter.js";
export type { ClaudeBinaryStatus } from "./types.js";