nemo-relay-openclaw 0.0.0 → 0.3.0-beta.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.
Files changed (45) hide show
  1. package/README.md +262 -4
  2. package/dist/index.d.ts +8 -0
  3. package/dist/index.js +20 -0
  4. package/dist/openclaw.plugin.json +154 -0
  5. package/dist/src/config.d.ts +329 -0
  6. package/dist/src/config.js +185 -0
  7. package/dist/src/health.d.ts +48 -0
  8. package/dist/src/health.js +63 -0
  9. package/dist/src/hook-replay/correlation.d.ts +34 -0
  10. package/dist/src/hook-replay/correlation.js +40 -0
  11. package/dist/src/hook-replay/llm.d.ts +52 -0
  12. package/dist/src/hook-replay/llm.js +1060 -0
  13. package/dist/src/hook-replay/marks.d.ts +30 -0
  14. package/dist/src/hook-replay/marks.js +109 -0
  15. package/dist/src/hook-replay/session.d.ts +157 -0
  16. package/dist/src/hook-replay/session.js +204 -0
  17. package/dist/src/hook-replay/tool.d.ts +12 -0
  18. package/dist/src/hook-replay/tool.js +101 -0
  19. package/dist/src/hooks-backend.d.ts +94 -0
  20. package/dist/src/hooks-backend.js +321 -0
  21. package/dist/src/modules.d.ts +42 -0
  22. package/dist/src/modules.js +15 -0
  23. package/dist/src/openclaw-hook-types.d.ts +186 -0
  24. package/dist/src/openclaw-hook-types.js +3 -0
  25. package/dist/src/runtime-state.d.ts +66 -0
  26. package/dist/src/runtime-state.js +420 -0
  27. package/dist/src/types.d.ts +27 -0
  28. package/dist/src/types.js +3 -0
  29. package/index.ts +23 -0
  30. package/openclaw.plugin.json +154 -0
  31. package/package.json +62 -24
  32. package/src/config.ts +251 -0
  33. package/src/health.ts +116 -0
  34. package/src/hook-replay/correlation.ts +75 -0
  35. package/src/hook-replay/llm.ts +1302 -0
  36. package/src/hook-replay/marks.ts +141 -0
  37. package/src/hook-replay/session.ts +396 -0
  38. package/src/hook-replay/tool.ts +142 -0
  39. package/src/hooks-backend.ts +457 -0
  40. package/src/modules.ts +79 -0
  41. package/src/openclaw-hook-types.ts +211 -0
  42. package/src/runtime-state.ts +553 -0
  43. package/src/types.ts +34 -0
  44. package/index.d.ts +0 -2
  45. package/index.js +0 -15
package/README.md CHANGED
@@ -5,8 +5,266 @@ SPDX-License-Identifier: Apache-2.0
5
5
 
6
6
  # nemo-relay-openclaw
7
7
 
8
- This is a temporary stub release used to reserve the `nemo-relay-openclaw` package
9
- name for NeMo Relay.
8
+ `nemo-relay-openclaw` is the NeMo Relay observability plugin package for
9
+ OpenClaw. It converts supported OpenClaw hook events into NeMo Relay sessions,
10
+ LLM spans, tool spans, and lifecycle marks that the generic NeMo Relay
11
+ observability component can export as ATIF JSON, OpenTelemetry spans, and
12
+ OpenInference/Phoenix spans. The same generic plugin config path can initialize
13
+ Adaptive components for hook-backed telemetry learning.
10
14
 
11
- Do not depend on version `0.0.0` for runtime behavior. Use a later
12
- release from https://github.com/NVIDIA/NeMo-Relay.
15
+ This public OpenClaw plugin package uses OpenClaw public hooks. It does not
16
+ rewrite OpenClaw tool execution, provider routing, policy decisions, or model
17
+ requests. For middleware-backed behavior that changes execution, use the
18
+ patch-based OpenClaw integration from the NeMo Relay repository.
19
+
20
+ ## Why Use It?
21
+
22
+ - Observe OpenClaw sessions without patching OpenClaw.
23
+ - Export OpenClaw activity into NeMo Relay observability formats.
24
+ - Preserve OpenClaw's agent, tool, and LLM lifecycle context where public hooks
25
+ expose enough data.
26
+ - Keep ambiguous LLM timing attribution visible through diagnostic marks instead
27
+ of unsafe latency.
28
+
29
+ ## What You Get
30
+
31
+ - OpenClaw plugin ID `nemo-relay`.
32
+ - Generic NeMo Relay plugin initialization through `config.plugins`.
33
+ - ATIF JSON export through the built-in `observability` component.
34
+ - Adaptive plugin initialization through `config.plugins`.
35
+ - Optional OpenTelemetry OTLP export.
36
+ - Optional OpenInference/Phoenix OTLP export.
37
+ - Bounded LLM replay correlation across supported OpenClaw hooks.
38
+ - Tool span replay with conservative privacy defaults.
39
+ - Admin-scoped `nemoRelay.status` gateway health method.
40
+
41
+ ## Installation
42
+
43
+ Install the package directly in a Node.js/OpenClaw environment:
44
+
45
+ ```bash
46
+ npm install nemo-relay-openclaw
47
+ ```
48
+
49
+ For OpenClaw-managed installation, use the OpenClaw CLI:
50
+
51
+ ```bash
52
+ openclaw plugins install npm:nemo-relay-openclaw
53
+ openclaw gateway restart
54
+ ```
55
+
56
+ OpenClaw uses the package `nemo-relay-openclaw` for installation and the plugin
57
+ manifest ID `nemo-relay` for configuration.
58
+
59
+ ## Configure the Plugin
60
+
61
+ Enable the `nemo-relay` plugin ID, grant conversation hook access, and place the
62
+ OpenClaw plugin configuration under `plugins.entries["nemo-relay"].config`:
63
+
64
+ ```json
65
+ {
66
+ "plugins": {
67
+ "allow": ["nemo-relay"],
68
+ "entries": {
69
+ "nemo-relay": {
70
+ "enabled": true,
71
+ "hooks": {
72
+ "allowConversationAccess": true
73
+ },
74
+ "config": {
75
+ "enabled": true,
76
+ "backend": "hooks",
77
+ "plugins": {
78
+ "version": 1,
79
+ "components": [
80
+ {
81
+ "kind": "observability",
82
+ "enabled": true,
83
+ "config": {
84
+ "version": 1,
85
+ "atif": {
86
+ "enabled": true,
87
+ "agent_name": "openclaw",
88
+ "output_directory": "./nemo-relay-atif"
89
+ },
90
+ "opentelemetry": {
91
+ "enabled": false,
92
+ "transport": "http_binary",
93
+ "endpoint": "http://localhost:4318/v1/traces",
94
+ "service_name": "openclaw-nemo-relay"
95
+ },
96
+ "openinference": {
97
+ "enabled": false,
98
+ "transport": "http_binary",
99
+ "endpoint": "http://localhost:6006/v1/traces",
100
+ "service_name": "openclaw-nemo-relay"
101
+ }
102
+ }
103
+ },
104
+ {
105
+ "kind": "adaptive",
106
+ "enabled": true,
107
+ "config": {
108
+ "version": 1,
109
+ "agent_id": "openclaw",
110
+ "state": {
111
+ "backend": {
112
+ "kind": "in_memory",
113
+ "config": {}
114
+ }
115
+ },
116
+ "telemetry": {
117
+ "learners": ["tool_parallelism"]
118
+ }
119
+ }
120
+ }
121
+ ]
122
+ },
123
+ "capture": {
124
+ "includePrompts": true,
125
+ "includeResponses": true,
126
+ "stripToolArgs": true,
127
+ "stripToolResults": true
128
+ },
129
+ "correlation": {
130
+ "llmOutputGraceMs": 250,
131
+ "recordTtlMs": 600000,
132
+ "maxRecordsPerKey": 32
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ This example enables local ATIF export and leaves OTLP exporters disabled until
142
+ you point them at a collector or Phoenix endpoint. Remove exporter sections you
143
+ do not use, or set their `enabled` fields to `false`.
144
+
145
+ - `plugins.allow` controls OpenClaw plugin trust and loading.
146
+ - `plugins.entries["nemo-relay"].enabled` controls whether OpenClaw starts this
147
+ plugin entry.
148
+ - `hooks.allowConversationAccess` lets trusted non-bundled plugins receive
149
+ conversation-sensitive hook payloads such as LLM prompts, LLM responses,
150
+ agent finalization messages, and tool payloads.
151
+ - `config.enabled` disables or enables the NeMo Relay OpenClaw wrapper without
152
+ removing the plugin entry. `config.backend` currently supports only `hooks`.
153
+ - `config.plugins` is the generic NeMo Relay plugin configuration document. Use
154
+ this object to configure built-in components such as `observability` and
155
+ `adaptive`.
156
+ - `config.plugins.components[].config.atif` writes ATIF trajectory JSON files.
157
+ Set `output_directory` to the directory where OpenClaw should write files.
158
+ - `config.plugins.components[].config.opentelemetry` sends generic OTLP spans to
159
+ an OpenTelemetry collector when `enabled` is `true`.
160
+ - `config.plugins.components[].config.openinference` sends OpenInference OTLP
161
+ spans to Phoenix or another OpenInference-compatible collector when `enabled`
162
+ is `true`.
163
+ - `config.plugins.components[]` entries with `kind: "adaptive"` initialize the
164
+ Adaptive plugin. In hook-backed OpenClaw mode, adaptive telemetry can consume
165
+ replayed NeMo Relay events, while request-rewrite features such as adaptive
166
+ hints require a managed execution path.
167
+ - `config.capture` controls prompt, response, tool argument, and tool result
168
+ capture. Tool arguments and tool results are stripped by default because they
169
+ often contain user data, local paths, tokens, or large payloads.
170
+ - `config.correlation` controls bounded in-memory hook correlation. By default,
171
+ the plugin waits 250 ms for a matching `llm_input` after an `llm_output`,
172
+ keeps correlation records for 600 seconds, and keeps at most 32 records per
173
+ correlation key.
174
+
175
+ Fields inside `config.plugins` are NeMo Relay generic plugin configuration, so
176
+ they use `snake_case` regardless of language. For the full exporter field list,
177
+ see the NeMo Relay Observability Plugin schema in the top-level NeMo Relay
178
+ documentation at [nvidia.github.io/NeMo-Relay](https://nvidia.github.io/NeMo-Relay/).
179
+
180
+ ## Verify the Integration
181
+
182
+ Inspect the plugin runtime:
183
+
184
+ ```bash
185
+ openclaw plugins inspect nemo-relay --runtime --json
186
+ ```
187
+
188
+ Run an OpenClaw session with the plugin enabled, then verify the configured
189
+ sink:
190
+
191
+ - ATIF: confirm JSON files appear in the configured
192
+ `config.plugins.components[].config.atif.output_directory`.
193
+ - OpenTelemetry: confirm spans arrive at the configured OTLP collector.
194
+ - OpenInference: confirm spans arrive at the configured OpenInference/Phoenix
195
+ endpoint.
196
+
197
+ The plugin also registers the `operator.admin` scoped gateway method
198
+ `nemoRelay.status`. If your CLI is already paired with admin-capable gateway
199
+ access, run:
200
+
201
+ ```bash
202
+ openclaw gateway call nemoRelay.status --json
203
+ ```
204
+
205
+ ## Current Limits
206
+
207
+ The plugin maps supported OpenClaw hook events into NeMo Relay telemetry without
208
+ changing OpenClaw execution behavior.
209
+
210
+ It does not change OpenClaw tool execution, provider routing, policy decisions,
211
+ or provider request payloads.
212
+
213
+ Current OpenClaw public hooks expose request, response, message-write, and
214
+ provider timing details through separate event streams. The plugin correlates
215
+ those events within the same session, provider, model, and run. When timing
216
+ cannot be paired safely, it emits diagnostic marks instead of inventing
217
+ latency.
218
+
219
+ ## Troubleshooting
220
+
221
+ If the plugin does not load, verify the package was installed with
222
+ `openclaw plugins install`, `plugins.allow` includes `nemo-relay`,
223
+ `plugins.entries["nemo-relay"].enabled` is not disabled, and the gateway was
224
+ restarted after configuration changes.
225
+
226
+ If conversation payloads are missing, verify
227
+ `hooks.allowConversationAccess` is enabled for the plugin and the OpenClaw
228
+ session emits the relevant LLM, message-write, and tool hooks.
229
+
230
+ If no export output appears, verify
231
+ `config.plugins.components[].config.atif.output_directory`,
232
+ `config.plugins.components[].config.opentelemetry.endpoint`, or
233
+ `config.plugins.components[].config.openinference.endpoint`, then confirm the
234
+ configured collector or output directory is reachable.
235
+
236
+ ## Development
237
+
238
+ Run these commands from the repository root:
239
+
240
+ ```bash
241
+ npm ci --ignore-scripts
242
+ npm run build --workspace=nemo-relay-openclaw
243
+ npm run typecheck --workspace=nemo-relay-openclaw
244
+ npm test --workspace=nemo-relay-openclaw
245
+ ```
246
+
247
+ The CI-equivalent repo recipe is:
248
+
249
+ ```bash
250
+ just --set ci true test-openclaw
251
+ ```
252
+
253
+ Check the package payload before changing package metadata or entrypoints:
254
+
255
+ ```bash
256
+ npm run pack:check --workspace=nemo-relay-openclaw
257
+ ```
258
+
259
+ `npm run build --workspace=nemo-relay-openclaw` emits production files under
260
+ `integrations/openclaw/dist/`. Tests compile to
261
+ `integrations/openclaw/.test-dist/` from the sibling
262
+ `integrations/openclaw/test/` directory so test artifacts do not enter the
263
+ installable package or production source tree.
264
+
265
+ The optional live smoke test requires a working installed `nemo-relay-node`
266
+ binding:
267
+
268
+ ```bash
269
+ npm run test:live --workspace=nemo-relay-openclaw
270
+ ```
@@ -0,0 +1,8 @@
1
+ declare const _default: {
2
+ id: string;
3
+ name: string;
4
+ description: string;
5
+ configSchema: import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginConfigSchema;
6
+ register: NonNullable<import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginDefinition["register"]>;
7
+ } & Pick<import("openclaw/plugin-sdk/plugin-entry").OpenClawPluginDefinition, "kind" | "reload" | "nodeHostCommands" | "securityAuditCollectors">;
8
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * OpenClaw plugin entry point.
5
+ *
6
+ * This file should stay small: it declares the public plugin metadata and hands
7
+ * registration to the runtime-state module, where lifecycle and hook wiring live.
8
+ */
9
+ import { definePluginEntry } from 'openclaw/plugin-sdk/plugin-entry';
10
+ import { nemoRelayConfigSchema } from './src/config.js';
11
+ import { registerNemoRelayPlugin } from './src/runtime-state.js';
12
+ export default definePluginEntry({
13
+ id: 'nemo-relay',
14
+ name: 'NeMo Relay Observability',
15
+ description: 'ATIF, OpenInference, and OpenTelemetry telemetry through NeMo Relay',
16
+ configSchema: nemoRelayConfigSchema,
17
+ register(api) {
18
+ registerNemoRelayPlugin(api);
19
+ },
20
+ });
@@ -0,0 +1,154 @@
1
+ {
2
+ "id": "nemo-relay",
3
+ "name": "NeMo Relay Observability",
4
+ "description": "ATIF, OpenInference, and OpenTelemetry telemetry through NeMo Relay.",
5
+ "activation": {
6
+ "onStartup": true
7
+ },
8
+ "contracts": {
9
+ "agentToolCallMiddleware": ["pi"]
10
+ },
11
+ "configSchema": {
12
+ "type": "object",
13
+ "additionalProperties": false,
14
+ "properties": {
15
+ "enabled": {
16
+ "type": "boolean",
17
+ "default": true,
18
+ "description": "Enables the NeMo Relay OpenClaw hook replay plugin."
19
+ },
20
+ "backend": {
21
+ "type": "string",
22
+ "enum": ["hooks"],
23
+ "default": "hooks",
24
+ "description": "Hook replay backend implementation. Only the hook-backed backend is supported."
25
+ },
26
+ "plugins": {
27
+ "$ref": "#/$defs/nemoRelayPluginConfig",
28
+ "description": "Generic NeMo Relay plugin configuration document. Use the observability component to configure ATIF, OpenTelemetry, and OpenInference exporters."
29
+ },
30
+ "capture": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "properties": {
34
+ "includePrompts": {
35
+ "type": "boolean",
36
+ "default": true,
37
+ "description": "Includes LLM prompt text in replayed telemetry when true."
38
+ },
39
+ "includeResponses": {
40
+ "type": "boolean",
41
+ "default": true,
42
+ "description": "Includes LLM response text in replayed telemetry when true."
43
+ },
44
+ "stripToolArgs": {
45
+ "type": "boolean",
46
+ "default": true,
47
+ "description": "Strips tool arguments from replayed tool spans by default."
48
+ },
49
+ "stripToolResults": {
50
+ "type": "boolean",
51
+ "default": true,
52
+ "description": "Strips tool results from replayed tool spans by default."
53
+ }
54
+ },
55
+ "description": "Controls sensitive payload capture for replayed LLM and tool telemetry."
56
+ },
57
+ "correlation": {
58
+ "type": "object",
59
+ "additionalProperties": false,
60
+ "properties": {
61
+ "llmOutputGraceMs": {
62
+ "type": "integer",
63
+ "minimum": 0,
64
+ "default": 250,
65
+ "description": "Milliseconds to wait for a matching llm_input before replaying an llm_output with a placeholder request."
66
+ },
67
+ "recordTtlMs": {
68
+ "type": "integer",
69
+ "minimum": 0,
70
+ "default": 600000,
71
+ "description": "Maximum age in milliseconds for buffered correlation records."
72
+ },
73
+ "maxRecordsPerKey": {
74
+ "type": "integer",
75
+ "minimum": 1,
76
+ "default": 32,
77
+ "description": "Maximum buffered records per correlation key."
78
+ }
79
+ },
80
+ "description": "Bounded correlation settings for matching OpenClaw hook events into replay spans."
81
+ }
82
+ },
83
+ "$defs": {
84
+ "nemoRelayPluginConfig": {
85
+ "type": "object",
86
+ "additionalProperties": true,
87
+ "properties": {
88
+ "version": {
89
+ "type": "integer",
90
+ "default": 1,
91
+ "description": "NeMo Relay generic plugin config version."
92
+ },
93
+ "components": {
94
+ "type": "array",
95
+ "items": {
96
+ "$ref": "#/$defs/pluginComponent"
97
+ },
98
+ "default": [],
99
+ "description": "NeMo Relay plugin components to validate and initialize."
100
+ },
101
+ "policy": {
102
+ "$ref": "#/$defs/pluginPolicy",
103
+ "description": "Policy for unknown or unsupported plugin configuration."
104
+ }
105
+ },
106
+ "default": {
107
+ "version": 1,
108
+ "components": []
109
+ }
110
+ },
111
+ "pluginComponent": {
112
+ "type": "object",
113
+ "required": ["kind"],
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "kind": {
117
+ "type": "string",
118
+ "description": "Registered NeMo Relay plugin kind."
119
+ },
120
+ "enabled": {
121
+ "type": "boolean",
122
+ "default": true,
123
+ "description": "Whether this component should be initialized."
124
+ },
125
+ "config": {
126
+ "type": "object",
127
+ "additionalProperties": true,
128
+ "description": "Component-local plugin configuration."
129
+ }
130
+ }
131
+ },
132
+ "pluginPolicy": {
133
+ "type": "object",
134
+ "additionalProperties": false,
135
+ "properties": {
136
+ "unknown_component": {
137
+ "$ref": "#/$defs/unsupportedBehavior"
138
+ },
139
+ "unknown_field": {
140
+ "$ref": "#/$defs/unsupportedBehavior"
141
+ },
142
+ "unsupported_value": {
143
+ "$ref": "#/$defs/unsupportedBehavior"
144
+ }
145
+ }
146
+ },
147
+ "unsupportedBehavior": {
148
+ "type": "string",
149
+ "enum": ["ignore", "warn", "error"]
150
+ }
151
+ },
152
+ "description": "Configuration for the NeMo Relay OpenClaw hook replay plugin."
153
+ }
154
+ }