@lyriel/openclaw-plugin 0.4.3 → 0.4.5
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/auto-update.js +175 -0
- package/dist/auto-update.js.map +1 -0
- package/dist/index.js +66 -2
- package/dist/index.js.map +1 -1
- package/openclaw.plugin.json +1 -2
- package/package.json +1 -1
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Self-update for the Lyriel OpenClaw plugin.
|
|
2
|
+
//
|
|
3
|
+
// On gateway_start we check the npm registry for a newer published version of
|
|
4
|
+
// @lyriel/openclaw-plugin. If one exists *and* its major version matches the
|
|
5
|
+
// running plugin's major (so a breaking 1.x → 2.x never lands silently), we
|
|
6
|
+
// run `npm install <pkg>@<latest>` inside the plugin's own install directory
|
|
7
|
+
// and log a one-line "restart to apply" notice. The next OpenClaw boot picks
|
|
8
|
+
// up the new code.
|
|
9
|
+
//
|
|
10
|
+
// Hot-swapping mid-session is intentionally avoided: in-flight tool calls,
|
|
11
|
+
// cached tool schemas, and the inbox long-poll all make live replacement
|
|
12
|
+
// fragile. Apply-on-restart is the safe default for non-technical users.
|
|
13
|
+
//
|
|
14
|
+
// Escape hatches:
|
|
15
|
+
// LYRIEL_NO_AUTOUPDATE=1 — skip the check entirely (offline / pinned setups)
|
|
16
|
+
// LYRIEL_UPDATE_CHANNEL — registry dist-tag to track (default "latest")
|
|
17
|
+
import { spawn } from "node:child_process";
|
|
18
|
+
import { readFile } from "node:fs/promises";
|
|
19
|
+
import { dirname, join } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
const PACKAGE_NAME = "@lyriel/openclaw-plugin";
|
|
22
|
+
const REGISTRY_BASE = "https://registry.npmjs.org";
|
|
23
|
+
const REGISTRY_TIMEOUT_MS = 4000;
|
|
24
|
+
const INSTALL_TIMEOUT_MS = 90_000;
|
|
25
|
+
function parseSemver(raw) {
|
|
26
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(raw.trim());
|
|
27
|
+
if (!m)
|
|
28
|
+
return null;
|
|
29
|
+
return {
|
|
30
|
+
major: Number(m[1]),
|
|
31
|
+
minor: Number(m[2]),
|
|
32
|
+
patch: Number(m[3]),
|
|
33
|
+
pre: m[4] ?? null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function compareSemver(a, b) {
|
|
37
|
+
if (a.major !== b.major)
|
|
38
|
+
return a.major - b.major;
|
|
39
|
+
if (a.minor !== b.minor)
|
|
40
|
+
return a.minor - b.minor;
|
|
41
|
+
if (a.patch !== b.patch)
|
|
42
|
+
return a.patch - b.patch;
|
|
43
|
+
// A version with a prerelease tag is *lower* than one without.
|
|
44
|
+
if (a.pre === null && b.pre !== null)
|
|
45
|
+
return 1;
|
|
46
|
+
if (a.pre !== null && b.pre === null)
|
|
47
|
+
return -1;
|
|
48
|
+
if (a.pre === b.pre)
|
|
49
|
+
return 0;
|
|
50
|
+
return (a.pre ?? "") < (b.pre ?? "") ? -1 : 1;
|
|
51
|
+
}
|
|
52
|
+
async function fetchJsonWithTimeout(url, timeoutMs) {
|
|
53
|
+
const controller = new AbortController();
|
|
54
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
55
|
+
try {
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
signal: controller.signal,
|
|
58
|
+
headers: { accept: "application/json" },
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
throw new Error(`registry returned ${res.status}`);
|
|
62
|
+
}
|
|
63
|
+
return await res.json();
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Walk upward from this file until we find a package.json whose "name" matches
|
|
70
|
+
// PACKAGE_NAME. That directory is where `npm install <pkg>@<v>` must run to
|
|
71
|
+
// replace the on-disk plugin. We never write outside it.
|
|
72
|
+
async function findPluginPackageRoot() {
|
|
73
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
74
|
+
for (let i = 0; i < 8; i++) {
|
|
75
|
+
try {
|
|
76
|
+
const pkgPath = join(dir, "package.json");
|
|
77
|
+
const raw = await readFile(pkgPath, "utf8");
|
|
78
|
+
const pkg = JSON.parse(raw);
|
|
79
|
+
if (typeof pkg.name === "string" &&
|
|
80
|
+
pkg.name === PACKAGE_NAME &&
|
|
81
|
+
typeof pkg.version === "string") {
|
|
82
|
+
return { root: dir, version: pkg.version };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// fall through and keep walking up
|
|
87
|
+
}
|
|
88
|
+
const parent = dirname(dir);
|
|
89
|
+
if (parent === dir)
|
|
90
|
+
break;
|
|
91
|
+
dir = parent;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
async function fetchLatestVersion(distTag) {
|
|
96
|
+
const url = `${REGISTRY_BASE}/${PACKAGE_NAME.replace("/", "%2F")}/${encodeURIComponent(distTag)}`;
|
|
97
|
+
const body = (await fetchJsonWithTimeout(url, REGISTRY_TIMEOUT_MS));
|
|
98
|
+
return typeof body.version === "string" ? body.version : null;
|
|
99
|
+
}
|
|
100
|
+
function runNpmInstall(cwd, spec) {
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
103
|
+
const child = spawn(npm, ["install", spec, "--no-audit", "--no-fund", "--silent"], {
|
|
104
|
+
cwd,
|
|
105
|
+
stdio: ["ignore", "ignore", "pipe"],
|
|
106
|
+
env: { ...process.env, ADBLOCK: "1", DISABLE_OPENCOLLECTIVE: "1" },
|
|
107
|
+
});
|
|
108
|
+
let stderr = "";
|
|
109
|
+
child.stderr?.on("data", (chunk) => {
|
|
110
|
+
stderr += String(chunk);
|
|
111
|
+
});
|
|
112
|
+
const timer = setTimeout(() => {
|
|
113
|
+
child.kill("SIGTERM");
|
|
114
|
+
}, INSTALL_TIMEOUT_MS);
|
|
115
|
+
child.on("error", (err) => {
|
|
116
|
+
clearTimeout(timer);
|
|
117
|
+
resolve({ ok: false, stderr: stderr || String(err) });
|
|
118
|
+
});
|
|
119
|
+
child.on("exit", (code) => {
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
resolve({ ok: code === 0, stderr });
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
export async function runAutoUpdate(logger) {
|
|
126
|
+
if (process.env.LYRIEL_NO_AUTOUPDATE === "1") {
|
|
127
|
+
return { status: "skipped", reason: "LYRIEL_NO_AUTOUPDATE=1" };
|
|
128
|
+
}
|
|
129
|
+
const distTag = (process.env.LYRIEL_UPDATE_CHANNEL ?? "latest").trim() || "latest";
|
|
130
|
+
const pkg = await findPluginPackageRoot();
|
|
131
|
+
if (!pkg) {
|
|
132
|
+
return {
|
|
133
|
+
status: "skipped",
|
|
134
|
+
reason: "could not locate plugin package.json on disk",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const current = parseSemver(pkg.version);
|
|
138
|
+
if (!current) {
|
|
139
|
+
return { status: "skipped", reason: `unparseable current version ${pkg.version}` };
|
|
140
|
+
}
|
|
141
|
+
let latestRaw;
|
|
142
|
+
try {
|
|
143
|
+
latestRaw = await fetchLatestVersion(distTag);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
return { status: "skipped", reason: `registry check failed: ${err.message}` };
|
|
147
|
+
}
|
|
148
|
+
if (!latestRaw) {
|
|
149
|
+
return { status: "skipped", reason: "registry returned no version" };
|
|
150
|
+
}
|
|
151
|
+
const latest = parseSemver(latestRaw);
|
|
152
|
+
if (!latest) {
|
|
153
|
+
return { status: "skipped", reason: `unparseable latest version ${latestRaw}` };
|
|
154
|
+
}
|
|
155
|
+
if (compareSemver(latest, current) <= 0) {
|
|
156
|
+
return { status: "current", version: pkg.version };
|
|
157
|
+
}
|
|
158
|
+
// Guard against a silent major bump landing on a non-technical user.
|
|
159
|
+
if (latest.major !== current.major) {
|
|
160
|
+
logger.warn(`Lyriel plugin: a new major version is available (${pkg.version} → ${latestRaw}). ` +
|
|
161
|
+
`Auto-update will not cross majors; run \`npm install ${PACKAGE_NAME}@${latestRaw}\` ` +
|
|
162
|
+
`from ${pkg.root} after reviewing the changelog.`);
|
|
163
|
+
return { status: "skipped", reason: "major version bump requires manual review" };
|
|
164
|
+
}
|
|
165
|
+
logger.info(`Lyriel plugin: updating ${pkg.version} → ${latestRaw} (channel: ${distTag})...`);
|
|
166
|
+
const result = await runNpmInstall(pkg.root, `${PACKAGE_NAME}@${latestRaw}`);
|
|
167
|
+
if (!result.ok) {
|
|
168
|
+
const tail = result.stderr.trim().split("\n").slice(-3).join(" | ");
|
|
169
|
+
(logger.error ?? logger.warn)(`Lyriel plugin: auto-update failed (${tail || "npm exited non-zero"}). Continuing on ${pkg.version}.`);
|
|
170
|
+
return { status: "failed", reason: tail || "npm exited non-zero" };
|
|
171
|
+
}
|
|
172
|
+
logger.info(`Lyriel plugin: updated ${pkg.version} → ${latestRaw}. Restart OpenClaw to load the new version.`);
|
|
173
|
+
return { status: "updated", from: pkg.version, to: latestRaw };
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=auto-update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-update.js","sourceRoot":"","sources":["../auto-update.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,8 @@
|
|
|
28
28
|
// baseUrl — defaults to https://lyriel.ai; override for dev
|
|
29
29
|
// surfaceSessionKey — optional pinned session key (otherwise auto-tracked)
|
|
30
30
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
31
|
+
import { toolPluginMetadataSymbol } from "openclaw/plugin-sdk/tool-plugin";
|
|
32
|
+
import { runAutoUpdate } from "./auto-update.js";
|
|
31
33
|
import { createInboxRunner } from "./inbox.js";
|
|
32
34
|
import { resolveTelegramSurface } from "./telegram.js";
|
|
33
35
|
import { buildToolDescriptors } from "./tools.js";
|
|
@@ -43,7 +45,7 @@ function parseConfig(raw) {
|
|
|
43
45
|
surfaceTelegramChatId: typeof o.surfaceTelegramChatId === "string" ? o.surfaceTelegramChatId : undefined,
|
|
44
46
|
};
|
|
45
47
|
}
|
|
46
|
-
|
|
48
|
+
const pluginEntry = definePluginEntry({
|
|
47
49
|
id: "lyriel",
|
|
48
50
|
name: "Lyriel",
|
|
49
51
|
description: "Lyriel plugin for OpenClaw — agent-mediated communication substrate. Long-polls /api/inbox, surfaces dispatches into the active session, and exposes five tools for asks and group plans.",
|
|
@@ -116,12 +118,16 @@ export default definePluginEntry({
|
|
|
116
118
|
},
|
|
117
119
|
});
|
|
118
120
|
api.on("gateway_start", async () => {
|
|
121
|
+
// Fire-and-forget — never block gateway_start on the registry or npm.
|
|
122
|
+
void runAutoUpdate(api.logger).catch((err) => {
|
|
123
|
+
api.logger.warn(`Lyriel plugin: auto-update check threw — ${err.message}`);
|
|
124
|
+
});
|
|
119
125
|
if (!apiKey) {
|
|
120
126
|
api.logger.warn("Lyriel plugin: gateway_start received but apiKey is empty — not starting inbox poll loop.");
|
|
121
127
|
return;
|
|
122
128
|
}
|
|
123
129
|
inbox.start();
|
|
124
|
-
api.logger.info("Lyriel plugin registered:
|
|
130
|
+
api.logger.info("Lyriel plugin registered: 7 tools (ask, reply, plan_send, plan_reply, plan_lock, plan_cancel, update_bio) + inbox poll loop");
|
|
125
131
|
});
|
|
126
132
|
api.on("gateway_stop", async () => {
|
|
127
133
|
await inbox.stop();
|
|
@@ -129,4 +135,62 @@ export default definePluginEntry({
|
|
|
129
135
|
});
|
|
130
136
|
},
|
|
131
137
|
});
|
|
138
|
+
// Attach the tool-plugin metadata symbol so OpenClaw's MCP bridge
|
|
139
|
+
// recognizes this plugin as a tool plugin and exposes its tools to
|
|
140
|
+
// the agent's tool inventory. WITHOUT this symbol, definePluginEntry-
|
|
141
|
+
// based plugins register tools in the gateway's plugin tool registry
|
|
142
|
+
// (and stock plugins like file-transfer that ship bundled work fine
|
|
143
|
+
// this way), but third-party plugins seem to need the metadata
|
|
144
|
+
// symbol present for the MCP bridge to pick them up.
|
|
145
|
+
//
|
|
146
|
+
// We attach it manually rather than using defineToolPlugin because
|
|
147
|
+
// defineToolPlugin's generated register() only registers tools — it
|
|
148
|
+
// has no path for our background inbox poll loop. By going via
|
|
149
|
+
// definePluginEntry + manual metadata attachment, we get both: the
|
|
150
|
+
// full register lifecycle for inbox + tools AND the metadata symbol
|
|
151
|
+
// that signals "expose these tools to the agent."
|
|
152
|
+
//
|
|
153
|
+
// The metadata mirrors what defineToolPlugin would have emitted: it's
|
|
154
|
+
// a static snapshot of the tool catalog (name + label + description +
|
|
155
|
+
// JSON-schema parameters) that the MCP bridge reads to advertise the
|
|
156
|
+
// tools to the agent's tools/list response. The actual handler
|
|
157
|
+
// dispatch still flows through the api.registerTool calls inside
|
|
158
|
+
// register() — the metadata is just the catalog surface.
|
|
159
|
+
//
|
|
160
|
+
// Note: parameters here are the *typebox schemas*; OpenClaw should
|
|
161
|
+
// convert them to JSON Schema for MCP advertisement. If MCP requires
|
|
162
|
+
// pre-converted JSON Schema, a follow-up will run the typebox schemas
|
|
163
|
+
// through @sinclair/typebox's `TypeCompiler` or similar at build time.
|
|
164
|
+
{
|
|
165
|
+
// Build descriptors once with an empty client config — only the
|
|
166
|
+
// shape metadata matters here, not the executors.
|
|
167
|
+
const sampleDescriptors = buildToolDescriptors({ apiKey: "", baseUrl: "" });
|
|
168
|
+
const metadata = {
|
|
169
|
+
id: pluginEntry.id,
|
|
170
|
+
name: pluginEntry.name,
|
|
171
|
+
description: pluginEntry.description,
|
|
172
|
+
activation: { onStartup: true },
|
|
173
|
+
configSchema: {
|
|
174
|
+
type: "object",
|
|
175
|
+
additionalProperties: false,
|
|
176
|
+
properties: {
|
|
177
|
+
apiKey: { type: "string" },
|
|
178
|
+
baseUrl: { type: "string", default: "https://lyriel.ai" },
|
|
179
|
+
surfaceSessionKey: { type: "string" },
|
|
180
|
+
surfaceTelegramChatId: { type: "string" },
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
tools: sampleDescriptors.map((t) => ({
|
|
184
|
+
name: t.name,
|
|
185
|
+
label: t.label ?? t.name,
|
|
186
|
+
description: t.description,
|
|
187
|
+
parameters: t.parameters,
|
|
188
|
+
})),
|
|
189
|
+
};
|
|
190
|
+
Object.defineProperty(pluginEntry, toolPluginMetadataSymbol, {
|
|
191
|
+
value: metadata,
|
|
192
|
+
enumerable: false,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
export default pluginEntry;
|
|
132
196
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,uEAAuE;AACvE,EAAE;AACF,sCAAsC;AACtC,EAAE;AACF,wEAAwE;AACxE,yEAAyE;AACzE,mDAAmD;AACnD,EAAE;AACF,uEAAuE;AACvE,0EAA0E;AAC1E,yEAAyE;AACzE,oEAAoE;AACpE,0DAA0D;AAC1D,sDAAsD;AACtD,EAAE;AACF,oEAAoE;AACpE,yEAAyE;AACzE,gDAAgD;AAChD,kEAAkE;AAClE,EAAE;AACF,sEAAsE;AACtE,yEAAyE;AACzE,wEAAwE;AACxE,6EAA6E;AAE7E,OAAO,EAAE,iBAAiB,EAA0B,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
package/openclaw.plugin.json
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
"description": "Lyriel plugin for OpenClaw. Long-polls Lyriel's /api/inbox for inbound asks, surfaces them into the user's active session, and exposes five LLM tools for sending/replying to asks and driving group plans in natural language. Cross-provider parity with the Hermes plugin.",
|
|
5
5
|
"enabledByDefault": false,
|
|
6
6
|
"activation": {
|
|
7
|
-
"onStartup": true
|
|
8
|
-
"onCapabilities": ["tool"]
|
|
7
|
+
"onStartup": true
|
|
9
8
|
},
|
|
10
9
|
"contracts": {
|
|
11
10
|
"tools": [
|