-
Notifications
You must be signed in to change notification settings - Fork 13
feat: OpenCode Observability Plugin #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
billxbf
wants to merge
17
commits into
NVIDIA:main
Choose a base branch
from
billxbf:feature/bx-opencode
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
d33301e
opencode obsv plugin
billxbf a2e5775
opencode obsv plugin
billxbf 5b86ad9
nit
billxbf 99af425
Merge branch 'feature/bx-opencode' of github.com:billxbf/NeMo-Flow in…
billxbf cb849b9
nit
billxbf da4c6c7
Merge branch 'main' into feature/bx-opencode
billxbf 9696ab3
docs: add OpenCode plugin docstrings
billxbf 1eb3d52
Merge branch 'feature/bx-opencode' of github.com:billxbf/NeMo-Flow in…
billxbf ddd2dd2
Merge branch 'main' into feature/bx-opencode
billxbf c9d9da2
Update integrations/opencode-plugin/package.json
billxbf 373d2f5
Update docs/integrate-frameworks/opencode.md
billxbf 6ebc939
resolve conflict
billxbf f188489
opencode observability plugin refactor
billxbf 9310111
doc, llm & tool span wrapper, debug
billxbf 82bc75a
Merge branch 'main' into feature/bx-opencode
billxbf b3067c6
addressing comments
billxbf af12512
nit
billxbf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| <!-- | ||
| SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| SPDX-License-Identifier: Apache-2.0 | ||
| --> | ||
|
|
||
| # OpenCode Plugin | ||
|
|
||
| NeMo Flow integrates with OpenCode through the `nemo-flow-opencode` server | ||
| plugin. The plugin uses OpenCode's public plugin hooks and does not require a | ||
| patched OpenCode checkout. | ||
|
|
||
| Use this plugin when you want NeMo Flow observability for OpenCode sessions, | ||
| LLM calls, successful tool calls, and session errors. The plugin maps OpenCode | ||
| hook payloads into NeMo Flow session, LLM, and tool spans. The generic NeMo | ||
| Flow `observability` component controls ATOF, ATIF, OpenTelemetry, and | ||
| OpenInference export. | ||
|
|
||
| ## Requirements | ||
|
|
||
| - OpenCode with server plugin support. | ||
| - Node.js 20 or newer. | ||
| - A NeMo Flow Node.js binding package compatible with `nemo-flow-opencode`. | ||
| - Provider credentials configured in OpenCode. | ||
|
|
||
| ## Install | ||
|
|
||
| Install the plugin with the OpenCode CLI: | ||
|
|
||
| ```bash | ||
| opencode plugin nemo-flow-opencode | ||
| ``` | ||
|
|
||
| You can also install the package in the Node.js environment where OpenCode | ||
| loads plugins: | ||
|
|
||
| ```bash | ||
| npm install nemo-flow-opencode | ||
| ``` | ||
|
|
||
| OpenCode uses the package name `nemo-flow-opencode` in the `plugin` array. | ||
|
|
||
| ## Enable and Configure the Plugin | ||
|
|
||
| Create or update `opencode.json` in the OpenCode project directory: | ||
|
|
||
| ```json | ||
| { | ||
| "plugin": [ | ||
| [ | ||
| "nemo-flow-opencode", | ||
| { | ||
| "enabled": true, | ||
| "logPath": "./.nemoflow/opencode-plugin.log", | ||
| "plugins": { | ||
| "version": 1, | ||
| "components": [ | ||
| { | ||
| "kind": "observability", | ||
| "enabled": true, | ||
| "config": { | ||
| "version": 1, | ||
| "atof": { | ||
| "enabled": true, | ||
| "output_directory": "./.nemoflow", | ||
| "filename": "opencode.atof.jsonl", | ||
| "mode": "overwrite" | ||
| }, | ||
| "atif": { | ||
| "enabled": true, | ||
| "agent_name": "opencode", | ||
| "output_directory": "./.nemoflow", | ||
| "filename_template": "opencode-{session_id}.atif.json" | ||
| }, | ||
| "opentelemetry": { | ||
| "enabled": false, | ||
| "transport": "http_binary", | ||
| "endpoint": "http://localhost:4318/v1/traces", | ||
| "service_name": "opencode-nemo-flow" | ||
| }, | ||
| "openinference": { | ||
| "enabled": false, | ||
| "transport": "http_binary", | ||
| "endpoint": "http://localhost:6006/v1/traces", | ||
| "service_name": "opencode-nemo-flow" | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| This example enables filesystem ATOF and ATIF export and leaves OTLP exporters | ||
| disabled until you point them at a collector or Phoenix endpoint. Remove | ||
| exporter sections you do not use, or set their `enabled` fields to `false`. | ||
|
|
||
| - `plugin[][0]` is the OpenCode plugin package name. Use | ||
| `nemo-flow-opencode`. | ||
| - `enabled` disables or enables the NeMo Flow OpenCode wrapper without removing | ||
| the plugin entry. | ||
| - `logPath` writes JSONL diagnostics for plugin initialization and | ||
| pass-through behavior. | ||
| - `plugins` is the generic NeMo Flow plugin configuration document. Use this | ||
| object to configure built-in components such as `observability`. | ||
| - `plugins.components[].config.atof` writes raw ATOF JSONL lifecycle events. | ||
| - `plugins.components[].config.atif` writes ATIF trajectory JSON files. | ||
| - `plugins.components[].config.opentelemetry` sends generic OTLP spans to an | ||
| OpenTelemetry collector when `enabled` is `true`. | ||
| - `plugins.components[].config.openinference` sends OpenInference OTLP spans to | ||
| Phoenix or another OpenInference-compatible collector when `enabled` is | ||
| `true`. | ||
|
|
||
| ## Configuration Key Names | ||
|
|
||
| OpenCode wrapper fields use JavaScript-style names, such as `logPath`. | ||
|
|
||
| The top-level `plugins` object inside the wrapper is the generic NeMo Flow | ||
| plugin config. Fields inside this object use NeMo Flow generic plugin names, so | ||
| they are `snake_case` in every binding. | ||
|
|
||
| Missing observability sections are disabled. Plugin-host validation or | ||
| initialization failures leave OpenCode in pass-through mode and write a warning | ||
| to `logPath`. | ||
|
|
||
| The ATIF filename placeholder `{session_id}` is the NeMo Flow top-level agent | ||
| scope UUID. The OpenCode session ID is recorded in event metadata. | ||
|
|
||
| See [Configure the Observability Plugin](../export-observability-data/observability-plugin.md) | ||
| for the complete `observability` component schema and exporter-specific fields. | ||
|
|
||
| The plugin is passive. It records observability output but does not rewrite | ||
| prompts, tool arguments, model requests, or OpenCode execution behavior. | ||
|
|
||
| OpenCode streaming message events are used internally to reconstruct concise | ||
| LLM responses. They are not exported as individual ATIF steps. | ||
|
|
||
| ## Known Limitations | ||
|
|
||
| The current OpenCode plugin API is enough for passive observability. It is not | ||
| enough for NeMo Flow request intercepts, execution intercepts, conditional | ||
| blocking, or complete tool error spans because OpenCode does not yet expose | ||
| around-style LLM or tool hooks. Future work should add generic OpenCode plugin | ||
| hooks upstream before enabling those behaviors. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| <!-- | ||
| SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| SPDX-License-Identifier: Apache-2.0 | ||
| --> | ||
|
|
||
| # NeMo Flow OpenCode Plugin | ||
|
|
||
| `nemo-flow-opencode` is a standalone OpenCode server plugin for NeMo Flow | ||
| observability. It uses OpenCode's public plugin API and does not require | ||
| patching OpenCode. It maps OpenCode activity into NeMo Flow session, LLM, and | ||
| tool spans for the generic observability plugin. | ||
|
|
||
| For the full guide, see `docs/integrate-frameworks/opencode.md` in the NeMo | ||
| Flow documentation. | ||
|
|
||
| ## Install | ||
|
|
||
| Install the plugin with the OpenCode CLI: | ||
|
|
||
| ```bash | ||
| opencode plugin nemo-flow-opencode | ||
| ``` | ||
|
|
||
| You can also install the package in the Node.js environment where OpenCode | ||
| loads plugins: | ||
|
|
||
| ```bash | ||
| npm install nemo-flow-opencode | ||
| ``` | ||
|
|
||
| ## Configure | ||
|
|
||
| Use the package name in `opencode.json`: | ||
|
|
||
| ```json | ||
| { | ||
| "plugin": [ | ||
| [ | ||
| "nemo-flow-opencode", | ||
| { | ||
| "enabled": true, | ||
| "logPath": "./.nemoflow/opencode-plugin.log", | ||
| "plugins": { | ||
| "version": 1, | ||
| "components": [ | ||
| { | ||
| "kind": "observability", | ||
| "enabled": true, | ||
| "config": { | ||
| "version": 1, | ||
| "atof": { | ||
| "enabled": true, | ||
| "output_directory": "./.nemoflow", | ||
| "filename": "opencode.atof.jsonl" | ||
| }, | ||
| "atif": { | ||
| "enabled": true, | ||
| "agent_name": "opencode", | ||
| "output_directory": "./.nemoflow", | ||
| "filename_template": "opencode-{session_id}.atif.json" | ||
| } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| ] | ||
| } | ||
| ``` | ||
|
|
||
| Fields inside `plugins` are NeMo Flow generic plugin configuration, so they use | ||
| `snake_case`. The OpenCode wrapper fields use JavaScript-style names, such as | ||
| `logPath`. | ||
|
|
||
| ## Output | ||
|
|
||
| Configure the built-in `observability` component to write: | ||
|
|
||
| - ATOF JSONL events with `plugins.components[].config.atof`. | ||
| - ATIF trajectory files with `plugins.components[].config.atif`. | ||
| - Optional OpenTelemetry or OpenInference traces with | ||
| `plugins.components[].config.opentelemetry` or `openinference`. | ||
| - JSONL plugin diagnostics with the OpenCode wrapper `logPath` field. | ||
|
|
||
| OpenCode streaming message events are used internally to reconstruct concise | ||
| LLM responses. They are not exported as individual ATIF steps. | ||
|
|
||
| ## Current Limitations | ||
|
|
||
| This plugin uses only existing OpenCode hooks. OpenCode does not yet expose an | ||
| around-style LLM stream hook or tool execution hook, so the plugin cannot record | ||
| exact LLM stream duration, tool error spans for every failure path, request | ||
| intercepts, execution intercepts, or conditional guardrail blocking. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| { | ||
| "name": "nemo-flow-opencode", | ||
| "version": "0.2.0", | ||
| "description": "OpenCode server plugin that maps OpenCode activity into NeMo Flow observability.", | ||
| "type": "module", | ||
| "main": "./server.js", | ||
| "exports": { | ||
| ".": { | ||
| "default": "./server.js" | ||
| }, | ||
| "./server": { | ||
| "default": "./server.js" | ||
| } | ||
| }, | ||
|
billxbf marked this conversation as resolved.
|
||
| "files": [ | ||
| "README.md", | ||
| "server.js" | ||
| ], | ||
| "scripts": { | ||
| "test": "node --test test/*.mjs" | ||
| }, | ||
| "keywords": [ | ||
| "opencode", | ||
| "nemo-flow", | ||
| "observability", | ||
| "atif", | ||
| "atof", | ||
| "plugin" | ||
| ], | ||
| "homepage": "https://github.com/NVIDIA/NeMo-Flow/blob/main/docs/integrate-frameworks/opencode.md", | ||
| "bugs": { | ||
| "url": "https://github.com/NVIDIA/NeMo-Flow/issues" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/NVIDIA/NeMo-Flow.git", | ||
| "directory": "integrations/opencode" | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "engines": { | ||
| "node": ">=20.0.0" | ||
| }, | ||
| "dependencies": { | ||
| "nemo-flow-node": ">0.1.0 <1.0.0" | ||
| }, | ||
|
billxbf marked this conversation as resolved.
|
||
| "peerDependencies": { | ||
| "@opencode-ai/plugin": ">=1.14.40" | ||
| }, | ||
| "devDependencies": { | ||
| "@opencode-ai/plugin": "^1.14.40" | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.