openclaw-openagent 1.0.9 → 1.0.12
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/index.js +1 -1
- package/dist/src/app/remote-agent-tool.js +110 -14
- package/dist/src/app/types.d.ts +2 -2
- package/dist/src/plugin-ui/adapters/adapters/oc-2026-04.js +103 -0
- package/dist/src/plugin-ui/adapters/adapters/oc-2026-05.js +125 -0
- package/dist/src/plugin-ui/adapters/adapters/oc-2026-06.js +125 -0
- package/dist/src/plugin-ui/adapters/adapters/oc-unknown.js +48 -0
- package/dist/src/plugin-ui/adapters/oc-2026-04.js +103 -0
- package/dist/src/plugin-ui/adapters/oc-2026-05.js +125 -0
- package/dist/src/plugin-ui/adapters/oc-2026-06.js +125 -0
- package/dist/src/plugin-ui/adapters/oc-unknown.js +48 -0
- package/dist/src/plugin-ui/assets/bg.png +0 -0
- package/dist/src/plugin-ui/assets/icon.png +0 -0
- package/dist/src/plugin-ui/assets/openagent-override.js +2480 -1004
- package/dist/src/plugin-ui/index.d.ts +1 -1
- package/dist/src/plugin-ui/index.js +2 -2
- package/dist/src/plugin-ui/ui-extension-loader/index.d.ts +2 -1
- package/dist/src/plugin-ui/ui-extension-loader/index.js +5 -5
- package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +128 -13
- package/dist/src/plugin-ui/ui-extension-loader/types.d.ts +4 -1
- package/dist/src/state/store.d.ts +21 -0
- package/dist/src/state/store.js +54 -0
- package/dist/src/transport/oasn/oasn-invocation.d.ts +3 -0
- package/dist/src/transport/oasn/oasn-invocation.js +28 -12
- package/dist/src/transport/oasn/oasn-types.d.ts +8 -4
- package/index.ts +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +5 -4
- package/src/app/remote-agent-tool.ts +131 -16
- package/src/app/types.ts +2 -2
- package/src/plugin-ui/adapters/oc-2026-04.js +103 -0
- package/src/plugin-ui/adapters/oc-2026-05.js +125 -0
- package/src/plugin-ui/adapters/oc-2026-06.js +125 -0
- package/src/plugin-ui/adapters/oc-unknown.js +48 -0
- package/src/plugin-ui/assets/bg.png +0 -0
- package/src/plugin-ui/assets/icon.png +0 -0
- package/src/plugin-ui/assets/openagent-override.js +2480 -1004
- package/src/plugin-ui/build.cjs +309 -23
- package/src/plugin-ui/index.ts +2 -2
- package/src/plugin-ui/modules/agent-book/panel/agent-book.js +187 -14
- package/src/plugin-ui/modules/agent-book/panel/agent-card.js +26 -10
- package/src/plugin-ui/modules/agent-book/panel/agent-data.js +1 -1
- package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +149 -1
- package/src/plugin-ui/modules/agent-book/panel/styles.js +352 -210
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/components-core.js +4 -2
- package/src/plugin-ui/modules/agent-book/remote-agent-tool/thought-chain-card.js +4 -1
- package/src/plugin-ui/modules/agent-book/scanner.js +17 -5
- package/src/plugin-ui/modules/agent-book/travelcard/travel-styles.js +5 -0
- package/src/plugin-ui/modules/loader/bootstrap.js +1 -1
- package/src/plugin-ui/modules/loader/shared-state.js +278 -0
- package/src/plugin-ui/modules/remote-agent/execution-card.js +385 -124
- package/src/plugin-ui/modules/remote-agent/native-style-adapter.js +5 -23
- package/src/plugin-ui/modules/remote-agent/output-card.js +97 -31
- package/src/plugin-ui/modules/remote-agent/render-hooks.js +149 -58
- package/src/plugin-ui/modules/remote-agent/styles.js +690 -523
- package/src/plugin-ui/modules/remote-agent/tool-card-model.js +77 -3
- package/src/plugin-ui/postinstall-deploy.cjs +52 -0
- package/src/plugin-ui/ui-extension-loader/index.ts +6 -6
- package/src/plugin-ui/ui-extension-loader/registry-regex.ts +131 -14
- package/src/plugin-ui/ui-extension-loader/types.ts +5 -1
- package/src/state/store.ts +80 -0
- package/src/transport/oasn/oasn-invocation.ts +47 -12
- package/src/transport/oasn/oasn-types.ts +6 -2
- package/src/types/openclaw-plugin-sdk-media-store.d.ts +9 -0
package/src/plugin-ui/build.cjs
CHANGED
|
@@ -13,6 +13,34 @@
|
|
|
13
13
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
|
+
const crypto = require('crypto');
|
|
17
|
+
const childProcess = require('child_process');
|
|
18
|
+
|
|
19
|
+
// ── 读取 OpenClaw 版本(用于注入到产物中)──
|
|
20
|
+
function resolveBuildHostVersion() {
|
|
21
|
+
// 优先使用环境变量
|
|
22
|
+
if (process.env.OPENCLAW_HOST_VERSION) return normalizeHostVersion(process.env.OPENCLAW_HOST_VERSION);
|
|
23
|
+
|
|
24
|
+
var packageCandidates = [
|
|
25
|
+
path.join(__dirname, '..', '..', 'node_modules', 'openclaw', 'package.json'),
|
|
26
|
+
path.join(__dirname, '..', '..', 'package.json'),
|
|
27
|
+
];
|
|
28
|
+
for (var i = 0; i < packageCandidates.length; i++) {
|
|
29
|
+
try {
|
|
30
|
+
if (!fs.existsSync(packageCandidates[i])) continue;
|
|
31
|
+
var candidatePkg = JSON.parse(fs.readFileSync(packageCandidates[i], 'utf-8'));
|
|
32
|
+
if (candidatePkg && candidatePkg.name === 'openclaw') {
|
|
33
|
+
var exactVersion = normalizeHostVersion(candidatePkg.version);
|
|
34
|
+
if (exactVersion) return exactVersion;
|
|
35
|
+
}
|
|
36
|
+
var depVersion = candidatePkg && candidatePkg.devDependencies && candidatePkg.devDependencies.openclaw;
|
|
37
|
+
depVersion = normalizeHostVersion(String(depVersion || '').replace(/^[\^~>=<]+/, '').trim());
|
|
38
|
+
if (depVersion) return depVersion;
|
|
39
|
+
} catch (e) {}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
16
44
|
|
|
17
45
|
// ═══════════════════════════════════════════════════════════════
|
|
18
46
|
// MANIFEST — 显式构建顺序,不要用 readdir+sort
|
|
@@ -58,7 +86,201 @@ const MANIFEST = [
|
|
|
58
86
|
// ═══════════════════════════════════════════════════════════════
|
|
59
87
|
|
|
60
88
|
const modulesDir = path.join(__dirname, 'modules');
|
|
61
|
-
const
|
|
89
|
+
const adaptersDir = path.join(__dirname, 'adapters');
|
|
90
|
+
const assetsDir = path.join(__dirname, 'assets');
|
|
91
|
+
const outFile = path.join(assetsDir, 'openagent-override.js');
|
|
92
|
+
const iconFile = path.join(assetsDir, 'icon.png');
|
|
93
|
+
const bgFile = path.join(assetsDir, 'bg.png');
|
|
94
|
+
const HOST_VERSION_TOKEN = "hostVersion: '__OPENCLAW_HOST_VERSION__'";
|
|
95
|
+
const BUILD_ID_TOKEN = "buildId: '__OPENAGENT_BUILD_ID__'";
|
|
96
|
+
const BUILD_ID_ASSIGNMENT_RE = /buildId:\s*(?:"[^"]*"|'[^']*')/;
|
|
97
|
+
const HOST_ADAPTER_START = '/*__OPENAGENT_HOST_ADAPTER_START__*/';
|
|
98
|
+
const HOST_ADAPTER_END = '/*__OPENAGENT_HOST_ADAPTER_END__*/';
|
|
99
|
+
const HOST_ADAPTER_BLOCK_RE = /\/\*__OPENAGENT_HOST_ADAPTER_START__\*\/[\s\S]*?\/\*__OPENAGENT_HOST_ADAPTER_END__\*\//;
|
|
100
|
+
|
|
101
|
+
function normalizeHostVersion(version) {
|
|
102
|
+
var match = String(version || '').match(/20\d{2}\.\d{1,2}\.\d{1,2}(?:-[A-Za-z0-9._-]+)?/);
|
|
103
|
+
return match ? match[0] : '';
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function injectHostVersion(content, hostVersion) {
|
|
107
|
+
hostVersion = normalizeHostVersion(hostVersion);
|
|
108
|
+
if (!hostVersion) return content;
|
|
109
|
+
return content.replace(HOST_VERSION_TOKEN, 'hostVersion: ' + JSON.stringify(hostVersion));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function resolveHostAdapterId(hostVersion) {
|
|
113
|
+
var parsed = normalizeHostVersion(hostVersion).split('.');
|
|
114
|
+
var year = parseInt(parsed[0], 10);
|
|
115
|
+
var month = parseInt(parsed[1], 10);
|
|
116
|
+
if (year === 2026 && month === 4) return 'oc-2026-04';
|
|
117
|
+
if (year === 2026 && month === 5) return 'oc-2026-05';
|
|
118
|
+
if (year === 2026 && month === 6) return 'oc-2026-06';
|
|
119
|
+
return 'oc-unknown';
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function getHostAdapterBlock(hostVersion) {
|
|
123
|
+
var adapterId = resolveHostAdapterId(hostVersion);
|
|
124
|
+
var adapterPath = path.join(adaptersDir, adapterId + '.js');
|
|
125
|
+
if (!fs.existsSync(adapterPath)) {
|
|
126
|
+
adapterId = 'oc-unknown';
|
|
127
|
+
adapterPath = path.join(adaptersDir, adapterId + '.js');
|
|
128
|
+
}
|
|
129
|
+
var adapterContent = fs.readFileSync(adapterPath, 'utf-8').trimEnd();
|
|
130
|
+
return [
|
|
131
|
+
HOST_ADAPTER_START,
|
|
132
|
+
'// HOST ADAPTER: ' + adapterId,
|
|
133
|
+
adapterContent,
|
|
134
|
+
HOST_ADAPTER_END,
|
|
135
|
+
].join('\n');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function injectHostAdapter(content, hostVersion) {
|
|
139
|
+
var block = getHostAdapterBlock(hostVersion);
|
|
140
|
+
if (HOST_ADAPTER_BLOCK_RE.test(content)) {
|
|
141
|
+
return content.replace(HOST_ADAPTER_BLOCK_RE, block);
|
|
142
|
+
}
|
|
143
|
+
return content;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function renderOverrideContent(content, hostVersion) {
|
|
147
|
+
return injectBuildId(injectHostAdapter(injectHostVersion(content, hostVersion), hostVersion));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function hashContent(content) {
|
|
151
|
+
return crypto.createHash('sha256').update(content).digest('hex').slice(0, 12);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function injectBuildId(content) {
|
|
155
|
+
var normalized = content.replace(BUILD_ID_ASSIGNMENT_RE, BUILD_ID_TOKEN);
|
|
156
|
+
var buildId = hashContent(normalized);
|
|
157
|
+
return normalized.replace(BUILD_ID_TOKEN, 'buildId: ' + JSON.stringify(buildId));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function resolveControlUiHostVersion(controlUiDir) {
|
|
161
|
+
if (process.env.OPENCLAW_HOST_VERSION) return normalizeHostVersion(process.env.OPENCLAW_HOST_VERSION);
|
|
162
|
+
|
|
163
|
+
var candidates = [
|
|
164
|
+
path.join(controlUiDir, '..', '..', 'package.json'),
|
|
165
|
+
path.join(controlUiDir, '..', 'package.json'),
|
|
166
|
+
];
|
|
167
|
+
for (var i = 0; i < candidates.length; i++) {
|
|
168
|
+
try {
|
|
169
|
+
if (!fs.existsSync(candidates[i])) continue;
|
|
170
|
+
var pkg = JSON.parse(fs.readFileSync(candidates[i], 'utf-8'));
|
|
171
|
+
if (pkg && pkg.name === 'openclaw') return normalizeHostVersion(pkg.version);
|
|
172
|
+
} catch (e) {}
|
|
173
|
+
}
|
|
174
|
+
return '';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function pushUniquePath(list, candidate) {
|
|
178
|
+
if (!list || !candidate) return;
|
|
179
|
+
var resolved = path.resolve(candidate);
|
|
180
|
+
for (var i = 0; i < list.length; i++) {
|
|
181
|
+
if (path.resolve(list[i]) === resolved) return;
|
|
182
|
+
}
|
|
183
|
+
list.push(resolved);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function collectCommandOutputLines(command, args) {
|
|
187
|
+
try {
|
|
188
|
+
var result = childProcess.spawnSync(command, args, {
|
|
189
|
+
encoding: 'utf-8',
|
|
190
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
191
|
+
});
|
|
192
|
+
return String(result.stdout || '')
|
|
193
|
+
.split(/\r?\n/)
|
|
194
|
+
.map(function(line) { return line.trim(); })
|
|
195
|
+
.filter(Boolean);
|
|
196
|
+
} catch (e) {
|
|
197
|
+
return [];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function collectGlobalNodeModuleRoots() {
|
|
202
|
+
var roots = [];
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
pushUniquePath(roots, path.join(path.dirname(process.execPath), '..', 'lib', 'node_modules'));
|
|
206
|
+
} catch (e) {}
|
|
207
|
+
|
|
208
|
+
var npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
209
|
+
var npmRoots = collectCommandOutputLines(npmCommand, ['root', '-g']);
|
|
210
|
+
for (var n = 0; n < npmRoots.length; n++) {
|
|
211
|
+
pushUniquePath(roots, npmRoots[n]);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
var openclawLocator = process.platform === 'win32' ? 'where' : 'which';
|
|
215
|
+
var openclawBins = collectCommandOutputLines(openclawLocator, ['openclaw']);
|
|
216
|
+
for (var b = 0; b < openclawBins.length; b++) {
|
|
217
|
+
var binPath = openclawBins[b];
|
|
218
|
+
try {
|
|
219
|
+
pushUniquePath(roots, path.join(path.dirname(binPath), '..', 'lib', 'node_modules'));
|
|
220
|
+
} catch (e) {}
|
|
221
|
+
try {
|
|
222
|
+
var realBin = fs.realpathSync(binPath);
|
|
223
|
+
var needle = path.join('node_modules', 'openclaw');
|
|
224
|
+
var idx = realBin.lastIndexOf(needle);
|
|
225
|
+
if (idx >= 0) {
|
|
226
|
+
pushUniquePath(roots, realBin.substring(0, idx + 'node_modules'.length));
|
|
227
|
+
}
|
|
228
|
+
} catch (e) {}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return roots;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function addGlobalOpenclawTargets(deployTargets, assetTargets) {
|
|
235
|
+
var roots = collectGlobalNodeModuleRoots();
|
|
236
|
+
for (var i = 0; i < roots.length; i++) {
|
|
237
|
+
var root = roots[i];
|
|
238
|
+
pushUniquePath(deployTargets, path.join(root, 'openclaw', 'dist', 'control-ui', 'openagent-override.js'));
|
|
239
|
+
pushUniquePath(deployTargets, path.join(root, 'openclaw-openagent', 'src', 'plugin-ui', 'assets', 'openagent-override.js'));
|
|
240
|
+
pushUniquePath(deployTargets, path.join(root, 'openclaw-openagent', 'dist', 'src', 'plugin-ui', 'assets', 'openagent-override.js'));
|
|
241
|
+
|
|
242
|
+
pushUniquePath(assetTargets, path.join(root, 'openclaw', 'dist', 'control-ui'));
|
|
243
|
+
pushUniquePath(assetTargets, path.join(root, 'openclaw-openagent', 'src', 'plugin-ui', 'assets'));
|
|
244
|
+
pushUniquePath(assetTargets, path.join(root, 'openclaw-openagent', 'dist', 'src', 'plugin-ui', 'assets'));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function updateControlUiIndex(controlUiDir, contentHash, hostVersion) {
|
|
249
|
+
var indexPath = path.join(controlUiDir, 'index.html');
|
|
250
|
+
if (!fs.existsSync(indexPath)) return false;
|
|
251
|
+
|
|
252
|
+
var html = fs.readFileSync(indexPath, 'utf-8');
|
|
253
|
+
var htmlMarker = '<!--openagent:html-script-tag-->';
|
|
254
|
+
var hostVersionAttr = hostVersion ? ' data-openagent-host-version="' + hostVersion + '"' : '';
|
|
255
|
+
var scriptTag = htmlMarker + '<script src="./openagent-override.js?v=' + contentHash + '"' + hostVersionAttr + '></script>';
|
|
256
|
+
var markedScriptPattern = /(?:\/\*openagent:html-script-tag\*\/|<!--openagent:html-script-tag-->)<script[^>]*openagent-override[^>]*><\/script>\n?\s*/g;
|
|
257
|
+
var oldScriptPattern = /<script[^>]*openagent-override[^>]*><\/script>\n?\s*/g;
|
|
258
|
+
var nextHtml;
|
|
259
|
+
|
|
260
|
+
if (/(?:\/\*openagent:html-script-tag\*\/|<!--openagent:html-script-tag-->)/.test(html)) {
|
|
261
|
+
nextHtml = html.replace(markedScriptPattern, scriptTag + '\n ');
|
|
262
|
+
if (nextHtml === html && !nextHtml.includes('openagent-override.js')) {
|
|
263
|
+
nextHtml = nextHtml.replace(/(?:\/\*openagent:html-script-tag\*\/|<!--openagent:html-script-tag-->)/, scriptTag + '\n ');
|
|
264
|
+
} else if (nextHtml === html && nextHtml.includes('openagent-override.js')) {
|
|
265
|
+
nextHtml = nextHtml.replace(oldScriptPattern, '').replace(/(?:\/\*openagent:html-script-tag\*\/|<!--openagent:html-script-tag-->)/, scriptTag + '\n ');
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
nextHtml = html.replace(oldScriptPattern, '');
|
|
269
|
+
var viteAnchor = '<script type="module" crossorigin src="./assets/index-';
|
|
270
|
+
var anchorIdx = nextHtml.indexOf(viteAnchor);
|
|
271
|
+
if (anchorIdx >= 0) {
|
|
272
|
+
nextHtml = nextHtml.substring(0, anchorIdx) + scriptTag + '\n ' + nextHtml.substring(anchorIdx);
|
|
273
|
+
} else {
|
|
274
|
+
nextHtml = nextHtml.replace('</head>', scriptTag + '\n</head>');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (nextHtml && nextHtml !== html) {
|
|
279
|
+
fs.writeFileSync(indexPath, nextHtml, 'utf-8');
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
62
284
|
|
|
63
285
|
const HEADER = `/**
|
|
64
286
|
* OpenAgent UI Override — Auto-generated, do not edit directly!
|
|
@@ -99,6 +321,12 @@ function build() {
|
|
|
99
321
|
body += `// MODULE: ${file}\n`;
|
|
100
322
|
body += `// ════════════════════════════════════════════════════════════════\n\n`;
|
|
101
323
|
body += content.trimEnd() + '\n';
|
|
324
|
+
if (file === 'loader/shared-state.js') {
|
|
325
|
+
body += `\n// ════════════════════════════════════════════════════════════════\n`;
|
|
326
|
+
body += `// MODULE: host-adapter/selected\n`;
|
|
327
|
+
body += `// ════════════════════════════════════════════════════════════════\n\n`;
|
|
328
|
+
body += getHostAdapterBlock('') + '\n';
|
|
329
|
+
}
|
|
102
330
|
}
|
|
103
331
|
|
|
104
332
|
if (errors > 0) {
|
|
@@ -107,12 +335,15 @@ function build() {
|
|
|
107
335
|
return;
|
|
108
336
|
}
|
|
109
337
|
|
|
110
|
-
|
|
338
|
+
// ── 不做构建时版本注入,由运行时 DOM/CSS 特征检测 ──
|
|
339
|
+
// (build.cjs 无法知道实际运行的 OpenClaw 版本)
|
|
340
|
+
var output = HEADER + body + FOOTER;
|
|
341
|
+
var assetOutput = renderOverrideContent(output, '');
|
|
111
342
|
|
|
112
343
|
fs.mkdirSync(path.dirname(outFile), { recursive: true });
|
|
113
|
-
fs.writeFileSync(outFile,
|
|
344
|
+
fs.writeFileSync(outFile, assetOutput, 'utf-8');
|
|
114
345
|
|
|
115
|
-
const lineCount =
|
|
346
|
+
const lineCount = assetOutput.split('\n').length;
|
|
116
347
|
console.log(`✅ Built: ${path.relative(process.cwd(), outFile)} (${lineCount} lines)`);
|
|
117
348
|
|
|
118
349
|
// ── Auto-deploy to runtime targets ──────────────────────────────────────
|
|
@@ -123,25 +354,38 @@ function build() {
|
|
|
123
354
|
|
|
124
355
|
const DEPLOY_TARGETS = [
|
|
125
356
|
// 插件安装目录(Gateway 启动时从这里读取并复制到 control-ui)
|
|
126
|
-
// 注意:安装目录仍使用旧路径 src/inject/,下次 npm publish 后才会变
|
|
127
357
|
path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/inject/assets/openagent-override.js'),
|
|
128
358
|
path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
|
|
129
359
|
path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/inject/assets/openagent-override.js'),
|
|
130
360
|
path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
|
|
361
|
+
// 本地开发 dist/ 目录
|
|
362
|
+
path.join(__dirname, '..', '..', 'dist', 'src', 'plugin-ui', 'assets', 'openagent-override.js'),
|
|
363
|
+
// 本地 node_modules 中的 openclaw control-ui(Gateway 实际运行路径)
|
|
364
|
+
path.join(__dirname, '..', '..', 'node_modules', 'openclaw', 'dist', 'control-ui', 'openagent-override.js'),
|
|
365
|
+
// npm 全局安装 + 项目缓存(Gateway 可能从这些路径加载)
|
|
366
|
+
path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
|
|
367
|
+
path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/dist/src/plugin-ui/assets/openagent-override.js'),
|
|
368
|
+
path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/src/plugin-ui/assets/openagent-override.js'),
|
|
369
|
+
path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/dist/src/plugin-ui/assets/openagent-override.js'),
|
|
131
370
|
];
|
|
132
|
-
|
|
133
|
-
// 动态发现 control-ui 目录(通过 node 可执行文件路径推断)
|
|
134
|
-
try {
|
|
135
|
-
const nodeDir = path.dirname(process.execPath);
|
|
136
|
-
const controlUiCandidate = path.join(nodeDir, '..', 'lib', 'node_modules', 'openclaw', 'dist', 'control-ui', 'openagent-override.js');
|
|
137
|
-
DEPLOY_TARGETS.push(path.resolve(controlUiCandidate));
|
|
138
|
-
} catch {}
|
|
371
|
+
addGlobalOpenclawTargets(DEPLOY_TARGETS, null);
|
|
139
372
|
|
|
140
373
|
let deployed = 0;
|
|
141
374
|
for (const target of DEPLOY_TARGETS) {
|
|
142
375
|
try {
|
|
143
376
|
if (fs.existsSync(path.dirname(target))) {
|
|
144
|
-
|
|
377
|
+
const targetDir = path.dirname(target);
|
|
378
|
+
const hostVersion = path.basename(targetDir) === 'control-ui'
|
|
379
|
+
? resolveControlUiHostVersion(targetDir)
|
|
380
|
+
: '';
|
|
381
|
+
const targetOutput = renderOverrideContent(output, hostVersion);
|
|
382
|
+
fs.writeFileSync(target, targetOutput, 'utf-8');
|
|
383
|
+
if (hostVersion) {
|
|
384
|
+
const contentHash = hashContent(targetOutput);
|
|
385
|
+
if (updateControlUiIndex(targetDir, contentHash, hostVersion)) {
|
|
386
|
+
console.log(` ↻ updated index.html cache-bust (${hostVersion}, ${resolveHostAdapterId(hostVersion)}, ${contentHash})`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
145
389
|
console.log(` → ${path.relative(homedir, target)}`);
|
|
146
390
|
deployed++;
|
|
147
391
|
}
|
|
@@ -149,10 +393,48 @@ function build() {
|
|
|
149
393
|
}
|
|
150
394
|
|
|
151
395
|
if (deployed > 0) {
|
|
152
|
-
console.log(`✅ Auto-deployed to ${deployed} target(s)`);
|
|
396
|
+
console.log(`✅ Auto-deployed override to ${deployed} target(s)`);
|
|
153
397
|
} else {
|
|
154
398
|
console.log('ℹ️ No deploy targets found (standalone build)');
|
|
155
399
|
}
|
|
400
|
+
|
|
401
|
+
// ── Shared asset deploy targets (control-ui + extension dirs) ──
|
|
402
|
+
const ASSET_DEPLOY_TARGETS = [
|
|
403
|
+
path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/inject/assets'),
|
|
404
|
+
path.join(homedir, '.openclaw-docker/extensions/openclaw-openagent/src/plugin-ui/assets'),
|
|
405
|
+
path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/inject/assets'),
|
|
406
|
+
path.join(homedir, '.openclaw/extensions/openclaw-openagent/src/plugin-ui/assets'),
|
|
407
|
+
path.join(__dirname, '..', '..', 'dist', 'src', 'plugin-ui', 'assets'),
|
|
408
|
+
path.join(__dirname, '..', '..', 'node_modules', 'openclaw', 'dist', 'control-ui'),
|
|
409
|
+
path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/src/plugin-ui/assets'),
|
|
410
|
+
path.join(homedir, '.openclaw/npm/projects/openclaw-openagent/node_modules/openclaw-openagent/dist/src/plugin-ui/assets'),
|
|
411
|
+
path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/src/plugin-ui/assets'),
|
|
412
|
+
path.join(homedir, '.nvm/versions/node/v22.21.1/lib/node_modules/openclaw-openagent/dist/src/plugin-ui/assets'),
|
|
413
|
+
];
|
|
414
|
+
addGlobalOpenclawTargets(null, ASSET_DEPLOY_TARGETS);
|
|
415
|
+
|
|
416
|
+
// ── Deploy image assets (icon.png, bg.png) ──
|
|
417
|
+
const IMAGE_ASSETS = [
|
|
418
|
+
{ file: iconFile, name: 'icon.png' },
|
|
419
|
+
{ file: bgFile, name: 'bg.png' },
|
|
420
|
+
];
|
|
421
|
+
|
|
422
|
+
for (const asset of IMAGE_ASSETS) {
|
|
423
|
+
if (!fs.existsSync(asset.file)) continue;
|
|
424
|
+
let deployed = 0;
|
|
425
|
+
for (const dir of ASSET_DEPLOY_TARGETS) {
|
|
426
|
+
try {
|
|
427
|
+
const dest = path.join(dir, asset.name);
|
|
428
|
+
if (fs.existsSync(dir)) {
|
|
429
|
+
fs.copyFileSync(asset.file, dest);
|
|
430
|
+
deployed++;
|
|
431
|
+
}
|
|
432
|
+
} catch {}
|
|
433
|
+
}
|
|
434
|
+
if (deployed > 0) {
|
|
435
|
+
console.log(`✅ Auto-deployed ${asset.name} to ${deployed} target(s)`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
156
438
|
}
|
|
157
439
|
|
|
158
440
|
// ── Execution ──
|
|
@@ -162,16 +444,20 @@ const isWatchMode = process.argv.includes('--watch');
|
|
|
162
444
|
build();
|
|
163
445
|
|
|
164
446
|
if (isWatchMode) {
|
|
165
|
-
console.log(`\n👀 Watching for changes in ${path.relative(process.cwd(), modulesDir)}...`);
|
|
447
|
+
console.log(`\n👀 Watching for changes in ${path.relative(process.cwd(), modulesDir)} and ${path.relative(process.cwd(), adaptersDir)}...`);
|
|
166
448
|
|
|
167
449
|
let debounceTimer;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
450
|
+
function watchSourceDir(sourceDir) {
|
|
451
|
+
fs.watch(sourceDir, { recursive: true }, (eventType, filename) => {
|
|
452
|
+
// Ignore dot files and non-js files
|
|
453
|
+
if (!filename || filename.startsWith('.') || !filename.endsWith('.js')) return;
|
|
171
454
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
455
|
+
clearTimeout(debounceTimer);
|
|
456
|
+
debounceTimer = setTimeout(() => {
|
|
457
|
+
build();
|
|
458
|
+
}, 100);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
watchSourceDir(modulesDir);
|
|
462
|
+
watchSourceDir(adaptersDir);
|
|
177
463
|
}
|
package/src/plugin-ui/index.ts
CHANGED
|
@@ -13,6 +13,6 @@ import { loadUIExtensions } from './ui-extension-loader/index.js';
|
|
|
13
13
|
* 由 index.ts register() 调用。内部通过 Manifest Reconciler
|
|
14
14
|
* 自动完成扩展点的 apply / revert / skip。
|
|
15
15
|
*/
|
|
16
|
-
export async function injectControlUiOverride(): Promise<void> {
|
|
17
|
-
await loadUIExtensions();
|
|
16
|
+
export async function injectControlUiOverride(hostVersion?: string): Promise<void> {
|
|
17
|
+
await loadUIExtensions({ hostVersion });
|
|
18
18
|
}
|