nemo-relay-openclaw 0.8.4 → 0.9.0-rc.2
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/src/modules.d.ts +2 -1
- package/dist/src/runtime-state.d.ts +1 -1
- package/dist/src/runtime-state.js +20 -14
- package/package.json +13 -7
- package/src/modules.ts +2 -1
- package/src/runtime-state.ts +21 -14
package/dist/src/modules.d.ts
CHANGED
|
@@ -8,10 +8,11 @@ import type * as NemoRelayRuntime from 'nemo-relay-node';
|
|
|
8
8
|
import type * as NemoRelayAdaptive from 'nemo-relay-node/adaptive';
|
|
9
9
|
import type * as NemoRelayPluginHost from 'nemo-relay-node/plugin';
|
|
10
10
|
type NemoRelayRuntimeKeys = 'ScopeType' | 'createScopeStack' | 'currentScopeStack' | 'setThreadScopeStack' | 'pushScope' | 'popScope' | 'event' | 'llmCall' | 'llmCallEnd' | 'toolCall' | 'toolCallEnd' | 'toolConditionalExecution';
|
|
11
|
-
type NemoRelayPluginHostKeys = 'defaultConfig' | 'validate' | 'initialize'
|
|
11
|
+
type NemoRelayPluginHostKeys = 'defaultConfig' | 'validate' | 'initialize';
|
|
12
12
|
type NemoRelayAdaptiveKeys = 'ADAPTIVE_PLUGIN_KIND' | 'ComponentSpec';
|
|
13
13
|
export type ConfigDiagnostic = NemoRelayPluginHost.ConfigDiagnostic;
|
|
14
14
|
export type ConfigReport = NemoRelayPluginHost.ConfigReport;
|
|
15
|
+
export type PluginHostActivation = NemoRelayPluginHost.PluginHostActivation;
|
|
15
16
|
/**
|
|
16
17
|
* @internal Package-owned subset of the dynamically imported `nemo-relay-node`
|
|
17
18
|
* namespace used by this integration.
|
|
@@ -19,7 +19,7 @@ export declare class NemoRelayRuntimeState {
|
|
|
19
19
|
private loadPromise;
|
|
20
20
|
private startPromise;
|
|
21
21
|
private statusValue;
|
|
22
|
-
private
|
|
22
|
+
private pluginHostActivation;
|
|
23
23
|
private backendValue;
|
|
24
24
|
private initializedPluginHost;
|
|
25
25
|
private pluginHostOutputsHealthy;
|
|
@@ -15,7 +15,7 @@ export class NemoRelayRuntimeState {
|
|
|
15
15
|
loadPromise;
|
|
16
16
|
startPromise;
|
|
17
17
|
statusValue = { state: 'not_initialized' };
|
|
18
|
-
|
|
18
|
+
pluginHostActivation;
|
|
19
19
|
backendValue;
|
|
20
20
|
initializedPluginHost = false;
|
|
21
21
|
pluginHostOutputsHealthy = false;
|
|
@@ -79,7 +79,6 @@ export class NemoRelayRuntimeState {
|
|
|
79
79
|
try {
|
|
80
80
|
this.loadPromise ??= this.moduleLoader();
|
|
81
81
|
modules = await this.loadPromise;
|
|
82
|
-
this.modulesValue = modules;
|
|
83
82
|
}
|
|
84
83
|
catch (error) {
|
|
85
84
|
this.loadPromise = undefined;
|
|
@@ -97,19 +96,20 @@ export class NemoRelayRuntimeState {
|
|
|
97
96
|
degradedReason = validationReport.reason;
|
|
98
97
|
ctx.logger.warn?.(degradedReason);
|
|
99
98
|
}
|
|
100
|
-
else if (validationReport.report.diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
|
|
99
|
+
else if (validationReport.report.config.diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
|
|
101
100
|
degradedReason = 'NeMo Relay plugin host config validation failed';
|
|
102
101
|
}
|
|
103
102
|
else {
|
|
104
|
-
if (validationReport.report.diagnostics.some((diagnostic) => diagnostic.level === 'warning') &&
|
|
103
|
+
if (validationReport.report.config.diagnostics.some((diagnostic) => diagnostic.level === 'warning') &&
|
|
105
104
|
degradedReason === undefined) {
|
|
106
105
|
degradedReason = 'NeMo Relay plugin host config validation produced warnings';
|
|
107
106
|
}
|
|
108
107
|
try {
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
this.pluginHostActivation = await modules.pluginHost.initialize(hostConfig);
|
|
109
|
+
const activationDiagnostics = this.pluginHostActivation.report.config.diagnostics;
|
|
110
|
+
logDiagnostics(ctx.logger, activationDiagnostics);
|
|
111
111
|
this.initializedPluginHost = true;
|
|
112
|
-
const hasInitializationErrors =
|
|
112
|
+
const hasInitializationErrors = activationDiagnostics.some((diagnostic) => diagnostic.level === 'error');
|
|
113
113
|
this.pluginHostOutputsHealthy = !hasInitializationErrors;
|
|
114
114
|
if (hasInitializationErrors) {
|
|
115
115
|
degradedReason ??= 'NeMo Relay plugin host initialization reported errors';
|
|
@@ -175,18 +175,24 @@ export class NemoRelayRuntimeState {
|
|
|
175
175
|
this.lastCounters = { ...backendState.counters };
|
|
176
176
|
}
|
|
177
177
|
this.backendValue = undefined;
|
|
178
|
-
|
|
178
|
+
let pluginHostCloseFailure;
|
|
179
|
+
if (this.pluginHostActivation) {
|
|
179
180
|
try {
|
|
180
|
-
this.
|
|
181
|
+
await this.pluginHostActivation.close();
|
|
181
182
|
}
|
|
182
183
|
catch (error) {
|
|
183
|
-
|
|
184
|
+
pluginHostCloseFailure = `failed to close NeMo Relay plugin host: ${toMessage(error)}`;
|
|
185
|
+
log.warn?.(pluginHostCloseFailure);
|
|
186
|
+
}
|
|
187
|
+
if (pluginHostCloseFailure === undefined) {
|
|
188
|
+
this.pluginHostActivation = undefined;
|
|
189
|
+
this.initializedPluginHost = false;
|
|
190
|
+
this.pluginHostOutputsHealthy = false;
|
|
184
191
|
}
|
|
185
|
-
this.initializedPluginHost = false;
|
|
186
|
-
this.pluginHostOutputsHealthy = false;
|
|
187
192
|
}
|
|
188
193
|
this.started = false;
|
|
189
|
-
this.statusValue =
|
|
194
|
+
this.statusValue =
|
|
195
|
+
pluginHostCloseFailure === undefined ? finalStatus : { state: 'degraded', reason: pluginHostCloseFailure };
|
|
190
196
|
}
|
|
191
197
|
/** Handle OpenClaw runtime lifecycle cleanup for either a session or the backend. */
|
|
192
198
|
async cleanup(ctx) {
|
|
@@ -381,7 +387,7 @@ function registerToolCallMiddleware(api, runtime) {
|
|
|
381
387
|
function validatePluginHostConfig(modules, config, logger) {
|
|
382
388
|
try {
|
|
383
389
|
const report = modules.pluginHost.validate(config);
|
|
384
|
-
logDiagnostics(logger, report.diagnostics);
|
|
390
|
+
logDiagnostics(logger, report.config.diagnostics);
|
|
385
391
|
return { ok: true, report };
|
|
386
392
|
}
|
|
387
393
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nemo-relay-openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0-rc.2",
|
|
4
4
|
"description": "NeMo Relay-authored observability plugin for OpenClaw.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
"./dist/index.js"
|
|
43
43
|
],
|
|
44
44
|
"compat": {
|
|
45
|
-
"pluginApi": ">=2026.
|
|
46
|
-
"minGatewayVersion": "2026.
|
|
45
|
+
"pluginApi": ">=2026.9.3",
|
|
46
|
+
"minGatewayVersion": "2026.9.3"
|
|
47
47
|
},
|
|
48
48
|
"build": {
|
|
49
|
-
"openclawVersion": "2026.
|
|
50
|
-
"pluginSdkVersion": "2026.
|
|
49
|
+
"openclawVersion": "2026.9.3",
|
|
50
|
+
"pluginSdkVersion": "2026.9.3"
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
@@ -60,13 +60,19 @@
|
|
|
60
60
|
"test:live": "npm run build:test && node scripts/test-live.mjs"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"openclaw": "2026.
|
|
63
|
+
"openclaw": "2026.9.3"
|
|
64
|
+
},
|
|
65
|
+
"peerDependenciesMeta": {
|
|
66
|
+
"openclaw": {
|
|
67
|
+
"optional": true
|
|
68
|
+
}
|
|
64
69
|
},
|
|
65
70
|
"dependencies": {
|
|
66
|
-
"nemo-relay-node": "0.
|
|
71
|
+
"nemo-relay-node": "0.9.0-rc.2"
|
|
67
72
|
},
|
|
68
73
|
"devDependencies": {
|
|
69
74
|
"@types/node": "^24.0.0",
|
|
75
|
+
"openclaw": "2026.9.3",
|
|
70
76
|
"typescript": "^5.8.2"
|
|
71
77
|
},
|
|
72
78
|
"license": "Apache-2.0"
|
package/src/modules.ts
CHANGED
|
@@ -25,11 +25,12 @@ type NemoRelayRuntimeKeys =
|
|
|
25
25
|
| 'toolCallEnd'
|
|
26
26
|
| 'toolConditionalExecution';
|
|
27
27
|
|
|
28
|
-
type NemoRelayPluginHostKeys = 'defaultConfig' | 'validate' | 'initialize'
|
|
28
|
+
type NemoRelayPluginHostKeys = 'defaultConfig' | 'validate' | 'initialize';
|
|
29
29
|
type NemoRelayAdaptiveKeys = 'ADAPTIVE_PLUGIN_KIND' | 'ComponentSpec';
|
|
30
30
|
|
|
31
31
|
export type ConfigDiagnostic = NemoRelayPluginHost.ConfigDiagnostic;
|
|
32
32
|
export type ConfigReport = NemoRelayPluginHost.ConfigReport;
|
|
33
|
+
export type PluginHostActivation = NemoRelayPluginHost.PluginHostActivation;
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* @internal Package-owned subset of the dynamically imported `nemo-relay-node`
|
package/src/runtime-state.ts
CHANGED
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
type ConfigDiagnostic,
|
|
27
27
|
type NemoRelayModules,
|
|
28
28
|
type NemoRelayModuleLoader,
|
|
29
|
+
type PluginHostActivation,
|
|
29
30
|
} from './modules.js';
|
|
30
31
|
import type { RuntimeStateOptions, StartContext } from './types.js';
|
|
31
32
|
|
|
@@ -52,7 +53,7 @@ export class NemoRelayRuntimeState {
|
|
|
52
53
|
private loadPromise: Promise<NemoRelayModules> | undefined;
|
|
53
54
|
private startPromise: Promise<void> | undefined;
|
|
54
55
|
private statusValue: HookReplayBackendStatus = { state: 'not_initialized' };
|
|
55
|
-
private
|
|
56
|
+
private pluginHostActivation: PluginHostActivation | undefined;
|
|
56
57
|
private backendValue: HookReplayBackend | undefined;
|
|
57
58
|
private initializedPluginHost = false;
|
|
58
59
|
private pluginHostOutputsHealthy = false;
|
|
@@ -124,7 +125,6 @@ export class NemoRelayRuntimeState {
|
|
|
124
125
|
try {
|
|
125
126
|
this.loadPromise ??= this.moduleLoader();
|
|
126
127
|
modules = await this.loadPromise;
|
|
127
|
-
this.modulesValue = modules;
|
|
128
128
|
} catch (error) {
|
|
129
129
|
this.loadPromise = undefined;
|
|
130
130
|
this.statusValue = { state: 'degraded', reason: `failed to load nemo-relay-node: ${toMessage(error)}` };
|
|
@@ -143,21 +143,22 @@ export class NemoRelayRuntimeState {
|
|
|
143
143
|
if (!validationReport.ok) {
|
|
144
144
|
degradedReason = validationReport.reason;
|
|
145
145
|
ctx.logger.warn?.(degradedReason);
|
|
146
|
-
} else if (validationReport.report.diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
|
|
146
|
+
} else if (validationReport.report.config.diagnostics.some((diagnostic) => diagnostic.level === 'error')) {
|
|
147
147
|
degradedReason = 'NeMo Relay plugin host config validation failed';
|
|
148
148
|
} else {
|
|
149
149
|
if (
|
|
150
|
-
validationReport.report.diagnostics.some((diagnostic) => diagnostic.level === 'warning') &&
|
|
150
|
+
validationReport.report.config.diagnostics.some((diagnostic) => diagnostic.level === 'warning') &&
|
|
151
151
|
degradedReason === undefined
|
|
152
152
|
) {
|
|
153
153
|
degradedReason = 'NeMo Relay plugin host config validation produced warnings';
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
157
|
+
this.pluginHostActivation = await modules.pluginHost.initialize(hostConfig);
|
|
158
|
+
const activationDiagnostics = this.pluginHostActivation.report.config.diagnostics;
|
|
159
|
+
logDiagnostics(ctx.logger, activationDiagnostics);
|
|
159
160
|
this.initializedPluginHost = true;
|
|
160
|
-
const hasInitializationErrors =
|
|
161
|
+
const hasInitializationErrors = activationDiagnostics.some((diagnostic) => diagnostic.level === 'error');
|
|
161
162
|
this.pluginHostOutputsHealthy = !hasInitializationErrors;
|
|
162
163
|
if (hasInitializationErrors) {
|
|
163
164
|
degradedReason ??= 'NeMo Relay plugin host initialization reported errors';
|
|
@@ -238,18 +239,24 @@ export class NemoRelayRuntimeState {
|
|
|
238
239
|
}
|
|
239
240
|
this.backendValue = undefined;
|
|
240
241
|
|
|
241
|
-
|
|
242
|
+
let pluginHostCloseFailure: string | undefined;
|
|
243
|
+
if (this.pluginHostActivation) {
|
|
242
244
|
try {
|
|
243
|
-
this.
|
|
245
|
+
await this.pluginHostActivation.close();
|
|
244
246
|
} catch (error) {
|
|
245
|
-
|
|
247
|
+
pluginHostCloseFailure = `failed to close NeMo Relay plugin host: ${toMessage(error)}`;
|
|
248
|
+
log.warn?.(pluginHostCloseFailure);
|
|
249
|
+
}
|
|
250
|
+
if (pluginHostCloseFailure === undefined) {
|
|
251
|
+
this.pluginHostActivation = undefined;
|
|
252
|
+
this.initializedPluginHost = false;
|
|
253
|
+
this.pluginHostOutputsHealthy = false;
|
|
246
254
|
}
|
|
247
|
-
this.initializedPluginHost = false;
|
|
248
|
-
this.pluginHostOutputsHealthy = false;
|
|
249
255
|
}
|
|
250
256
|
|
|
251
257
|
this.started = false;
|
|
252
|
-
this.statusValue =
|
|
258
|
+
this.statusValue =
|
|
259
|
+
pluginHostCloseFailure === undefined ? finalStatus : { state: 'degraded', reason: pluginHostCloseFailure };
|
|
253
260
|
}
|
|
254
261
|
|
|
255
262
|
/** Handle OpenClaw runtime lifecycle cleanup for either a session or the backend. */
|
|
@@ -513,7 +520,7 @@ function validatePluginHostConfig(
|
|
|
513
520
|
): { ok: true; report: ReturnType<NemoRelayModules['pluginHost']['validate']> } | { ok: false; reason: string } {
|
|
514
521
|
try {
|
|
515
522
|
const report = modules.pluginHost.validate(config);
|
|
516
|
-
logDiagnostics(logger, report.diagnostics);
|
|
523
|
+
logDiagnostics(logger, report.config.diagnostics);
|
|
517
524
|
return { ok: true, report };
|
|
518
525
|
} catch (error) {
|
|
519
526
|
return {
|