@perkos/perkos-a2a 0.12.51 → 0.12.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin-upgrade.d.ts +23 -0
- package/dist/plugin-upgrade.d.ts.map +1 -0
- package/dist/plugin-upgrade.js +165 -0
- package/dist/plugin-upgrade.js.map +1 -0
- package/dist/repair-cli.js +14 -1
- package/dist/repair-cli.js.map +1 -1
- package/docs/plans/2026-08-15-private-store-plugin-upgrade-design.md +33 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type CommandRunner } from "./repair.js";
|
|
2
|
+
export interface PluginUpgradeOptions {
|
|
3
|
+
artifactPath: string;
|
|
4
|
+
artifactSha256: string;
|
|
5
|
+
targetVersion: string;
|
|
6
|
+
openclawBin?: string;
|
|
7
|
+
stateDir?: string;
|
|
8
|
+
configPath?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PluginUpgradeResult {
|
|
11
|
+
schemaVersion: 1;
|
|
12
|
+
ok: true;
|
|
13
|
+
phase: "done";
|
|
14
|
+
version: string;
|
|
15
|
+
idempotent: boolean;
|
|
16
|
+
snapshotCreated: boolean;
|
|
17
|
+
configRestored: boolean;
|
|
18
|
+
generationCount: 1;
|
|
19
|
+
source: "openclaw-private-npm-project";
|
|
20
|
+
}
|
|
21
|
+
/** Transactionally replace a stale OpenClaw private npm project generation. */
|
|
22
|
+
export declare function upgradePrivateStorePlugin(options: PluginUpgradeOptions, run?: CommandRunner): Promise<PluginUpgradeResult>;
|
|
23
|
+
//# sourceMappingURL=plugin-upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-upgrade.d.ts","sourceRoot":"","sources":["../src/plugin-upgrade.ts"],"names":[],"mappings":"AAMA,OAAO,EAA0D,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AAIzG,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,aAAa,EAAE,CAAC,CAAC;IACjB,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,CAAC,CAAC;IACnB,MAAM,EAAE,8BAA8B,CAAC;CACxC;AA4DD,+EAA+E;AAC/E,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,oBAAoB,EAC7B,GAAG,GAAE,aAA6B,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAgF9B"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
|
+
import { chmod, cp, mkdir, readFile, readdir, realpath, rm, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve, sep } from "node:path";
|
|
6
|
+
import { acquireRepairLock, writeJsonConfig } from "./repair.js";
|
|
7
|
+
function isObject(value) {
|
|
8
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
9
|
+
}
|
|
10
|
+
function parseJsonOutput(text) {
|
|
11
|
+
const start = text.indexOf("{");
|
|
12
|
+
if (start < 0)
|
|
13
|
+
throw new Error("OpenClaw returned no JSON object");
|
|
14
|
+
return JSON.parse(text.slice(start));
|
|
15
|
+
}
|
|
16
|
+
async function defaultRunner(command, args) {
|
|
17
|
+
return new Promise((resolveResult, reject) => {
|
|
18
|
+
const child = spawn(command, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
19
|
+
let stdout = "";
|
|
20
|
+
let stderr = "";
|
|
21
|
+
child.stdout.on("data", (chunk) => { stdout += String(chunk); });
|
|
22
|
+
child.stderr.on("data", (chunk) => { stderr += String(chunk); });
|
|
23
|
+
child.on("error", reject);
|
|
24
|
+
child.on("close", (code) => resolveResult({ code: code ?? 1, stdout, stderr }));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async function sha256(path) {
|
|
28
|
+
return createHash("sha256").update(await readFile(path)).digest("hex");
|
|
29
|
+
}
|
|
30
|
+
async function packageVersions(root) {
|
|
31
|
+
const versions = [];
|
|
32
|
+
async function walk(path, depth) {
|
|
33
|
+
if (depth > 8)
|
|
34
|
+
return;
|
|
35
|
+
let entries;
|
|
36
|
+
try {
|
|
37
|
+
entries = await readdir(path, { withFileTypes: true });
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (!entry.isDirectory())
|
|
44
|
+
continue;
|
|
45
|
+
const child = join(path, entry.name);
|
|
46
|
+
if (entry.name === "perkos-a2a" && child.includes(`${sep}@perkos${sep}`)) {
|
|
47
|
+
try {
|
|
48
|
+
const pkg = JSON.parse(await readFile(join(child, "package.json"), "utf8"));
|
|
49
|
+
if (pkg.name === "@perkos/perkos-a2a" && typeof pkg.version === "string")
|
|
50
|
+
versions.push(pkg.version);
|
|
51
|
+
}
|
|
52
|
+
catch { /* not a package root */ }
|
|
53
|
+
}
|
|
54
|
+
await walk(child, depth + 1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
await walk(root, 0);
|
|
58
|
+
return versions;
|
|
59
|
+
}
|
|
60
|
+
async function inspectActive(openclaw, run) {
|
|
61
|
+
const result = await run(openclaw, ["plugins", "inspect", "perkos-a2a", "--json"]);
|
|
62
|
+
if (result.code !== 0)
|
|
63
|
+
throw new Error("OpenClaw plugin inspection failed");
|
|
64
|
+
const parsed = parseJsonOutput(`${result.stdout}\n${result.stderr}`);
|
|
65
|
+
const plugin = isObject(parsed.plugin) ? parsed.plugin : parsed;
|
|
66
|
+
const version = typeof plugin.version === "string" ? plugin.version : "";
|
|
67
|
+
const rootDir = typeof plugin.rootDir === "string" ? plugin.rootDir : "";
|
|
68
|
+
if (!version || !rootDir)
|
|
69
|
+
throw new Error("OpenClaw plugin inspection was incomplete");
|
|
70
|
+
return { version, rootDir };
|
|
71
|
+
}
|
|
72
|
+
/** Transactionally replace a stale OpenClaw private npm project generation. */
|
|
73
|
+
export async function upgradePrivateStorePlugin(options, run = defaultRunner) {
|
|
74
|
+
if (!/^\d+\.\d+\.\d+$/u.test(options.targetVersion))
|
|
75
|
+
throw new Error("invalid target version");
|
|
76
|
+
if (!/^[a-f0-9]{64}$/u.test(options.artifactSha256))
|
|
77
|
+
throw new Error("invalid artifact sha256");
|
|
78
|
+
const artifactPath = resolve(options.artifactPath);
|
|
79
|
+
if (await sha256(artifactPath) !== options.artifactSha256)
|
|
80
|
+
throw new Error("artifact sha256 mismatch");
|
|
81
|
+
const stateDir = resolve(options.stateDir ?? join(homedir(), ".openclaw"));
|
|
82
|
+
const configPath = resolve(options.configPath ?? join(stateDir, "openclaw.json"));
|
|
83
|
+
const projectStore = join(stateDir, "npm", "projects");
|
|
84
|
+
const openclaw = options.openclawBin ?? "openclaw";
|
|
85
|
+
const release = await acquireRepairLock(stateDir);
|
|
86
|
+
let snapshot = "";
|
|
87
|
+
let originalDocument;
|
|
88
|
+
let storeExisted = false;
|
|
89
|
+
try {
|
|
90
|
+
originalDocument = JSON.parse(await readFile(configPath, "utf8"));
|
|
91
|
+
const plugins = isObject(originalDocument.plugins) ? originalDocument.plugins : undefined;
|
|
92
|
+
const entries = plugins && isObject(plugins.entries) ? plugins.entries : undefined;
|
|
93
|
+
const entry = entries && isObject(entries["perkos-a2a"]) ? structuredClone(entries["perkos-a2a"]) : undefined;
|
|
94
|
+
if (!entry)
|
|
95
|
+
throw new Error("existing PerkOS plugin config is missing");
|
|
96
|
+
try {
|
|
97
|
+
const active = await inspectActive(openclaw, run);
|
|
98
|
+
const activeRoot = await realpath(active.rootDir);
|
|
99
|
+
const managedRoot = await realpath(projectStore);
|
|
100
|
+
const versions = await packageVersions(projectStore);
|
|
101
|
+
if (active.version === options.targetVersion && activeRoot.startsWith(`${managedRoot}${sep}`)
|
|
102
|
+
&& versions.length === 1 && versions[0] === options.targetVersion) {
|
|
103
|
+
return { schemaVersion: 1, ok: true, phase: "done", version: options.targetVersion,
|
|
104
|
+
idempotent: true, snapshotCreated: false, configRestored: true, generationCount: 1,
|
|
105
|
+
source: "openclaw-private-npm-project" };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch { /* stale/missing state proceeds through the transaction */ }
|
|
109
|
+
snapshot = join(stateDir, "perkos-a2a", "plugin-upgrade", `${Date.now()}-${randomUUID()}`);
|
|
110
|
+
await mkdir(snapshot, { recursive: true, mode: 0o700 });
|
|
111
|
+
await writeFile(join(snapshot, "openclaw.json.before"), `${JSON.stringify(originalDocument, null, 2)}\n`, { mode: 0o600 });
|
|
112
|
+
try {
|
|
113
|
+
await stat(projectStore);
|
|
114
|
+
storeExisted = true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
storeExisted = false;
|
|
118
|
+
}
|
|
119
|
+
if (storeExisted)
|
|
120
|
+
await cp(projectStore, join(snapshot, "projects.before"), { recursive: true, errorOnExist: true });
|
|
121
|
+
await chmod(snapshot, 0o700);
|
|
122
|
+
const uninstall = await run(openclaw, ["plugins", "uninstall", "--force", "perkos-a2a"]);
|
|
123
|
+
if (uninstall.code !== 0)
|
|
124
|
+
throw new Error("official plugin uninstall failed");
|
|
125
|
+
const install = await run(openclaw, ["plugins", "install", "--force", "--pin", `npm-pack:${artifactPath}`]);
|
|
126
|
+
const installText = `${install.stderr}\n${install.stdout}`;
|
|
127
|
+
if (install.code !== 0 && !/EBUSY|resource busy|locked|rename/iu.test(installText)) {
|
|
128
|
+
throw new Error("official plugin install failed");
|
|
129
|
+
}
|
|
130
|
+
const current = JSON.parse(await readFile(configPath, "utf8"));
|
|
131
|
+
current.plugins = isObject(current.plugins) ? current.plugins : {};
|
|
132
|
+
const currentPlugins = current.plugins;
|
|
133
|
+
currentPlugins.entries = isObject(currentPlugins.entries) ? currentPlugins.entries : {};
|
|
134
|
+
currentPlugins.entries["perkos-a2a"] = entry;
|
|
135
|
+
await writeJsonConfig(configPath, current);
|
|
136
|
+
const validate = await run(openclaw, ["config", "validate"]);
|
|
137
|
+
if (validate.code !== 0)
|
|
138
|
+
throw new Error("OpenClaw config validation failed");
|
|
139
|
+
const active = await inspectActive(openclaw, run);
|
|
140
|
+
const versions = await packageVersions(projectStore);
|
|
141
|
+
const managedRoot = await realpath(projectStore);
|
|
142
|
+
const activeRoot = await realpath(active.rootDir);
|
|
143
|
+
if (active.version !== options.targetVersion || versions.length !== 1
|
|
144
|
+
|| versions[0] !== options.targetVersion || !activeRoot.startsWith(`${managedRoot}${sep}`)) {
|
|
145
|
+
throw new Error("target plugin generation was not uniquely selected");
|
|
146
|
+
}
|
|
147
|
+
return { schemaVersion: 1, ok: true, phase: "done", version: options.targetVersion,
|
|
148
|
+
idempotent: false, snapshotCreated: true, configRestored: true, generationCount: 1,
|
|
149
|
+
source: "openclaw-private-npm-project" };
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (snapshot && originalDocument) {
|
|
153
|
+
await rm(projectStore, { recursive: true, force: true });
|
|
154
|
+
if (storeExisted)
|
|
155
|
+
await cp(join(snapshot, "projects.before"), projectStore, { recursive: true, errorOnExist: true });
|
|
156
|
+
await mkdir(dirname(configPath), { recursive: true, mode: 0o700 });
|
|
157
|
+
await writeJsonConfig(configPath, originalDocument);
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
await release();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=plugin-upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-upgrade.js","sourceRoot":"","sources":["../src/plugin-upgrade.ts"],"names":[],"mappings":"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"}
|
package/dist/repair-cli.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { connectOpenClaw } from "./connect.js";
|
|
3
3
|
import { connectHermes, HermesConnectFailure } from "./hermes-connect.js";
|
|
4
4
|
import { RepairFailure, repairOpenClaw } from "./repair.js";
|
|
5
|
+
import { upgradePrivateStorePlugin } from "./plugin-upgrade.js";
|
|
5
6
|
function value(flag) {
|
|
6
7
|
const index = process.argv.indexOf(flag);
|
|
7
8
|
return index >= 0 ? process.argv[index + 1] : undefined;
|
|
@@ -14,6 +15,18 @@ function required(flag) {
|
|
|
14
15
|
}
|
|
15
16
|
async function main() {
|
|
16
17
|
const command = process.argv[2];
|
|
18
|
+
if (command === "plugin-upgrade") {
|
|
19
|
+
const result = await upgradePrivateStorePlugin({
|
|
20
|
+
artifactPath: required("--artifact"),
|
|
21
|
+
artifactSha256: required("--sha256"),
|
|
22
|
+
targetVersion: required("--target-version"),
|
|
23
|
+
stateDir: value("--state-dir"),
|
|
24
|
+
configPath: value("--config"),
|
|
25
|
+
openclawBin: value("--openclaw-bin"),
|
|
26
|
+
});
|
|
27
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
17
30
|
if (command === "connect-hermes") {
|
|
18
31
|
const relayApiKey = value("--relay-api-key") ?? process.env.A2A_RELAY_API_KEY;
|
|
19
32
|
if (!relayApiKey) {
|
|
@@ -31,7 +44,7 @@ async function main() {
|
|
|
31
44
|
return;
|
|
32
45
|
}
|
|
33
46
|
if (command !== "repair" && command !== "connect") {
|
|
34
|
-
throw new Error("usage: perkos-a2a <connect|repair|connect-hermes>
|
|
47
|
+
throw new Error("usage: perkos-a2a <connect|repair|plugin-upgrade|connect-hermes> [command options] [--json]");
|
|
35
48
|
}
|
|
36
49
|
const common = {
|
|
37
50
|
artifactPath: required("--artifact"),
|
package/dist/repair-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repair-cli.js","sourceRoot":"","sources":["../src/repair-cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"repair-cli.js","sourceRoot":"","sources":["../src/repair-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Private-store plugin upgrade design
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
OpenClaw can retain several npm project generations. `plugins install --force`
|
|
6
|
+
may stage a new package while discovery continues loading an older project,
|
|
7
|
+
including after restart. A production uninstall/install attempt also showed the
|
|
8
|
+
installer may return `EBUSY` after committing part of its work.
|
|
9
|
+
|
|
10
|
+
## Command
|
|
11
|
+
|
|
12
|
+
Add `perkos-a2a plugin-upgrade` as a narrowly scoped, idempotent transaction.
|
|
13
|
+
It accepts a verified npm-pack artifact and SHA-256, derives the existing agent
|
|
14
|
+
binding from protected OpenClaw configuration, and never prints configuration.
|
|
15
|
+
|
|
16
|
+
The command snapshots the strict JSON configuration and complete private npm
|
|
17
|
+
project store into a mode-0700 attempt directory with mode-0600 files. It then
|
|
18
|
+
uses only the official OpenClaw uninstall-by-ID and pinned install operations.
|
|
19
|
+
The exported A2A entry is restored with the existing EBUSY-safe config writer.
|
|
20
|
+
Success requires config validation, one discovered A2A plugin, exact target
|
|
21
|
+
version, and a resolved root inside the private npm project store.
|
|
22
|
+
|
|
23
|
+
Any failure restores both the complete store and configuration before returning
|
|
24
|
+
a fixed-schema redacted error. Re-running after success returns an idempotent
|
|
25
|
+
success when the single resolved generation already matches the artifact.
|
|
26
|
+
|
|
27
|
+
## Tests
|
|
28
|
+
|
|
29
|
+
Tests use temporary directories and a fake command runner: successful stale-root
|
|
30
|
+
replacement, EBUSY-after-install acceptance only when exact state is certified,
|
|
31
|
+
config preservation, idempotent rerun, install failure rollback, and failure
|
|
32
|
+
when discovery resolves outside the managed private store. No test uses network,
|
|
33
|
+
real credentials, production config, or message history.
|
package/openclaw.plugin.json
CHANGED