fix: publish compiled OpenClaw runtime entry (#37)

This commit is contained in:
Gianfranco Piana
2026-05-04 11:41:54 -03:00
committed by GitHub
parent 8eb56d7130
commit 08bfcafd80
11 changed files with 215 additions and 9 deletions
+1
View File
@@ -1,2 +1,3 @@
node_modules/
dist/
.tmp-*.md
+2 -2
View File
@@ -65,8 +65,8 @@ openclaw plugins install ./gianfrancopiana-openclaw-autoresearch-<version>.tgz
```
The install command records the plugin, enables it, and makes it available
after restart. OpenClaw reads the package metadata, loads the root
[`index.ts`](index.ts), and finds the manifest in
after restart. OpenClaw reads the package metadata, loads the compiled runtime
entry [`dist/index.js`](dist/index.js), and finds the manifest in
[`openclaw.plugin.json`](openclaw.plugin.json).
Verify:
+1 -1
View File
@@ -13,7 +13,7 @@
"autoresearch_status"
]
},
"version": "1.0.10",
"version": "1.0.11",
"configSchema": {
"type": "object",
"additionalProperties": false,
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@gianfrancopiana/openclaw-autoresearch",
"version": "1.0.10",
"version": "1.0.11",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@gianfrancopiana/openclaw-autoresearch",
"version": "1.0.10",
"version": "1.0.11",
"license": "MIT",
"dependencies": {
"@sinclair/typebox": "0.34.48"
+17 -3
View File
@@ -1,18 +1,28 @@
{
"name": "@gianfrancopiana/openclaw-autoresearch",
"version": "1.0.10",
"version": "1.0.11",
"description": "Faithful OpenClaw port of pi-autoresearch.",
"type": "module",
"main": "./index.ts",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"scripts": {
"build": "node ./scripts/clean-dist.mjs && tsc -p tsconfig.build.json",
"check:release-metadata": "node ./scripts/release-metadata.mjs",
"sync:release-metadata": "node ./scripts/release-metadata.mjs --write",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "vitest run",
"validate": "npm run check:release-metadata && npm run typecheck && npm run test",
"release:verify": "npm run validate && npm pack --dry-run",
"release:verify": "npm run validate && npm run build && npm pack --dry-run",
"release:check-tag": "node ./scripts/check-release-tag.mjs",
"release:prepare": "node ./scripts/prepare-release.mjs",
"prepack": "npm run build",
"prepublishOnly": "npm run release:verify",
"smoke:openclaw-host": "node ./scripts/smoke-openclaw-host.mjs",
"smoke:registry-openclaw-host": "node ./scripts/smoke-openclaw-registry.mjs"
@@ -26,6 +36,7 @@
"experimentation"
],
"files": [
"dist/",
"index.ts",
"extensions/openclaw-autoresearch/**/*.ts",
"openclaw.plugin.json",
@@ -68,6 +79,9 @@
"extensions": [
"./index.ts"
],
"runtimeExtensions": [
"./dist/index.js"
],
"install": {
"minHostVersion": ">=2026.4.24"
},
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
fs.rmSync(path.join(process.cwd(), "dist"), { recursive: true, force: true });
+20
View File
@@ -13,6 +13,8 @@ const expectedTools = [
"log_experiment",
"autoresearch_status",
];
const expectedExtensions = ["./index.ts"];
const expectedRuntimeExtensions = ["./dist/index.js"];
const requiredKeywords = [
"openclaw",
"openclaw-plugin",
@@ -62,6 +64,14 @@ if (writeMode) {
}
if (expectedCompatRange) {
const openclaw = ensureObject(pkg, "openclaw");
if (JSON.stringify(openclaw.extensions) !== JSON.stringify(expectedExtensions)) {
openclaw.extensions = [...expectedExtensions];
packageChanged = true;
}
if (JSON.stringify(openclaw.runtimeExtensions) !== JSON.stringify(expectedRuntimeExtensions)) {
openclaw.runtimeExtensions = [...expectedRuntimeExtensions];
packageChanged = true;
}
const install = ensureObject(openclaw, "install");
const compat = ensureObject(openclaw, "compat");
if (install.minHostVersion !== expectedCompatRange) {
@@ -114,6 +124,8 @@ const minHostVersion = pkg.openclaw?.install?.minHostVersion;
const pluginApiVersion = pkg.openclaw?.compat?.pluginApi;
const peerOpenClawVersion = pkg.peerDependencies?.openclaw;
const peerOpenClawMeta = pkg.peerDependenciesMeta?.openclaw;
const extensions = pkg.openclaw?.extensions;
const runtimeExtensions = pkg.openclaw?.runtimeExtensions;
if (typeof buildVersion !== "string" || buildVersion.trim().length === 0) {
fail("package.json openclaw.build.openclawVersion must be a non-empty string");
@@ -141,6 +153,14 @@ if (peerOpenClawMeta?.optional !== true) {
fail("package.json peerDependenciesMeta.openclaw.optional must be true");
}
if (JSON.stringify(extensions) !== JSON.stringify(expectedExtensions)) {
fail(`package.json openclaw.extensions must equal ${expectedExtensions.join(", ")}`);
}
if (JSON.stringify(runtimeExtensions) !== JSON.stringify(expectedRuntimeExtensions)) {
fail(`package.json openclaw.runtimeExtensions must equal ${expectedRuntimeExtensions.join(", ")}`);
}
const toolContracts = manifest.contracts?.tools;
if (JSON.stringify(toolContracts) !== JSON.stringify(expectedTools)) {
fail(`openclaw.plugin.json contracts.tools must equal ${expectedTools.join(", ")}`);
+40 -1
View File
@@ -4,11 +4,16 @@ import { describe, expect, it } from "vitest";
type PackageManifest = {
openclawRuntime?: unknown;
main?: unknown;
types?: unknown;
exports?: unknown;
files?: unknown;
scripts?: Record<string, unknown>;
peerDependencies?: Record<string, unknown>;
peerDependenciesMeta?: Record<string, { optional?: unknown }>;
openclaw?: {
extensions?: unknown;
runtimeExtensions?: unknown;
install?: {
minHostVersion?: unknown;
};
@@ -31,15 +36,49 @@ describe("package manifest contract", () => {
expect(manifest.openclawRuntime).toBeUndefined();
expect(manifest.openclaw?.extensions).toEqual(["./index.ts"]);
expect(manifest.openclaw?.runtimeExtensions).toEqual(["./dist/index.js"]);
expect(manifest.openclaw?.install?.minHostVersion).toBe(">=2026.4.24");
expect(manifest.openclaw?.compat?.pluginApi).toBe(">=2026.4.24");
expect(manifest.openclaw?.build?.openclawVersion).toBe("2026.4.24");
});
it("runs release verification before publishing", () => {
it("publishes compiled runtime entrypoints and type declarations", () => {
const manifest = readPackageManifest();
expect(manifest.main).toBe("./dist/index.js");
expect(manifest.types).toBe("./dist/index.d.ts");
expect(manifest.exports).toEqual({
".": {
types: "./dist/index.d.ts",
import: "./dist/index.js",
default: "./dist/index.js",
},
});
expect(manifest.files).toEqual(
expect.arrayContaining([
"dist/",
"openclaw.plugin.json",
"skills/",
"docs/",
"README.md",
"RELEASING.md",
"LICENSE",
]),
);
});
it("builds compiled output before release verification and publishing", () => {
const manifest = readPackageManifest();
expect(manifest.scripts?.build).toBe("node ./scripts/clean-dist.mjs && tsc -p tsconfig.build.json");
expect(manifest.scripts?.prepack).toBe("npm run build");
expect(manifest.scripts?.["release:verify"]).toBe(
"npm run validate && npm run build && npm pack --dry-run",
);
expect(manifest.scripts?.prepublishOnly).toBe("npm run release:verify");
expect(existsSync(resolve(process.cwd(), "scripts/clean-dist.mjs"))).toBe(true);
expect(existsSync(resolve(process.cwd(), "tsconfig.build.json"))).toBe(true);
expect(existsSync(resolve(process.cwd(), "types/openclaw-plugin-sdk-core.d.ts"))).toBe(true);
});
it("provides a registry tarball smoke command", () => {
+4
View File
@@ -9,6 +9,8 @@ type PackageManifest = {
peerDependencies?: Record<string, unknown>;
peerDependenciesMeta?: Record<string, { optional?: unknown }>;
openclaw?: {
extensions?: unknown;
runtimeExtensions?: unknown;
install?: {
minHostVersion?: unknown;
};
@@ -44,6 +46,8 @@ describe("release metadata contract", () => {
expect(manifest.version).toBe(pkg.version);
expect(manifest.description).toBe(pkg.description);
expect(buildVersion).toBe("2026.4.24");
expect(pkg.openclaw?.extensions).toEqual(["./index.ts"]);
expect(pkg.openclaw?.runtimeExtensions).toEqual(["./dist/index.js"]);
expect(pkg.openclaw?.install?.minHostVersion).toBe(`>=${buildVersion}`);
expect(pkg.openclaw?.compat?.pluginApi).toBe(`>=${buildVersion}`);
expect(pkg.peerDependencies?.openclaw).toBe(`>=${buildVersion}`);
+25
View File
@@ -0,0 +1,25 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": false,
"outDir": "dist",
"rootDir": ".",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"paths": {
"openclaw/plugin-sdk": ["./types/openclaw-plugin-sdk-core.d.ts"],
"openclaw/plugin-sdk/core": ["./types/openclaw-plugin-sdk-core.d.ts"],
"openclaw/plugin-sdk/plugin-entry": ["./types/openclaw-plugin-sdk-core.d.ts"]
}
},
"include": [
"index.ts",
"extensions/openclaw-autoresearch/**/*.ts"
],
"exclude": [
"dist",
"node_modules",
"test"
]
}
+97
View File
@@ -0,0 +1,97 @@
export type CommandRegistration = {
name: string;
description: string;
acceptsArgs?: boolean;
handler: (ctx: {
args?: string;
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
runId?: string;
cwd?: string;
}) => { text: string };
};
export type OpenClawPluginToolContext = {
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
};
export type ToolRegistration = {
name: string;
};
export type AnyAgentTool = ToolRegistration;
export type OpenClawPluginApi = {
resolvePath(path: string): string;
runtime: {
system: {
runCommandWithTimeout: (
argv: string[],
optionsOrTimeout:
| number
| {
timeoutMs: number;
cwd?: string;
input?: string;
env?: NodeJS.ProcessEnv;
windowsVerbatimArguments?: boolean;
noOutputTimeoutMs?: number;
},
) => Promise<{
pid?: number;
stdout: string;
stderr: string;
code: number | null;
signal: NodeJS.Signals | null;
killed: boolean;
termination: "exit" | "timeout" | "no-output-timeout" | "signal";
noOutputTimedOut?: boolean;
}>;
};
};
registerTool(
tool: ToolRegistration | ((ctx: OpenClawPluginToolContext) => ToolRegistration),
options?: { name?: string; optional?: boolean },
): void;
registerCommand(command: CommandRegistration): void;
on?(
hookName: string,
handler: (
event: unknown,
ctx: {
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
runId?: string;
cwd?: string;
},
) => unknown,
): void;
registerHook?(
hookName: string,
handler: (
event: { systemPrompt?: string },
ctx: {
sessionKey?: string;
sessionId?: string;
workspaceDir?: string;
runId?: string;
cwd?: string;
},
) => { systemPrompt?: string } | void,
): void;
};
export function definePluginEntry<
TEntry extends {
id: string;
name: string;
description: string;
register(api: OpenClawPluginApi): void;
},
>(entry: TEntry): TEntry;
export function emptyPluginConfigSchema(): Record<string, never>;