mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-21 16:41:56 +00:00
Plugins: remove public extension-api surface (#48462)
* Plugins: remove public extension-api surface * Plugins: fix loader setup routing follow-ups * CI: ignore non-extension helper dirs in extension-fast * Docs: note extension-api removal as breaking
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
export { resolveAgentDir, resolveAgentWorkspaceDir } from "./agents/agent-scope.ts";
|
||||
|
||||
export { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./agents/defaults.ts";
|
||||
export { resolveAgentIdentity } from "./agents/identity.ts";
|
||||
export { resolveThinkingDefault } from "./agents/model-selection.ts";
|
||||
export { runEmbeddedPiAgent } from "./agents/pi-embedded.ts";
|
||||
export { resolveAgentTimeoutMs } from "./agents/timeout.ts";
|
||||
export { ensureAgentWorkspace } from "./agents/workspace.ts";
|
||||
export {
|
||||
resolveStorePath,
|
||||
loadSessionStore,
|
||||
saveSessionStore,
|
||||
resolveSessionFilePath,
|
||||
} from "./config/sessions.ts";
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as extensionApi from "openclaw/extension-api";
|
||||
import * as compatSdk from "openclaw/plugin-sdk/compat";
|
||||
import * as coreSdk from "openclaw/plugin-sdk/core";
|
||||
import type {
|
||||
@@ -242,8 +241,4 @@ describe("plugin-sdk subpath exports", () => {
|
||||
const zalo = await import("openclaw/plugin-sdk/zalo");
|
||||
expect(typeof zalo.resolveClientIp).toBe("function");
|
||||
});
|
||||
|
||||
it("exports the extension api bridge", () => {
|
||||
expect(typeof extensionApi.runEmbeddedPiAgent).toBe("function");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,5 +15,6 @@ export {
|
||||
requestBodyErrorToText,
|
||||
} from "../infra/http-body.js";
|
||||
export { fetchWithSsrFGuard } from "../infra/net/fetch-guard.js";
|
||||
export type { SessionEntry } from "../config/sessions/types.js";
|
||||
export type { OpenClawPluginApi } from "../plugins/types.js";
|
||||
export { sleep } from "../utils.js";
|
||||
|
||||
@@ -297,22 +297,6 @@ function createPluginSdkAliasFixture(params?: {
|
||||
return { root, srcFile, distFile };
|
||||
}
|
||||
|
||||
function createExtensionApiAliasFixture(params?: { srcBody?: string; distBody?: string }) {
|
||||
const root = makeTempDir();
|
||||
const srcFile = path.join(root, "src", "extensionAPI.ts");
|
||||
const distFile = path.join(root, "dist", "extensionAPI.js");
|
||||
mkdirSafe(path.dirname(srcFile));
|
||||
mkdirSafe(path.dirname(distFile));
|
||||
fs.writeFileSync(
|
||||
path.join(root, "package.json"),
|
||||
JSON.stringify({ name: "openclaw", type: "module" }, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(srcFile, params?.srcBody ?? "export {};\n", "utf-8");
|
||||
fs.writeFileSync(distFile, params?.distBody ?? "export {};\n", "utf-8");
|
||||
return { root, srcFile, distFile };
|
||||
}
|
||||
|
||||
function createPluginRuntimeAliasFixture(params?: { srcBody?: string; distBody?: string }) {
|
||||
const root = makeTempDir();
|
||||
const srcFile = path.join(root, "src", "plugins", "runtime", "index.ts");
|
||||
@@ -2125,6 +2109,7 @@ module.exports = {
|
||||
channels: {
|
||||
"setup-runtime-preferred-test": {
|
||||
enabled: true,
|
||||
token: "configured",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
@@ -2232,6 +2217,7 @@ module.exports = {
|
||||
channels: {
|
||||
"setup-runtime-not-preferred-test": {
|
||||
enabled: true,
|
||||
token: "configured",
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
@@ -3205,26 +3191,6 @@ module.exports = {
|
||||
expect(resolved).toBe(srcFile);
|
||||
});
|
||||
|
||||
it("prefers dist extension-api alias when loader runs from dist", () => {
|
||||
const { root, distFile } = createExtensionApiAliasFixture();
|
||||
|
||||
const resolved = __testing.resolveExtensionApiAlias({
|
||||
modulePath: path.join(root, "dist", "plugins", "loader.js"),
|
||||
});
|
||||
expect(resolved).toBe(distFile);
|
||||
});
|
||||
|
||||
it("prefers src extension-api alias when loader runs from src in non-production", () => {
|
||||
const { root, srcFile } = createExtensionApiAliasFixture();
|
||||
|
||||
const resolved = withEnv({ NODE_ENV: undefined }, () =>
|
||||
__testing.resolveExtensionApiAlias({
|
||||
modulePath: path.join(root, "src", "plugins", "loader.ts"),
|
||||
}),
|
||||
);
|
||||
expect(resolved).toBe(srcFile);
|
||||
});
|
||||
|
||||
it("resolves plugin-sdk alias from package root when loader runs from transpiler cache path", () => {
|
||||
const { root, srcFile } = createPluginSdkAliasFixture();
|
||||
|
||||
@@ -3239,18 +3205,6 @@ module.exports = {
|
||||
expect(resolved).toBe(srcFile);
|
||||
});
|
||||
|
||||
it("resolves extension-api alias from package root when loader runs from transpiler cache path", () => {
|
||||
const { root, srcFile } = createExtensionApiAliasFixture();
|
||||
|
||||
const resolved = withEnv({ NODE_ENV: undefined }, () =>
|
||||
__testing.resolveExtensionApiAlias({
|
||||
modulePath: "/tmp/tsx-cache/openclaw-loader.js",
|
||||
argv1: path.join(root, "openclaw.mjs"),
|
||||
}),
|
||||
);
|
||||
expect(resolved).toBe(srcFile);
|
||||
});
|
||||
|
||||
it("resolves plugin runtime module from package root when loader runs from transpiler cache path", () => {
|
||||
const { root, srcFile } = createPluginRuntimeAliasFixture();
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ const openAllowlistWarningCache = new Set<string>();
|
||||
const LAZY_RUNTIME_REFLECTION_KEYS = [
|
||||
"version",
|
||||
"config",
|
||||
"agent",
|
||||
"subagent",
|
||||
"system",
|
||||
"media",
|
||||
@@ -197,34 +198,6 @@ const resolvePluginSdkAliasFile = (params: {
|
||||
const resolvePluginSdkAlias = (): string | null =>
|
||||
resolvePluginSdkAliasFile({ srcFile: "root-alias.cjs", distFile: "root-alias.cjs" });
|
||||
|
||||
const resolveExtensionApiAlias = (params: LoaderModuleResolveParams = {}): string | null => {
|
||||
try {
|
||||
const modulePath = resolveLoaderModulePath(params);
|
||||
const packageRoot = resolveLoaderPackageRoot({ ...params, modulePath });
|
||||
if (!packageRoot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const orderedKinds = resolvePluginSdkAliasCandidateOrder({
|
||||
modulePath,
|
||||
isProduction: process.env.NODE_ENV === "production",
|
||||
});
|
||||
const candidateMap = {
|
||||
src: path.join(packageRoot, "src", "extensionAPI.ts"),
|
||||
dist: path.join(packageRoot, "dist", "extensionAPI.js"),
|
||||
} as const;
|
||||
for (const kind of orderedKinds) {
|
||||
const candidate = candidateMap[kind];
|
||||
if (fs.existsSync(candidate)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
function resolvePluginRuntimeModulePath(params: LoaderModuleResolveParams = {}): string | null {
|
||||
try {
|
||||
const modulePath = resolveLoaderModulePath(params);
|
||||
@@ -302,7 +275,6 @@ const resolvePluginSdkScopedAliasMap = (): Record<string, string> => {
|
||||
export const __testing = {
|
||||
listPluginSdkAliasCandidates,
|
||||
listPluginSdkExportedSubpaths,
|
||||
resolveExtensionApiAlias,
|
||||
resolvePluginSdkAliasCandidateOrder,
|
||||
resolvePluginSdkAliasFile,
|
||||
resolvePluginRuntimeModulePath,
|
||||
@@ -856,9 +828,7 @@ export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegi
|
||||
return jitiLoader;
|
||||
}
|
||||
const pluginSdkAlias = resolvePluginSdkAlias();
|
||||
const extensionApiAlias = resolveExtensionApiAlias();
|
||||
const aliasMap = {
|
||||
...(extensionApiAlias ? { "openclaw/extension-api": extensionApiAlias } : {}),
|
||||
...(pluginSdkAlias ? { "openclaw/plugin-sdk": pluginSdkAlias } : {}),
|
||||
...resolvePluginSdkScopedAliasMap(),
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
|
||||
import { onAgentEvent } from "../../infra/agent-events.js";
|
||||
import { requestHeartbeatNow } from "../../infra/heartbeat-wake.js";
|
||||
import { onSessionTranscriptUpdate } from "../../sessions/transcript-events.js";
|
||||
@@ -54,6 +55,17 @@ describe("plugin runtime command execution", () => {
|
||||
expect(runtime.system.requestHeartbeatNow).toBe(requestHeartbeatNow);
|
||||
});
|
||||
|
||||
it("exposes runtime.agent host helpers", () => {
|
||||
const runtime = createPluginRuntime();
|
||||
expect(runtime.agent.defaults).toEqual({
|
||||
model: DEFAULT_MODEL,
|
||||
provider: DEFAULT_PROVIDER,
|
||||
});
|
||||
expect(typeof runtime.agent.runEmbeddedPiAgent).toBe("function");
|
||||
expect(typeof runtime.agent.resolveAgentDir).toBe("function");
|
||||
expect(typeof runtime.agent.session.resolveSessionFilePath).toBe("function");
|
||||
});
|
||||
|
||||
it("exposes runtime.modelAuth with getApiKeyForModel and resolveApiKeyForProvider", () => {
|
||||
const runtime = createPluginRuntime();
|
||||
expect(runtime.modelAuth).toBeDefined();
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
import { resolveStateDir } from "../../config/paths.js";
|
||||
import { transcribeAudioFile } from "../../media-understanding/transcribe-audio.js";
|
||||
import { textToSpeechTelephony } from "../../tts/tts.js";
|
||||
import { createRuntimeAgent } from "./runtime-agent.js";
|
||||
import { createRuntimeChannel } from "./runtime-channel.js";
|
||||
import { createRuntimeConfig } from "./runtime-config.js";
|
||||
import { createRuntimeEvents } from "./runtime-events.js";
|
||||
@@ -53,6 +54,7 @@ export function createPluginRuntime(_options: CreatePluginRuntimeOptions = {}):
|
||||
const runtime = {
|
||||
version: resolveVersion(),
|
||||
config: createRuntimeConfig(),
|
||||
agent: createRuntimeAgent(),
|
||||
subagent: _options.subagent ?? createUnavailableSubagentRuntime(),
|
||||
system: createRuntimeSystem(),
|
||||
media: createRuntimeMedia(),
|
||||
|
||||
36
src/plugins/runtime/runtime-agent.ts
Normal file
36
src/plugins/runtime/runtime-agent.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { resolveAgentDir, resolveAgentWorkspaceDir } from "../../agents/agent-scope.js";
|
||||
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "../../agents/defaults.js";
|
||||
import { resolveAgentIdentity } from "../../agents/identity.js";
|
||||
import { resolveThinkingDefault } from "../../agents/model-selection.js";
|
||||
import { runEmbeddedPiAgent } from "../../agents/pi-embedded.js";
|
||||
import { resolveAgentTimeoutMs } from "../../agents/timeout.js";
|
||||
import { ensureAgentWorkspace } from "../../agents/workspace.js";
|
||||
import {
|
||||
loadSessionStore,
|
||||
resolveSessionFilePath,
|
||||
resolveStorePath,
|
||||
saveSessionStore,
|
||||
} from "../../config/sessions.js";
|
||||
import type { PluginRuntime } from "./types.js";
|
||||
|
||||
export function createRuntimeAgent(): PluginRuntime["agent"] {
|
||||
return {
|
||||
defaults: {
|
||||
model: DEFAULT_MODEL,
|
||||
provider: DEFAULT_PROVIDER,
|
||||
},
|
||||
resolveAgentDir,
|
||||
resolveAgentWorkspaceDir,
|
||||
resolveAgentIdentity,
|
||||
resolveThinkingDefault,
|
||||
runEmbeddedPiAgent,
|
||||
resolveAgentTimeoutMs,
|
||||
ensureAgentWorkspace,
|
||||
session: {
|
||||
resolveStorePath,
|
||||
loadSessionStore,
|
||||
saveSessionStore,
|
||||
resolveSessionFilePath,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -13,6 +13,25 @@ export type PluginRuntimeCore = {
|
||||
loadConfig: typeof import("../../config/config.js").loadConfig;
|
||||
writeConfigFile: typeof import("../../config/config.js").writeConfigFile;
|
||||
};
|
||||
agent: {
|
||||
defaults: {
|
||||
model: typeof import("../../agents/defaults.js").DEFAULT_MODEL;
|
||||
provider: typeof import("../../agents/defaults.js").DEFAULT_PROVIDER;
|
||||
};
|
||||
resolveAgentDir: typeof import("../../agents/agent-scope.js").resolveAgentDir;
|
||||
resolveAgentWorkspaceDir: typeof import("../../agents/agent-scope.js").resolveAgentWorkspaceDir;
|
||||
resolveAgentIdentity: typeof import("../../agents/identity.js").resolveAgentIdentity;
|
||||
resolveThinkingDefault: typeof import("../../agents/model-selection.js").resolveThinkingDefault;
|
||||
runEmbeddedPiAgent: typeof import("../../agents/pi-embedded.js").runEmbeddedPiAgent;
|
||||
resolveAgentTimeoutMs: typeof import("../../agents/timeout.js").resolveAgentTimeoutMs;
|
||||
ensureAgentWorkspace: typeof import("../../agents/workspace.js").ensureAgentWorkspace;
|
||||
session: {
|
||||
resolveStorePath: typeof import("../../config/sessions.js").resolveStorePath;
|
||||
loadSessionStore: typeof import("../../config/sessions.js").loadSessionStore;
|
||||
saveSessionStore: typeof import("../../config/sessions.js").saveSessionStore;
|
||||
resolveSessionFilePath: typeof import("../../config/sessions.js").resolveSessionFilePath;
|
||||
};
|
||||
};
|
||||
system: {
|
||||
enqueueSystemEvent: typeof import("../../infra/system-events.js").enqueueSystemEvent;
|
||||
requestHeartbeatNow: typeof import("../../infra/heartbeat-wake.js").requestHeartbeatNow;
|
||||
|
||||
3
src/types/extension-api.d.ts
vendored
3
src/types/extension-api.d.ts
vendored
@@ -1,3 +0,0 @@
|
||||
declare module "../../../dist/extensionAPI.js" {
|
||||
export const runEmbeddedPiAgent: (params: Record<string, unknown>) => Promise<unknown>;
|
||||
}
|
||||
Reference in New Issue
Block a user