Skip to content

feat: add OpenClaw observability plugin#67

Open
mnajafian-nv wants to merge 20 commits intoNVIDIA:mainfrom
mnajafian-nv:feat/openclaw-hooks-observability-plugin
Open

feat: add OpenClaw observability plugin#67
mnajafian-nv wants to merge 20 commits intoNVIDIA:mainfrom
mnajafian-nv:feat/openclaw-hooks-observability-plugin

Conversation

@mnajafian-nv
Copy link
Copy Markdown
Contributor

@mnajafian-nv mnajafian-nv commented May 7, 2026

Overview

Adds a NeMo Flow-owned OpenClaw integration package under integrations/openclaw/. The plugin uses existing OpenClaw plugin hooks and NeMo Flow manual lifecycle APIs to emit ATIF, OpenTelemetry, and OpenInference telemetry without applying OpenClaw source patches.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Adds the standalone OpenClaw plugin manifest, package shell, config schema, and lazy nemo-flow-node loading.
  • Implements hook-backed session scope management, safe replay, ATIF capture/export, OTel/OpenInference subscriber lifecycle, and status reporting.
  • Replays OpenClaw LLM hooks through llmCall/llmCallEnd with bounded FIFO correlation, placeholder replay, timing enrichment, and ambiguity handling.
  • Replays successful tool calls through toolCall/toolCallEnd; blocked tools emit mark events instead of fake successful spans.
  • Keeps privacy-safe defaults by stripping tool args/results and supporting prompt/response capture controls.
  • Adds unit tests plus an opt-in live smoke test for real local nemo-flow-node bindings.

Validation recorded for this PR:

  • npm --prefix integrations/openclaw run typecheck
  • npm --prefix integrations/openclaw test
  • npm --prefix integrations/openclaw run test:live
  • git diff --check upstream/main..HEAD
  • uv run pre-commit run --all-files

Where should the reviewer start?

Start with integrations/openclaw/src/runtime-state.ts for plugin lifecycle, then integrations/openclaw/src/hooks-backend.ts for hook dispatch, and integrations/openclaw/src/hook-replay/llm.ts / tool.ts for replay behavior.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

Closes: NMF-9

Summary by CodeRabbit

  • New Features

    • NeMo Flow Observability plugin for OpenClaw: captures LLM/tool telemetry, replays to OTEL/OpenInference, and provides health/status snapshots.
    • ATIF session export with configurable output, safe filenames, and capture options (strip prompts, args, results) plus bounded correlation controls and replay semantics.
    • Runtime lifecycle: lazy module loading, registration, shutdown, and gateway status.
  • Packaging

    • Plugin package and manifest added for distribution and automatic activation.
  • Tests

    • Comprehensive unit and integration test suites covering capture, replay, telemetry shutdown, failure modes, and live smoke tests.

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv mnajafian-nv added this to the 0.2.0 milestone May 7, 2026
@mnajafian-nv mnajafian-nv self-assigned this May 7, 2026
@mnajafian-nv mnajafian-nv requested review from a team as code owners May 7, 2026 07:49
@mnajafian-nv mnajafian-nv added feat PR introduces new feature or functionality lang:js PR changes/introduces Javascript/Typescript code size:XXL PR is very large labels May 7, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds a new OpenClaw integration package (@nvidia/nemo-flow-openclaw) that implements NeMo Flow observability: configuration schema and parsing, runtime/module loader, hook replay (LLM/tool) with session/correlation and ATIF export, telemetry subscriber registration/shutdown, health snapshots, runtime lifecycle and extensive tests.

Changes

Hook Event & Type Contracts

Layer / File(s) Summary
Hook Event Types
integrations/openclaw/src/openclaw-hook-types.ts
Exports hook event/context type definitions for agent, tool, session, LLM, model call, subagent, and gateway lifecycle events.

Runtime & Module Interfaces

Layer / File(s) Summary
Runtime Types
integrations/openclaw/src/types.ts, integrations/openclaw/src/modules.ts
Runtime-state types and constrained module/runtime/plugin-host type views plus defaultNemoFlowModuleLoader.

Configuration & Manifest

Layer / File(s) Summary
Config Schema & Parsing
integrations/openclaw/openclaw.plugin.json, integrations/openclaw/src/config.ts
Adds plugin manifest with configSchema, type definitions, DEFAULT_CONFIG, parseConfig() and nemoFlowConfigSchema.safeParse().
Package & Build
integrations/openclaw/package.json, integrations/openclaw/tsconfig.json, .gitignore
New package metadata, TS config, build/test scripts, and .gitignore entry to exclude dist/.

Health & Status

Layer / File(s) Summary
Health Reporting
integrations/openclaw/src/health.ts
Adds health types and createHealthSnapshot() that reports backend status, per-output health, counters, and lastError.

Session, Correlation & Marks

Layer / File(s) Summary
Session & State
integrations/openclaw/src/hook-replay/session.ts
Session state, session manager, key resolution/aliasing, ensureSession/drain/closeSessionRoot, bounded maps and TTL eviction.
Correlation Keys
integrations/openclaw/src/hook-replay/correlation.ts
tupleKey/llmKey/modelTimingKey, evictExpiredRecords, nowMicros, startMicrosFromDuration.
Marks & JSON
integrations/openclaw/src/hook-replay/marks.ts
emitMark(), blockedToolDetails(), toJsonRecord/value(), errorToJson() with circular handling.

LLM & Tool Replay

Layer / File(s) Summary
LLM Replay
integrations/openclaw/src/hook-replay/llm.ts
recordLlmInput/Output, modelCallStarted/Ended, pending-output grace-timer replay, buildReplayLlmRequest/Response, timing correlation and ambiguity handling.
Tool Replay
integrations/openclaw/src/hook-replay/tool.ts
replayAfterToolCall() with blocked-tool detection, conditional stripping of args/results, and nf.toolCall/toolCallEnd replay.

ATIF Capture & Export

Layer / File(s) Summary
ATIF
integrations/openclaw/src/atif-capture.ts
createAtifExporter(), withAtifCapture(), exportAtifJson(), makeSafeSessionId(), and exporter cleanup with degraded-output tracking.

Hook Replay Backend

Layer / File(s) Summary
Backend
integrations/openclaw/src/hooks-backend.ts
HookReplayBackend class implementing all hook handlers, safeReplay wrappers, session lifecycle management, ATIF export on close, counters and public helpers (resolveBackendSessionKey, llmKey re-export).

Telemetry Lifecycle

Layer / File(s) Summary
Telemetry
integrations/openclaw/src/telemetry.ts
registerTelemetrySubscribers() and shutdownTelemetrySubscribers() with degraded-output marking and safe cleanup semantics.

Runtime Lifecycle & Plugin Registration

Layer / File(s) Summary
Runtime State & Registration
integrations/openclaw/src/runtime-state.ts, integrations/openclaw/index.ts
NemoFlowRuntimeState manages module loading, plugin host validation/initialization, telemetry and backend construction, hook wiring, status/health and idempotent shutdown; registerNemoFlowPlugin() entrypoint and plugin entry export.

Tests

Layer / File(s) Summary
Tests
integrations/openclaw/src/__tests__/*
Extensive test suites covering config behavior, hook backend, LLM/tool replay semantics, ATIF capture/export, telemetry shutdown failure scenarios, replay failure model, and an optional live smoke test.

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integrations/openclaw/openclaw.plugin.json`:
- Around line 25-28: The manifest's schema advertises incorrect defaults and a
too-generic otlpSubscriber shape: update the "pluginConfig" default to match the
runtime-normalized NemoFlow config (set default to an object equivalent to {
version: 1, components: [] } for nemoFlow.pluginConfig) and adjust the shared
"otlpSubscriber" definition to allow distinct "instrumentationScope"
defaults/variants for OTEL vs OpenInference (or split into two subscriber
schemas) so the manifest's public contract exactly matches runtime normalization
and supports different instrumentationScope defaults used by OpenInference and
OTEL.

In `@integrations/openclaw/package.json`:
- Around line 30-32: The peerDependency for openclaw in package.json is
currently the unbounded "*", which allows incompatible major versions; update
the peerDependencies entry for "openclaw" to a bounded range such as
">=2026.5.0" (or ">=2026.3.22" if you need older stable support) instead of "*"
in integrations/openclaw/package.json so the plugin-SDK only advertises
compatibility with tested OpenClaw releases; after changing the "openclaw" entry
run your package manager's install and a quick test suite to verify
compatibility.

In `@integrations/openclaw/src/__tests__/config.test.ts`:
- Around line 349-357: The test "does not statically import nemo-flow-node or
OpenClaw private src paths" only reads modules.js and index.js; update it to
scan the entire integration source tree (all files under the package src and
top-level built files) instead of only "../modules.js" and "../../index.js".
Replace the current readFileSync-based files aggregation with a recursive
glob/readDir that reads every .ts/.js (and compiled .js) file in the package
(e.g., all files under the src directory and top-level index/modules artifacts),
then run the same assert.doesNotMatch checks (/from ['"]nemo-flow-node/, /from
['"]nemo-flow-node\/plugin/, /openclaw\/src\//) against that aggregated content
so imports in runtime-state.ts, hooks-backend.ts, hook-replay/*, etc. are also
caught.

In `@integrations/openclaw/src/__tests__/live-smoke.test.ts`:
- Around line 172-193: The helper loadRealNemoFlowModules reimplements the
dynamic import logic; instead import and call the exported loader
defaultNemoFlowModuleLoader (from src/modules.ts) and only wrap that call to
translate the missing-package error into the custom message. Replace the manual
Promise.all import block in loadRealNemoFlowModules with a call to await
defaultNemoFlowModuleLoader(), and in the catch keep the
isMissingLocalNemoFlowNode(error) check to throw the existing user-friendly
message, otherwise rethrow the original error; return the loader result cast to
NemoFlowModules["nf"] and ["pluginHost"] as before.

In `@integrations/openclaw/src/config.ts`:
- Around line 258-266: The asRecord function currently treats null as an object
because typeof null === "object"; update asRecord (function name: asRecord) to
explicitly reject null by checking value !== null (e.g., require value !== null
&& typeof value === "object" && !Array.isArray(value)) so null is not returned
as a Record<string, unknown>; keep the existing optional handling (value ===
undefined && optional) and throw the same error message `${path} must be an
object` when the value is null or not an object.

In `@integrations/openclaw/src/hook-replay/correlation.ts`:
- Around line 26-36: llmKey and modelTimingLlmKey currently return the same
tupleKey([sessionId, runId, provider, model]); decide whether they are
intentionally identical: if so, replace the duplicate function implementation by
exporting modelTimingLlmKey as an alias to llmKey (export const
modelTimingLlmKey = llmKey) and add a one-line comment explaining the alias; if
they should differ, update modelTimingLlmKey to construct the correct tuple via
tupleKey with the intended fields (inspect ModelTimingKeyInput vs LlmKeyInput)
so it no longer duplicates llmKey; refer to the functions llmKey,
modelTimingLlmKey and helper tupleKey when making the change.

In `@integrations/openclaw/src/hook-replay/llm.ts`:
- Around line 335-351: The ensureSession call in replayLlmOutput is missing
ctx.sessionKey which prevents proper session alias registration when sessionKey
differs from sessionId; update the ensureSession invocation inside
replayLlmOutput to pass sessionKey: ctx.sessionKey (mirroring recordLlmInput and
other callers) so the session alias is registered correctly for that
manager/session.

In `@integrations/openclaw/src/hook-replay/tool.ts`:
- Line 22: The blocked-tool metadata uses ctx.runId unconditionally; change the
call to blockedToolDetails to supply the same runId fallback used elsewhere by
passing the event runId first and falling back to ctx.runId (i.e., use
event.runId with ctx.runId as fallback) so blocked marks retain event.runId when
present; update the call to blockedToolDetails(event, { runId: ... })
accordingly.

In `@integrations/openclaw/src/modules.ts`:
- Around line 1-2: Replace the leading line-comment SPDX headers with C-style
block comments in integrations/openclaw/src/modules.ts (and all new sibling .ts
files in this PR); specifically, change the two lines beginning with "//
SPDX-FileCopyrightText" and "// SPDX-License-Identifier" to a single or two
C-style comment(s) using /* ... */ so they follow the repo policy for SPDX
headers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: d34a5cdc-41c0-4945-ac0a-ab3ca4dca2e1

📥 Commits

Reviewing files that changed from the base of the PR and between 7744e0a and 115ea38.

⛔ Files ignored due to path filters (1)
  • integrations/openclaw/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (28)
  • .gitignore
  • integrations/openclaw/index.ts
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/package.json
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/tsconfig.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (13)
**/{integrations,integration,*-integration}/**

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

**/{integrations,integration,*-integration}/**: Keep NeMo Flow optional in framework integrations
Preserve the framework's original behavior when NeMo Flow is absent
Wrap tool and LLM paths at the correct framework boundary
Integration pattern must follow docs/integrate-frameworks/adding-scopes.md

Files:

  • integrations/openclaw/tsconfig.json
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/index.ts
  • integrations/openclaw/package.json
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,yaml,yml,toml,json,md,txt}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • integrations/openclaw/tsconfig.json
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/index.ts
  • integrations/openclaw/package.json
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use camelCase naming convention for Node.js code

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{rs,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license headers in all Rust, Go, JavaScript, and TypeScript source files using C-style comment syntax

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use SONAR_IGNORE_START / SONAR_IGNORE_END markers only for documented false positives that cannot be resolved in code; keep ignored blocks small, add explanatory comments, and require reviewer sign-off

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{md,markdown,py,sh,bash,js,ts,java,cpp,go,rust}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current in documentation

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{md,markdown,py,sh,bash,js,ts,example}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Example commands must match current package names and paths

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
{crates/adaptive/**,python/nemo_flow/{adaptive,plugin}.py,go/nemo_flow/{adaptive,**}/*.go,**/*.{ts,js,wasm}}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive config schema, plugin lifecycle, and bindings in sync across crates/adaptive, core, bindings, Python (python/nemo_flow/adaptive.py and python/nemo_flow/plugin.py), Go (go/nemo_flow/adaptive and go/nemo_flow), and Node/WebAssembly helpers

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{rs,py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{rs,py,go,js,ts,jsx,tsx}: Format changed files with the language-native formatter before the final lint/test pass
Use language-native formatters: cargo fmt --all for Rust, uv run ruff format python for Python, go fmt ./... for Go, npm --prefix crates/node run format for Node.js, and npm --prefix crates/node run precommit:format -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts for WebAssembly

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/*.{js,ts,tsx,jsx,py,rs,go,java,c,cpp,h,cc,cxx,cs,rb,php,swift,kt}

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changed files must be formatted with the language-native formatter

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/index.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/health.ts
  • integrations/openclaw/src/openclaw-plugin-entry.d.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/atif-capture.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/openclaw-hook-types.ts
  • integrations/openclaw/src/hook-replay/session.ts
**/package.json

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency in Node package metadata in crates/node/package.json

Files:

  • integrations/openclaw/package.json
**/{config,schema,adaptive}.{yaml,yml,json,ts,tsx,py,go,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure dynamic config shape matches the documented canonical model in docs/use-adaptive-optimization/configure.md

Files:

  • integrations/openclaw/src/config.ts
🧠 Learnings (1)
📚 Learning: 2026-04-15T18:16:52.951Z
Learnt from: bbednarski9
Repo: NVIDIA/NeMo-Flow PR: 1
File: docs/atof-event-format.md:381-381
Timestamp: 2026-04-15T18:16:52.951Z
Learning: In docs/atof-event-format.md (and when reviewing references to this format across the NeMo-Flow repo), treat `AtifExporter.events_to_steps()` as the intended public/API method name. Do not flag it as inconsistent with internal Rust symbol names (e.g., `event_to_steps` in `crates/core/src/atif.rs`)—the documentation’s public-facing naming may differ intentionally from internal implementation details.

Applied to files:

  • .gitignore
🔇 Additional comments (26)
.gitignore (1)

30-30: Good ignore rule for integration build output.

This correctly prevents checked-in artifacts from integrations/openclaw/dist/.

integrations/openclaw/tsconfig.json (1)

2-24: Compiler configuration looks solid for strict, declaration-emitting builds.

strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes is a good baseline for this integration surface.

integrations/openclaw/src/__tests__/telemetry.test.ts (1)

11-54: Nice failure-path coverage for telemetry shutdown sequencing.

These tests explicitly lock in “continue cleanup even on partial failure,” which is the right reliability behavior.

integrations/openclaw/src/__tests__/failure-model.test.ts (1)

13-43: Good regression test for async replay-failure containment.

This correctly verifies both counter mutation and bounded warning behavior when llmCall throws in delayed replay.

integrations/openclaw/src/__tests__/atif-capture.test.ts (1)

21-167: ATIF failure-mode coverage is comprehensive and practical.

The suite locks in non-blocking behavior across constructor/register/deregister/export/clear failures with solid state assertions.

integrations/openclaw/src/__tests__/tool-replay.test.ts (1)

13-107: Tool replay tests validate the key safety and behavior contracts.

Nice coverage of default redaction, opt-in raw payloads, and blocked-tool mark-only replay.

integrations/openclaw/src/telemetry.ts (1)

1-127: LGTM!

Clean implementation of telemetry subscriber lifecycle management. Error handling is thorough with graceful degradation: registration failures mark outputs degraded and attempt best-effort cleanup, and shutdown handles each phase (deregister/flush/shutdown) independently with appropriate warnings.

integrations/openclaw/src/__tests__/llm-replay.test.ts (1)

1-530: LGTM!

Comprehensive test coverage for LLM replay scenarios: input/output correlation, grace window handling, placeholder requests, timing attachment, privacy capture controls, and TTL eviction. The test at line 352 correctly verifies that eviction clears pending timers.

integrations/openclaw/src/runtime-state.ts (1)

1-436: LGTM!

Well-structured plugin lifecycle management:

  • Proper double-start/stop guards with state machine transitions
  • Graceful degradation on module load, config validation, and telemetry initialization failures
  • Clean hook dispatch pattern with safe replay wrappers
  • beforeExit listener properly registered/removed with cleanup

The integration correctly preserves OpenClaw's original behavior when NeMo Flow is absent (Lines 354-371).

integrations/openclaw/src/hook-replay/marks.ts (1)

1-113: LGTM!

Correct JSON normalization with circular reference detection. The WeakSet-based approach properly handles both true circular references (marked as "[Circular]") and legitimate multiple references to the same object by removing from seen after processing each branch.

integrations/openclaw/src/hooks-backend.ts (1)

1-394: LGTM!

Solid backend implementation:

  • Safe replay wrappers catch errors and increment counters without crashing
  • Scope stack save/restore in emitCapturedUnderSession correctly uses try/finally
  • Session iteration in closeAllSessions spreads to array to avoid iterator invalidation during deletion
  • Bounded warning pattern in logBoundedWarn prevents log spam
integrations/openclaw/src/hook-replay/correlation.ts (1)

1-64: LGTM for the rest of the file.

Key generation normalizes empty strings to null for consistency. TTL eviction logic correctly filters expired records and cleans up empty map entries. Time helpers properly convert between milliseconds and microseconds.

integrations/openclaw/src/atif-capture.ts (1)

1-153: LGTM!

Robust ATIF capture lifecycle:

  • Re-entrancy guard at lines 45-48 prevents nested capture issues
  • Registration failures disable ATIF for the session but still execute the emit callback
  • Leaked registration detection (deregister returning false) properly disables ATIF to prevent duplicate subscribers
  • Export handles directory creation, write errors, and always cleans up the exporter in finally
integrations/openclaw/src/openclaw-plugin-entry.d.ts (1)

1-54: LGTM!

Ambient declarations correctly type the external modules. The loose Record<string, unknown> for nemo-flow-node accommodates dynamic module loading, and the plugin lifecycle types match their usage in runtime-state.ts and modules.ts.

integrations/openclaw/src/config.ts (1)

1-97: LGTM: Well-structured configuration module.

Type definitions are comprehensive, defaults are sensible (privacy-safe with stripToolArgs: true, stripToolResults: true), and the schema integration with OpenClawPluginConfigSchema is clean.

integrations/openclaw/src/hook-replay/llm.ts (4)

32-67: LGTM: Input recording with proper correlation.

The function correctly handles the input/output correlation dance: records input, checks for pending outputs, and replays when matched. Timer cleanup with clearPendingTimer prevents leaks.


69-115: LGTM: Output recording with grace timer.

Proper handling of out-of-order events with grace timer. timer.unref?.() ensures the timer doesn't prevent Node.js from exiting—good practice for background telemetry.


380-412: LGTM: Conservative timing selection.

Only consuming when exactly one candidate exists prevents incorrect timing attribution. The ambiguity mark emission is idempotent via the ambiguous flag.


500-509: LGTM: Message deduplication in appendPromptIfMissing.

Correctly avoids duplicating the user prompt if it already exists as the last message in history.

integrations/openclaw/src/hook-replay/session.ts (6)

1-47: LGTM: Clean type definitions for session state.

Types are well-structured with clear separation of concerns. The optional fields in SessionState.atif allow graceful degradation when ATIF export fails.


189-232: LGTM: Robust session creation with aliasing.

The double lookup (resolved key, then canonical sessionId) handles edge cases where alias registration is incomplete. createAtifExporter and openSessionRoot are appropriately deferred until first use.


234-239: LGTM: Proper session drain sequence.

Timer cancellation before replay prevents race conditions. The eviction after replay ensures no orphaned records remain.


241-257: LGTM: Clean scope teardown.

Idempotent with the rootHandle guard; scope is properly popped and handle cleared.


349-372: LGTM: Timer cleanup during TTL eviction.

Clearing timers on expired pending outputs prevents timer callbacks from firing for stale sessions.


263-275: LGTM: Bounded insertion with FIFO eviction.

The while loop is defensive against edge cases where multiple evictions are needed.

integrations/openclaw/src/openclaw-hook-types.ts (1)

1-177: LGTM: Comprehensive hook event types.

Well-structured type definitions with appropriate use of optional fields and union types for constrained values (e.g., outcome, failureKind, reason). The intersection type for PluginHookModelCallEndedEvent correctly extends PluginHookModelCallStartedEvent.

Comment thread integrations/openclaw/openclaw.plugin.json Outdated
Comment thread integrations/openclaw/package.json
Comment thread integrations/openclaw/src/__tests__/config.test.ts
Comment thread integrations/openclaw/src/__tests__/live-smoke.test.ts
Comment thread integrations/openclaw/src/config.ts
Comment thread integrations/openclaw/src/hook-replay/correlation.ts Outdated
Comment thread integrations/openclaw/src/hook-replay/llm.ts
Comment thread integrations/openclaw/src/hook-replay/tool.ts Outdated
Comment thread integrations/openclaw/src/modules.ts
Comment thread integrations/openclaw/package.json Outdated
Comment thread integrations/openclaw/package.json Outdated
Comment thread integrations/openclaw/openclaw.plugin.json
Comment thread integrations/openclaw/src/modules.ts Outdated
Comment thread integrations/openclaw/package.json Outdated
Comment thread integrations/openclaw/tsconfig.json Outdated
Comment thread integrations/openclaw/src/openclaw-plugin-entry.d.ts Outdated
Comment thread integrations/openclaw/src/types.ts
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file isn't necessary. You can obtain all of the types through:

import type {
  PluginHookAfterToolCallEvent,
  PluginHookToolContext,
  ...
} from "openclaw/plugins/hooks";

Copy link
Copy Markdown
Contributor Author

@mnajafian-nv mnajafian-nv May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this against the published package before changing it. openclaw@2026.5.6 exports ./plugin-sdk/plugin-entry, but it does not export ./plugins/hooks, so importing from openclaw/plugins/hooks does not resolve from the current npm package.

I also checked openclaw/plugin-sdk/hook-runtime; it is exported, but it does not export these hook event/context types. The hook declarations appear only under internal package paths, so I kept the local structural hook aliases for now and removed the other local type shims. Once OpenClaw publishes the hook types through a public subpath, this file can be replaced with package imports.

Co-authored-by: Will Killian <2007799+willkill07@users.noreply.github.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
integrations/openclaw/package.json (1)

30-32: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bound the openclaw peer range to avoid incompatible plugin-SDK upgrades.

Line 31 uses "*", which overstates compatibility and can pull breaking OpenClaw releases. Please set a tested minimum/compatible range (for example ">=2026.5.0 <2027" or your validated window).

What is the latest OpenClaw plugin SDK compatibility guidance for package.json peerDependencies and openclaw.compat.pluginApi fields, and what semver range is recommended for third-party plugins targeting current stable OpenClaw?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integrations/openclaw/package.json` around lines 30 - 32, The
peerDependencies entry currently uses a wildcard for "openclaw" which risks
pulling incompatible releases; update package.json's "peerDependencies" ->
"openclaw" to a bounded semver window you have tested (for example ">=2026.5.0
<2027") and also set the package's openclaw.compat.pluginApi field to the
matching plugin API range to reflect supported OpenClaw versions; ensure the
chosen range matches your validated compatibility window and update any
docs/tests that assert a specific OpenClaw version.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@integrations/openclaw/package.json`:
- Around line 30-32: The peerDependencies entry currently uses a wildcard for
"openclaw" which risks pulling incompatible releases; update package.json's
"peerDependencies" -> "openclaw" to a bounded semver window you have tested (for
example ">=2026.5.0 <2027") and also set the package's openclaw.compat.pluginApi
field to the matching plugin API range to reflect supported OpenClaw versions;
ensure the chosen range matches your validated compatibility window and update
any docs/tests that assert a specific OpenClaw version.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 55c3ae0f-cf57-4edd-a037-3c83059abda3

📥 Commits

Reviewing files that changed from the base of the PR and between 115ea38 and c48ea23.

📒 Files selected for processing (1)
  • integrations/openclaw/package.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/{integrations,integration,*-integration}/**

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

**/{integrations,integration,*-integration}/**: Keep NeMo Flow optional in framework integrations
Preserve the framework's original behavior when NeMo Flow is absent
Wrap tool and LLM paths at the correct framework boundary
Integration pattern must follow docs/integrate-frameworks/adding-scopes.md

Files:

  • integrations/openclaw/package.json
**/package.json

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency in Node package metadata in crates/node/package.json

Files:

  • integrations/openclaw/package.json
**/*.{rs,py,js,ts,tsx,jsx,go,sh,yaml,yml,toml,json,md,txt}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • integrations/openclaw/package.json

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Addressed review feedback in 97d9c18.

Summary:

  • Set package version to 0.2.0.
  • Bounded openclaw peer dependency to >=2026.5.6 and removed optional peer metadata.
  • Moved nemo-flow-node to required dependencies with >=0.1.0 <0.3.0; lockfile now resolves nemo-flow-node@0.1.0 from npm, not file:../../crates/node.
  • Added descriptions to manifest properties and split OTel/OpenInference subscriber defaults.
  • Removed tsconfig path shims and deleted openclaw-plugin-entry.d.ts.
  • Trimmed local plugin API/type shims and now use package-owned OpenClaw and NeMo Flow types.
  • Kept local OpenClaw hook structural aliases because openclaw@2026.5.6 exports ./plugin-sdk/plugin-entry but not ./plugins/hooks.

Validation:

  • npm --prefix integrations/openclaw run typecheck
  • npm --prefix integrations/openclaw test
  • npm --prefix integrations/openclaw run test:live
  • git diff --check upstream/main..HEAD
  • uv run pre-commit run --all-files

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integrations/openclaw/src/__tests__/failure-model.test.ts`:
- Around line 38-42: The test currently uses a fixed sleep (await delay(10))
which can race; replace it with bounded polling that repeatedly checks
backend.state().counters.replayErrors === 1 and logger.messages.warn has length
>= 1 (and that logger.messages.warn[0] matches /llm_output/) until a short
timeout (e.g., 1–2s) and fail if timeout reached. Implement this as a small
helper (e.g., waitFor or retryUntil) used in the test in place of delay, polling
at short intervals and throwing on timeout so the assertions are stable;
reference the existing symbols backend.state().counters.replayErrors,
logger.messages.warn, and the current regex /llm_output/ when writing the check.

In `@integrations/openclaw/src/hook-replay/marks.ts`:
- Around line 85-88: normalizeJsonValue currently returns number values as-is,
which lets NaN/Infinity/-Infinity through even though RFC 8259 disallows them;
modify normalizeJsonValue to detect numeric values and if Number.isFinite(value)
is false (covers NaN/Infinity/-Infinity) return null instead of the original
number so normalization matches JSON.stringify behavior and downstream NAPI
serialization; keep all other branches (strings, booleans, null, object handling
using seen WeakSet) unchanged.

In `@integrations/openclaw/src/telemetry.ts`:
- Around line 1-2: Replace the line-comments SPDX header at the top of
telemetry.ts with a C-style block comment; change the two leading `//
SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...` lines into a
single /* ... */ block containing both SPDX entries (so the file and sibling .ts
files comply with the repo policy); locate the header in
integrations/openclaw/src/telemetry.ts and update similarly in any other new .ts
files added in this PR.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: fdc9d16e-7def-4b1e-bd7f-e047558e0ce0

📥 Commits

Reviewing files that changed from the base of the PR and between c48ea23 and 97d9c18.

⛔ Files ignored due to path filters (1)
  • integrations/openclaw/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/package.json
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/config.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/tsconfig.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (13)
**/{integrations,integration,*-integration}/**

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

**/{integrations,integration,*-integration}/**: Keep NeMo Flow optional in framework integrations
Preserve the framework's original behavior when NeMo Flow is absent
Wrap tool and LLM paths at the correct framework boundary
Integration pattern must follow docs/integrate-frameworks/adding-scopes.md

Files:

  • integrations/openclaw/tsconfig.json
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/package.json
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,yaml,yml,toml,json,md,txt}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • integrations/openclaw/tsconfig.json
  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/openclaw.plugin.json
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/package.json
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use camelCase naming convention for Node.js code

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{rs,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license headers in all Rust, Go, JavaScript, and TypeScript source files using C-style comment syntax

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use SONAR_IGNORE_START / SONAR_IGNORE_END markers only for documented false positives that cannot be resolved in code; keep ignored blocks small, add explanatory comments, and require reviewer sign-off

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{md,markdown,py,sh,bash,js,ts,java,cpp,go,rust}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current in documentation

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{md,markdown,py,sh,bash,js,ts,example}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Example commands must match current package names and paths

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
{crates/adaptive/**,python/nemo_flow/{adaptive,plugin}.py,go/nemo_flow/{adaptive,**}/*.go,**/*.{ts,js,wasm}}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive config schema, plugin lifecycle, and bindings in sync across crates/adaptive, core, bindings, Python (python/nemo_flow/adaptive.py and python/nemo_flow/plugin.py), Go (go/nemo_flow/adaptive and go/nemo_flow), and Node/WebAssembly helpers

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{rs,py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{rs,py,go,js,ts,jsx,tsx}: Format changed files with the language-native formatter before the final lint/test pass
Use language-native formatters: cargo fmt --all for Rust, uv run ruff format python for Python, go fmt ./... for Go, npm --prefix crates/node run format for Node.js, and npm --prefix crates/node run precommit:format -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts for WebAssembly

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/*.{js,ts,tsx,jsx,py,rs,go,java,c,cpp,h,cc,cxx,cs,rb,php,swift,kt}

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changed files must be formatted with the language-native formatter

Files:

  • integrations/openclaw/src/hook-replay/tool.ts
  • integrations/openclaw/src/types.ts
  • integrations/openclaw/src/__tests__/telemetry.test.ts
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/tool-replay.test.ts
  • integrations/openclaw/src/telemetry.ts
  • integrations/openclaw/src/__tests__/live-smoke.test.ts
  • integrations/openclaw/src/modules.ts
  • integrations/openclaw/src/__tests__/llm-replay.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
  • integrations/openclaw/src/hook-replay/correlation.ts
  • integrations/openclaw/src/__tests__/config.test.ts
  • integrations/openclaw/src/runtime-state.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/__tests__/atif-capture.test.ts
  • integrations/openclaw/src/hook-replay/session.ts
  • integrations/openclaw/src/hooks-backend.ts
  • integrations/openclaw/src/hook-replay/llm.ts
  • integrations/openclaw/src/config.ts
**/package.json

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Maintain consistency in Node package metadata in crates/node/package.json

Files:

  • integrations/openclaw/package.json
**/{config,schema,adaptive}.{yaml,yml,json,ts,tsx,py,go,rs}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Ensure dynamic config shape matches the documented canonical model in docs/use-adaptive-optimization/configure.md

Files:

  • integrations/openclaw/src/config.ts
🔇 Additional comments (15)
integrations/openclaw/src/types.ts (1)

10-28: Type boundaries look clean and minimal.

These exported runtime-state types are scoped well to plugin/runtime contracts and keep ownership clear.

integrations/openclaw/tsconfig.json (1)

2-24: TS project configuration is solid for this package.

Strictness flags and NodeNext settings are consistent with the ESM build/test workflow.

integrations/openclaw/src/hook-replay/tool.ts (1)

22-81: Blocked-vs-success replay branching is correctly implemented.

The blocked-tool mark path and successful tool span path are cleanly separated, with consistent runId fallback handling.

integrations/openclaw/src/__tests__/telemetry.test.ts (1)

11-55: Failure-path shutdown coverage is strong here.

These cases validate continuation behavior and degraded-output marking across all subscriber lifecycle failure points.

integrations/openclaw/package.json (1)

7-39: Package entrypoints and scripts are consistently wired.

main/types/exports, dist file list, and build+test scripts align with this integration package layout.

integrations/openclaw/src/__tests__/tool-replay.test.ts (1)

12-108: Tool replay behavior coverage is comprehensive.

The suite exercises default redaction, trusted opt-in capture, null end payload behavior, and blocked-tool mark emission paths.

integrations/openclaw/src/__tests__/atif-capture.test.ts (1)

21-167: ATIF lifecycle failure-path coverage is well executed.

The cases around exporter construction/register/deregister/export/clear failures and safe session filename handling are thorough.

integrations/openclaw/src/__tests__/config.test.ts (1)

350-370: This guard still misses direct nemo-flow-node imports in .ts sources.

Reading only emitted .js leaves the optional-dependency invariant partially uncovered. A future static import added in src/runtime-state.ts, src/hooks-backend.ts, or src/hook-replay/* can bypass this test entirely if the workspace does not contain mirrored build output.

As per coding guidelines, "Keep NeMo Flow optional in framework integrations" and "Preserve the framework's original behavior when NeMo Flow is absent".

integrations/openclaw/src/modules.ts (1)

25-61: Avoid leaking optional nemo-flow-node types through exported declarations.

These exported aliases are built directly from nemo-flow-node / nemo-flow-node/plugin. If modules.ts is part of the published type surface, TypeScript consumers now need those optional packages present just to type-check, which breaks the integration’s “NeMo Flow optional” contract. Prefer local structural interfaces kept module-private, or define exported types without referencing the optional packages in emitted .d.ts.

#!/bin/bash
set -euo pipefail

echo "## Potential public entrypoints / package metadata"
fd -i 'package.json|index.ts|index.js|modules.ts|modules.js' integrations/openclaw -x sh -c '
  echo "### $1"
  sed -n "1,220p" "$1"
' sh {}

echo
echo "## References to exported module-surface types"
rg -n --glob 'integrations/openclaw/**' \
  'NemoFlow(RuntimeModule|PluginHostModule|Subscriber|Modules|ModuleLoader|AtifExporterLike)|from\s+["'\'']\.\.?/.*/modules\.js["'\'']|from\s+["'\'']\.\.?/.*/modules\.ts["'\'']'

As per coding guidelines, "Keep NeMo Flow optional in framework integrations" and "Preserve the framework's original behavior when NeMo Flow is absent".

integrations/openclaw/openclaw.plugin.json (1)

1-268: LGTM!

The manifest is well-structured with comprehensive JSON Schema definitions. Previous review concerns have been addressed: pluginConfig default now matches the runtime default ({ version: 1, components: [] }), separate subscriber schemas provide distinct instrumentationScope defaults for OTEL vs OpenInference, and all properties include descriptions.

integrations/openclaw/src/runtime-state.ts (1)

1-438: LGTM!

Well-structured runtime state management with proper idempotency, error handling, and lifecycle coordination. The beforeExit listener registration/cleanup, degraded state tracking, and safe replay wrappers are correctly implemented.

integrations/openclaw/src/hooks-backend.ts (1)

1-394: LGTM!

Clean session-scoped replay backend with proper error isolation via safeReplay/safeReplayAsync, bounded warning logging to prevent spam, and correct scope stack management in emitCapturedUnderSession. The delegation pattern to replay modules keeps this file focused on orchestration.

integrations/openclaw/src/hook-replay/session.ts (1)

1-377: LGTM!

Solid session state management with proper FIFO bounded record insertion, TTL-based eviction, and timer cleanup. The alias tracking and dual lookup in ensureSession correctly handles the various session key scenarios.

integrations/openclaw/src/config.ts (1)

1-352: LGTM!

Configuration parsing is thorough with proper type validation, default fallbacks, and the null check issue in asRecord (line 262) has been correctly fixed with value !== null.

integrations/openclaw/src/hook-replay/llm.ts (1)

1-622: LGTM!

Comprehensive LLM event recording and replay implementation. The previous review concern about missing sessionKey in replayLlmOutput's ensureSession call (line 345) has been addressed. The grace timer pattern for deferred matching, timing correlation with ambiguity detection, and bounded FIFO eviction with timer cleanup are all correctly implemented.

Comment thread integrations/openclaw/src/__tests__/failure-model.test.ts Outdated
Comment thread integrations/openclaw/src/hook-replay/marks.ts
Comment thread integrations/openclaw/src/telemetry.ts
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@integrations/openclaw/src/hook-replay/marks.ts`:
- Around line 75-82: stripUndefined currently copies untrusted keys into a plain
object which allows assignment to "__proto__" to mutate the prototype; change
the output creation inside stripUndefined from a plain {} to a null-prototype
object (e.g., Object.create(null)) so keys like "__proto__" are stored as data
properties, and keep using normalizeJsonValue(value, seen) for values as before.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: ba0e164d-b07a-4d63-bf44-cbf80b898b99

📥 Commits

Reviewing files that changed from the base of the PR and between 97d9c18 and 65a4fee.

📒 Files selected for processing (3)
  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use camelCase naming convention for Node.js code

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{rs,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license headers in all Rust, Go, JavaScript, and TypeScript source files using C-style comment syntax

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Use SONAR_IGNORE_START / SONAR_IGNORE_END markers only for documented false positives that cannot be resolved in code; keep ignored blocks small, add explanatory comments, and require reviewer sign-off

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{md,markdown,py,sh,bash,js,ts,java,cpp,go,rust}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Keep package names, repo references, and build commands current in documentation

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{md,markdown,py,sh,bash,js,ts,example}

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Example commands must match current package names and paths

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/{integrations,integration,*-integration}/**

📄 CodeRabbit inference engine (.agents/skills/contribute-integration/SKILL.md)

**/{integrations,integration,*-integration}/**: Keep NeMo Flow optional in framework integrations
Preserve the framework's original behavior when NeMo Flow is absent
Wrap tool and LLM paths at the correct framework boundary
Integration pattern must follow docs/integrate-frameworks/adding-scopes.md

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
{crates/adaptive/**,python/nemo_flow/{adaptive,plugin}.py,go/nemo_flow/{adaptive,**}/*.go,**/*.{ts,js,wasm}}

📄 CodeRabbit inference engine (.agents/skills/maintain-optimizer/SKILL.md)

Keep adaptive config schema, plugin lifecycle, and bindings in sync across crates/adaptive, core, bindings, Python (python/nemo_flow/adaptive.py and python/nemo_flow/plugin.py), Go (go/nemo_flow/adaptive and go/nemo_flow), and Node/WebAssembly helpers

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{rs,py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*.{rs,py,go,js,ts,jsx,tsx}: Format changed files with the language-native formatter before the final lint/test pass
Use language-native formatters: cargo fmt --all for Rust, uv run ruff format python for Python, go fmt ./... for Go, npm --prefix crates/node run format for Node.js, and npm --prefix crates/node run precommit:format -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts for WebAssembly

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{py,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,yaml,yml,toml,json,md,txt}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
**/*.{js,ts,tsx,jsx,py,rs,go,java,c,cpp,h,cc,cxx,cs,rb,php,swift,kt}

📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)

Changed files must be formatted with the language-native formatter

Files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • integrations/openclaw/src/__tests__/failure-model.test.ts
  • integrations/openclaw/src/__tests__/hooks-backend.test.ts
  • integrations/openclaw/src/hook-replay/marks.ts
🔇 Additional comments (2)
integrations/openclaw/src/__tests__/failure-model.test.ts (1)

38-93: Async failure assertion path is now deterministic.

Using bounded polling via waitFor instead of fixed sleep makes this test substantially more stable under variable CI timing.

integrations/openclaw/src/__tests__/hooks-backend.test.ts (1)

297-317: Normalization boundary tests are strong and targeted.

The circular-reference and non-finite-number assertions directly protect the replay payload contract before NAPI boundaries.

Comment thread integrations/openclaw/src/hook-replay/marks.ts
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Updated in bd66d54: the package root now only exports the OpenClaw plugin entry. The runtime/config/health helpers remain internal under src/, so NeMo Flow implementation details are no longer part of the package API.

…-observability-plugin

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

I updated the package metadata to follow the OpenClaw plugin shape from opik-openclaw: source extensions, compiled runtimeExtensions, compat, and build fields. I used 2026.5.6 because that is the OpenClaw version this PR is tested against and the peer dependency floor.

I also rechecked the type duplication concern. The avoidable shims were already removed, and the plugin entry uses public package-owned types. For hook payloads specifically, the current public exports in openclaw@2026.5.6 do not expose the event/context types this backend needs:

  • openclaw/plugins/hooks is not exported.
  • openclaw/plugin-sdk/hook-runtime is exported, but does not export these payload/context types.
  • the types exist only under OpenClaw internal dist/plugin-sdk/src/... paths.

I avoided private deep imports and kept the hook aliases structural, with a comment explaining they should be removed once OpenClaw exposes those hook contracts publicly.

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Pushed a focused package/docs cleanup commit: fbd33d5.

Changes:

  • Split production build output from test output so tests compile to .test-dist and do not enter dist.
  • Added prepack and pack:check to validate declared OpenClaw source/runtime entrypoints, production source files, fresh dist, and test artifact exclusion.
  • Updated the package files allowlist to include index.ts, production source files, runtime dist/**, manifest, and README.
  • Added package README covering enablement, plugins.allow, allowConversationAccess, config examples, event mapping, health/status, privacy defaults, and packaging behavior.

Validation:

  • npm --prefix integrations/openclaw run typecheck
  • npm --prefix integrations/openclaw test
  • npm --prefix integrations/openclaw run test:live
  • npm --prefix integrations/openclaw run pack:check
  • uv run pre-commit run --all-files

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Pushed a focused plugin API cleanup commit (1b557e1). Hook registration now uses direct api.on("hook_name", ...) calls so OpenClaw owns event/context inference at the registration boundary. nemoFlow.status now follows the gateway method respond(...) contract, and the tests exercise that path through a shared helper.

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@github-actions github-actions Bot added the lang:rust PR changes/introduces Rust code label May 8, 2026
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Pushed two focused follow-up commits:

  • 4df12b3 hardens the OpenClaw runtime lifecycle: scoped cleanup now closes only the target session, restart cleanup leaves the runtime ready to reinitialize on the next hook, and hook replay can lazily initialize from OpenClaw runtime state when service start has not run yet.
  • 7a812fb preserves LLM usage through the replay/export path: OpenClaw LLM output usage is carried on the replayed response, and the OpenInference exporter reads that usage when emitting Phoenix-compatible token, cost, and latency attributes.

Validation:

  • npm --prefix integrations/openclaw run typecheck
  • npm --prefix integrations/openclaw test
  • npm --prefix integrations/openclaw run pack:check
  • cargo test -p nemo-flow observability::openinference::tests::
  • uv run pre-commit run --all-files

Also validated with a real OpenClaw gateway run using the NeMo Flow plugin: the trace produced a web_search tool span, an LLM span with token/cost/latency in Phoenix, and a current-session ATIF JSON export.

Copy link
Copy Markdown
Member

@willkill07 willkill07 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the current head (7a812fb7) with a focus on integration shape, observability-only behavior, testing, and dependency hygiene.

Strengths:

  • The integration boundary is appropriate: this uses OpenClaw plugin hooks (api.on(...)) and package runtime entrypoints rather than patching OpenClaw source. That matches the current OpenClaw plugin hook / SDK guidance: https://docs.openclaw.ai/plugins/hooks and https://docs.openclaw.ai/plugins/sdk-overview.
  • The observability behavior is scoped well. Successful tool/LLM work is replayed as spans, blocked tools are marks rather than fake successful calls, and telemetry outputs have explicit register/flush/shutdown handling.
  • The OpenInference token usage fallback is directionally right. The emitted llm.token_count.* attributes line up with the OpenInference semantic conventions: https://arize-ai.github.io/openinference/spec/semantic_conventions.html.
  • The integration unit tests are broad and useful: config parsing, ATIF capture/export failure modes, subscriber shutdown failure paths, LLM/tool replay, and an opt-in live smoke path are all covered.

Focused improvements before merge:

  1. Dependency and lockfile handling needs to be reworked. This PR adds integrations/openclaw/package-lock.json as a separate 6k+ line lockfile, while the repo currently keeps dependency locks at established root/surface locations such as Cargo.lock, uv.lock, and crates/node/package-lock.json. More importantly, npm --prefix integrations/openclaw ci --ignore-scripts currently fails because the new lockfile is not in sync with integrations/openclaw/package.json (missing OpenClaw transitive packages such as @lydell/node-pty-*, @mariozechner/clipboard-*, koffi, sqlite-vec, and @napi-rs/canvas-*). I would prefer this to use a root/workspace-managed lockfile instead of a package-local lockfile, then update that shared lock in this PR.

  2. Wire the new integration validation into normal repo CI. The package has good tests, but .github/ci-path-filters.yml does not include integrations/openclaw/**, and just test-node still only installs/tests crates/node. As a result, npm --prefix integrations/openclaw run typecheck, npm --prefix integrations/openclaw test, and npm --prefix integrations/openclaw run pack:check are manual-only unless a reviewer remembers to run them. Please add a just recipe and CI path filter/job coverage for this package. The live smoke test can stay opt-in, but typecheck/unit/pack validation should be part of the regular PR path.

Non-blocking cleanup: runtime-state.ts has an unused PLUGIN_ID constant. It is minor, but removing it would keep the new package tidy.

Validation I ran:

  • git diff --check upstream/main...HEAD passed.
  • cargo test -p nemo-flow openinference passed: 21 OpenInference tests passed.
  • npm --prefix integrations/openclaw ci --ignore-scripts failed due the out-of-sync integration lockfile noted above, so I could not run the OpenClaw package test scripts from a clean install.

Comment thread package-lock.json
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay... thinking about this, I think we need a git repository root package.json that adds:

  • integration/openclaw
  • crates/node
    as two workspace members. That way we have a ground truth for all packages for licenses.

See: https://docs.npmjs.com/cli/v11/using-npm/workspaces

Copy link
Copy Markdown
Contributor Author

@mnajafian-nv mnajafian-nv May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Will. Absolutely! I will rework this so the OpenClaw integration participates in a repo-root npm workspace instead of carrying its own package-local lockfile.

Plan:

  • add a repository-root npm workspace covering crates/node and integrations/openclaw
  • remove the integration-local package-lock.json and update the shared npm lock instead
  • update Node attribution/pre-commit lockfile handling to use the shared lock
  • add a just recipe for OpenClaw integration validation
  • wire integrations/openclaw/** into normal CI path filtering so typecheck, unit tests, and pack validation run automatically
  • keep the live smoke test opt-in
  • remove the unused PLUGIN_ID constant while I’m there

I’ll push this as a focused dependency/CI hygiene follow-up so the review surface stays clear.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

part of the node testing in CI can also now test OpenClaw as well :)

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
@github-actions github-actions Bot added the lang:python PR changes/introduces Python code label May 8, 2026
@mnajafian-nv
Copy link
Copy Markdown
Contributor Author

Pushed the dependency/CI hygiene follow-up.

This moves Node dependency management to a repo-root npm workspace covering crates/node and integrations/openclaw, removes both package-local npm lockfiles, and regenerates the shared root package-lock.json plus Node attributions from that single lock source.

I also wired integrations/openclaw/** into Node CI and added just test-openclaw; CI now runs the OpenClaw integration typecheck, unit tests, and pack validation from a clean npm ci --ignore-scripts install. The live smoke test remains opt-in. I also removed the unused PLUGIN_ID constant.

Local validation passed:

  • npm ci --ignore-scripts
  • npm run typecheck --workspace=@nvidia/nemo-flow-openclaw
  • npm test --workspace=@nvidia/nemo-flow-openclaw
  • npm run pack:check --workspace=@nvidia/nemo-flow-openclaw
  • npm test --workspace=nemo-flow-node
  • uv run pre-commit run --all-files

Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Signed-off-by: mnajafian-nv <mnajafian@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat PR introduces new feature or functionality lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XXL PR is very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants