launchdarkly-ai-opencode-agents 0.0.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. launchdarkly_ai_opencode_agents-0.2.0/.gitignore +38 -0
  2. launchdarkly_ai_opencode_agents-0.2.0/CHANGELOG.md +31 -0
  3. launchdarkly_ai_opencode_agents-0.2.0/PKG-INFO +61 -0
  4. launchdarkly_ai_opencode_agents-0.2.0/README.md +39 -0
  5. launchdarkly_ai_opencode_agents-0.2.0/agents.md +47 -0
  6. launchdarkly_ai_opencode_agents-0.2.0/api-report/launchdarkly_ai_opencode_agents.txt +4 -0
  7. launchdarkly_ai_opencode_agents-0.2.0/pyproject.toml +34 -0
  8. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/__init__.py +17 -0
  9. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/_version.py +4 -0
  10. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/handler.py +833 -0
  11. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/process.py +254 -0
  12. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/py.typed +0 -0
  13. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/server.py +249 -0
  14. launchdarkly_ai_opencode_agents-0.2.0/src/launchdarkly_ai_opencode_agents/spans.py +146 -0
  15. launchdarkly_ai_opencode_agents-0.2.0/tests/fake_opencode.py +292 -0
  16. launchdarkly_ai_opencode_agents-0.2.0/tests/test_handler.py +1720 -0
  17. launchdarkly_ai_opencode_agents-0.2.0/tests/test_sdk_usage.py +87 -0
  18. launchdarkly_ai_opencode_agents-0.0.0/PKG-INFO +0 -6
  19. launchdarkly_ai_opencode_agents-0.0.0/pyproject.toml +0 -10
  20. launchdarkly_ai_opencode_agents-0.0.0/setup.cfg +0 -4
  21. launchdarkly_ai_opencode_agents-0.0.0/src/launchdarkly_ai_opencode_agents.egg-info/PKG-INFO +0 -6
  22. launchdarkly_ai_opencode_agents-0.0.0/src/launchdarkly_ai_opencode_agents.egg-info/SOURCES.txt +0 -6
  23. launchdarkly_ai_opencode_agents-0.0.0/src/launchdarkly_ai_opencode_agents.egg-info/dependency_links.txt +0 -1
  24. launchdarkly_ai_opencode_agents-0.0.0/src/launchdarkly_ai_opencode_agents.egg-info/top_level.txt +0 -1
  25. launchdarkly_ai_opencode_agents-0.0.0/src/placeholder_sdk/__init__.py +0 -1
@@ -0,0 +1,38 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .venv/
5
+ dist/
6
+ *.egg-info/
7
+
8
+ # Environment
9
+ .env
10
+ .env.local
11
+ .env.*.local
12
+
13
+ # macOS
14
+ .DS_Store
15
+
16
+ # Editor
17
+ .vscode/
18
+ .cursor/
19
+
20
+ # Logs
21
+ *.log
22
+
23
+ # Test coverage
24
+ coverage/
25
+ .coverage
26
+ htmlcov/
27
+
28
+ # Type checking
29
+ .mypy_cache/
30
+
31
+ # Test cache
32
+ .pytest_cache/
33
+
34
+ # Run output / scratch
35
+ tmp/
36
+ output/
37
+
38
+ .claude/
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0](https://github.com/launchdarkly/python-ai-sdk/compare/launchdarkly-ai-opencode-agents-0.1.0...launchdarkly-ai-opencode-agents-0.2.0) (2026-10-23)
4
+
5
+
6
+ ### ⚠ BREAKING CHANGES
7
+
8
+ * **opencode:** start and stop opencode serve in the handler ([#198](https://github.com/launchdarkly/python-ai-sdk/issues/198))
9
+
10
+ ### Features
11
+
12
+ * **opencode-agents:** add an OpenCode handler ([#159](https://github.com/launchdarkly/python-ai-sdk/issues/159)) ([fc08e8c](https://github.com/launchdarkly/python-ai-sdk/commit/fc08e8c383bfb6e5e505b7a07d57f5bd9dd79a11))
13
+ * **opencode-agents:** emit the AG-UI text and tool subset ([#162](https://github.com/launchdarkly/python-ai-sdk/issues/162)) ([7677621](https://github.com/launchdarkly/python-ai-sdk/commit/7677621a88ba433a2117b1b5a007631cbf7d74d0))
14
+ * **opencode-agents:** open one OpenCode session per call ([#179](https://github.com/launchdarkly/python-ai-sdk/issues/179)) ([b225113](https://github.com/launchdarkly/python-ai-sdk/commit/b225113d66bbc980cb72c3007620bca061ab6035))
15
+ * **opencode-agents:** render agent instruction templates ([#182](https://github.com/launchdarkly/python-ai-sdk/issues/182)) ([83175aa](https://github.com/launchdarkly/python-ai-sdk/commit/83175aa680dc18697ddcc1d17863cdfdaf08d7e6))
16
+ * **opencode:** start and stop opencode serve in the handler ([#198](https://github.com/launchdarkly/python-ai-sdk/issues/198)) ([0748dcf](https://github.com/launchdarkly/python-ai-sdk/commit/0748dcf209076f98cffa38fc59d1987293d5015f))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * **opencode-agents:** own the HTTP client ([#194](https://github.com/launchdarkly/python-ai-sdk/issues/194)) ([ed2d419](https://github.com/launchdarkly/python-ai-sdk/commit/ed2d41914ee3f843fe087d754914cd4f2ae1dac8))
22
+ * **opencode-agents:** skip judges and record structured history ([#177](https://github.com/launchdarkly/python-ai-sdk/issues/177)) ([6fadf1d](https://github.com/launchdarkly/python-ai-sdk/commit/6fadf1da3abc49c0a82ffc4c2532484aceac8d76))
23
+
24
+ ## Changelog
25
+
26
+ ## Changelog
27
+
28
+ All notable changes to this project will be documented in this file.
29
+
30
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
31
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
@@ -0,0 +1,61 @@
1
+ Metadata-Version: 2.5
2
+ Name: launchdarkly-ai-opencode-agents
3
+ Version: 0.2.0
4
+ Summary: OpenCode agent handler for LaunchDarkly AI SDK
5
+ Project-URL: Homepage, https://github.com/launchdarkly/python-ai-sdk
6
+ Project-URL: Repository, https://github.com/launchdarkly/python-ai-sdk
7
+ Project-URL: Bug Tracker, https://github.com/launchdarkly/python-ai-sdk/issues
8
+ Author-email: LaunchDarkly <team@launchdarkly.com>
9
+ License-Expression: Apache-2.0
10
+ Keywords: agents,ai,launchdarkly,opencode
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: httpx>=0.27
19
+ Requires-Dist: launchdarkly-ai-server
20
+ Requires-Dist: opentelemetry-api>=1.25
21
+ Description-Content-Type: text/markdown
22
+
23
+ # `launchdarkly-ai-opencode-agents`
24
+
25
+ OpenCode handler for `launchdarkly-ai-server`. `async with handler` starts `opencode serve` and waits until it is healthy. The process stops when that context exits. It does not depend on an OpenCode SDK.
26
+
27
+ **`provides_for`:** `['*', 'agent']` — matches an agent-mode variation for any provider.
28
+
29
+ ```bash
30
+ pip install launchdarkly-ai-server launchdarkly-server-sdk launchdarkly-ai-opencode-agents
31
+ ```
32
+
33
+ ```python
34
+ import asyncio
35
+ import os
36
+
37
+ from launchdarkly_ai_opencode_agents import create_opencode_handler
38
+ from launchdarkly_ai_server import config, init_client, shutdown
39
+
40
+
41
+ async def main() -> None:
42
+ await init_client()
43
+ handler = create_opencode_handler(
44
+ cwd="/work",
45
+ config="/home/app/.vega/opencode.json",
46
+ env=os.environ.copy(),
47
+ )
48
+ async with handler:
49
+ async for event in config(key="my-agent", handler=handler).stream(
50
+ "Hello", {"kind": "user", "key": "user-1"}
51
+ ):
52
+ print(event)
53
+ await shutdown()
54
+
55
+
56
+ asyncio.run(main())
57
+ ```
58
+
59
+ `cwd` is the working directory, `config` is the OpenCode config file, and `env` is the child environment. The handler sets `OPENCODE_CONFIG` from `config`, replaces any `OPENCODE_SERVER_USERNAME` in `env` with `opencode`, replaces any `OPENCODE_SERVER_PASSWORD` with a generated secret, and binds `opencode serve` to loopback. Requests to that server use that username and secret as basic auth. A caller does not pass a URL, an HTTP client, or a transport. `command` overrides the `opencode` executable; a test passes a fake executable there.
60
+
61
+ Entering the handler starts `opencode serve` and returns once it is healthy. The process stops when the context exits, after `config().stream()` returns. Put a wall-clock limit around `config().stream()`, not around the context. A judge routed here runs as a full OpenCode agent: the server's tools, in `cwd`, apply to the judge prompt. There is no tool-less judge mode. The handler yields AG-UI text and tool events. `config().stream()` yields `chunk` then `done`.
@@ -0,0 +1,39 @@
1
+ # `launchdarkly-ai-opencode-agents`
2
+
3
+ OpenCode handler for `launchdarkly-ai-server`. `async with handler` starts `opencode serve` and waits until it is healthy. The process stops when that context exits. It does not depend on an OpenCode SDK.
4
+
5
+ **`provides_for`:** `['*', 'agent']` — matches an agent-mode variation for any provider.
6
+
7
+ ```bash
8
+ pip install launchdarkly-ai-server launchdarkly-server-sdk launchdarkly-ai-opencode-agents
9
+ ```
10
+
11
+ ```python
12
+ import asyncio
13
+ import os
14
+
15
+ from launchdarkly_ai_opencode_agents import create_opencode_handler
16
+ from launchdarkly_ai_server import config, init_client, shutdown
17
+
18
+
19
+ async def main() -> None:
20
+ await init_client()
21
+ handler = create_opencode_handler(
22
+ cwd="/work",
23
+ config="/home/app/.vega/opencode.json",
24
+ env=os.environ.copy(),
25
+ )
26
+ async with handler:
27
+ async for event in config(key="my-agent", handler=handler).stream(
28
+ "Hello", {"kind": "user", "key": "user-1"}
29
+ ):
30
+ print(event)
31
+ await shutdown()
32
+
33
+
34
+ asyncio.run(main())
35
+ ```
36
+
37
+ `cwd` is the working directory, `config` is the OpenCode config file, and `env` is the child environment. The handler sets `OPENCODE_CONFIG` from `config`, replaces any `OPENCODE_SERVER_USERNAME` in `env` with `opencode`, replaces any `OPENCODE_SERVER_PASSWORD` with a generated secret, and binds `opencode serve` to loopback. Requests to that server use that username and secret as basic auth. A caller does not pass a URL, an HTTP client, or a transport. `command` overrides the `opencode` executable; a test passes a fake executable there.
38
+
39
+ Entering the handler starts `opencode serve` and returns once it is healthy. The process stops when the context exits, after `config().stream()` returns. Put a wall-clock limit around `config().stream()`, not around the context. A judge routed here runs as a full OpenCode agent: the server's tools, in `cwd`, apply to the judge prompt. There is no tool-less judge mode. The handler yields AG-UI text and tool events. `config().stream()` yields `chunk` then `done`.
@@ -0,0 +1,47 @@
1
+ # Agent Guide — `launchdarkly-ai-opencode-agents`
2
+
3
+ ```python
4
+ provides_for = ('*', 'agent')
5
+ ```
6
+
7
+ Each call starts `opencode serve`, speaks the stable HTTP API (`/session`, `/session/{id}/message`, `/event`, `/session/{id}/abort`), and stops the process when the stream finishes or the caller closes it. The package does not import or construct `anomalyco/opencode-sdk-python`.
8
+
9
+ This package is Python-only. There is no JS counterpart in this slice. The spec section, API surface list, and `usage-ids.txt` row live in `launchdarkly/ai-sdks-monorepo`, which is not this repository. The usage helper ids are `opencode-agents.createOpenCodeHandler` and `opencode-agents.opencodeAgents`. The package is a normal pre-v1 package, same as the other handlers.
10
+
11
+ ## File map
12
+
13
+ | File | Role |
14
+ | --- | --- |
15
+ | `handler.py` | Reducer, `create_opencode_handler`, `opencode_agents` |
16
+ | `process.py` | Starts and stops `opencode serve` for one call |
17
+ | `server.py` | The HTTP session this process just started |
18
+ | `spans.py` | `invoke_agent` root, and the `chat` / `execute_tool` constructors the parity checks call |
19
+ | `_version.py` | Package name and version sent with usage events |
20
+
21
+ ## Dependencies
22
+
23
+ `launchdarkly-ai-server`, `httpx`, and `opentelemetry-api`. `launchdarkly-server-sdk` is what `init_client()` loads for a normal process. No OpenCode SDK. The `opencode` executable is the default command.
24
+
25
+ ## init_client
26
+
27
+ Call `init_client()` before `config()`, the same way as the other handlers. The example in `README.md` does.
28
+
29
+ ## OTel
30
+
31
+ A run opens one `invoke_agent` span and sets `launchdarkly.operation.type`. The handler stream is the AG-UI text and tool subset. `config().stream()` is `chunk` then `done`.
32
+
33
+ ## Call shape
34
+
35
+ `create_opencode_handler(*, cwd, config, env, capture_content=None, model=None, agent=None, command=None)` returns a `ProviderHandler`. `cwd` is the working directory. `config` is the path of the OpenCode config file. `env` replaces the child environment, and the handler sets `OPENCODE_CONFIG` from `config`. Each start also sets `OPENCODE_SERVER_USERNAME` to `opencode` and `OPENCODE_SERVER_PASSWORD` to a generated secret, replacing either value inherited from `env`, and sends that pair as basic auth. `command` defaults to `opencode`. A test passes a fake executable instead of a URL. There is no `base_url`, client, or transport argument.
36
+
37
+ `async with handler` starts the process and returns once `/global/health` returns 200 and `healthy: true`. Concurrent entries share that process. The process stops when the last context exits, after `config().stream()` returns, including when the caller times out or closes the stream. A wall-clock budget goes around `config().stream()`, not around the context. Closing the stream still aborts the session. Without the context, one call starts and stops its own process.
38
+
39
+ Assistant text is emitted only after `message.updated` marks that message `role == "assistant"`. A part snapshot is the full text of that part so far; a later delta appends. A text delta without `partID` is dropped.
40
+
41
+ ## Common pitfalls
42
+
43
+ `provides_for` is `('*', 'agent')`, so a judge is routed here too. Each call starts its own process, so the judge prompt does not enter the agent's session and does not need `skip_judges=True`. The judge still runs as a full OpenCode agent, with the server's tools, in `cwd`. This package does not take a tool-less judge agent.
44
+
45
+ The reducer does not adopt the first session on the bus. Other sessions are dropped, including their `session.error`. `session.idle` for this session ends the run.
46
+
47
+ `env` is not merged with the parent environment. A bare `opencode` command needs `PATH` in `env`.
@@ -0,0 +1,4 @@
1
+ # Public API of launchdarkly_ai_opencode_agents. Generated by `make api-report`; do not edit.
2
+ create_opencode_handler(*, cwd: str | os.PathLike[str], config: str | os.PathLike[str], env: Mapping[str, str], capture_content: bool | None = None, model: ModelResolver | None = None, agent: str | None = None, command: Command = None) -> ProviderHandler
3
+ opencode_agents(config_key: str, user_input: str, context: dict[str, Any], **kwargs: Any) -> Any
4
+ OpenCodeSessionError(Exception) [class]
@@ -0,0 +1,34 @@
1
+ [project]
2
+ name = "launchdarkly-ai-opencode-agents"
3
+ version = "0.2.0"
4
+ requires-python = ">=3.12"
5
+ dependencies = [
6
+ "launchdarkly-ai-server",
7
+ "httpx>=0.27",
8
+ "opentelemetry-api>=1.25",
9
+ ]
10
+ description = "OpenCode agent handler for LaunchDarkly AI SDK"
11
+ readme = "README.md"
12
+ license = "Apache-2.0"
13
+ authors = [{name = "LaunchDarkly", email = "team@launchdarkly.com"}]
14
+ keywords = ["launchdarkly", "ai", "opencode", "agents"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Software Development :: Libraries",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/launchdarkly/python-ai-sdk"
26
+ Repository = "https://github.com/launchdarkly/python-ai-sdk"
27
+ "Bug Tracker" = "https://github.com/launchdarkly/python-ai-sdk/issues"
28
+
29
+ [build-system]
30
+ requires = ["hatchling>=1.32,<2"]
31
+ build-backend = "hatchling.build"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/launchdarkly_ai_opencode_agents"]
@@ -0,0 +1,17 @@
1
+ """LaunchDarkly AI SDK - integration for OpenCode agents.
2
+
3
+ See https://launchdarkly.com/docs for usage.
4
+ """
5
+
6
+ from launchdarkly_ai_server import register_ai_sdk_package
7
+
8
+ from ._version import PACKAGE_NAME, __version__
9
+ from .handler import OpenCodeSessionError, create_opencode_handler, opencode_agents
10
+
11
+ __all__ = [
12
+ "OpenCodeSessionError",
13
+ "create_opencode_handler",
14
+ "opencode_agents",
15
+ ]
16
+
17
+ register_ai_sdk_package(PACKAGE_NAME, __version__)
@@ -0,0 +1,4 @@
1
+ """This package's identity, as sent with ``$ld:ai:sdk:info`` and ``$ld:ai:sdk:usage``."""
2
+
3
+ PACKAGE_NAME = "launchdarkly-ai-opencode-agents"
4
+ __version__ = "0.2.0" # x-release-please-version