|
| 1 | +# Contributing |
| 2 | + |
| 3 | +Thanks for your interest in contributing to the LangSmith Java SDK! |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +This SDK is **auto-generated by [Stainless](https://www.stainless.com/)** from our OpenAPI spec. Custom code (prompts, OTel wrappers, etc.) lives alongside generated code — Stainless is configured to [preserve custom code](https://www.stainless.com/docs/sdks/configure/custom-code/) and never overwrite it. |
| 8 | + |
| 9 | +> **Important:** Most files in the SDK are generated. If you need to change generated code, talk to @edongashi — there may be weird errors in the Stainless config, but they're generally fixable. |
| 10 | +
|
| 11 | +## Branching and workflow |
| 12 | + |
| 13 | +| Branch | Purpose | |
| 14 | +| ----------------------------------------------- | ----------------------------------------------------- | |
| 15 | +| `next` | **Development branch.** All PRs should target `next`. | |
| 16 | +| `main` | Release branch. Only updated via release-please. | |
| 17 | +| `release-please--branches--main--changes--next` | Auto-generated release PR. Merges `next` → `main`. | |
| 18 | + |
| 19 | +**Always work off `next`.** Do not merge directly to `main` — Dependabot or other bots occasionally violate this, which can cause headaches. |
| 20 | + |
| 21 | +### Release process |
| 22 | + |
| 23 | +1. Merge your PR into `next`. |
| 24 | +2. A release-please PR is automatically created/updated (`release-please--branches--main--changes--next`). |
| 25 | +3. Verify your change appears in the release PR diff and description. |
| 26 | +4. Approve the release PR — it auto-merges on approval. |
| 27 | +5. A GitHub Action publishes to Maven Central via `./gradlew publishAndReleaseToMavenCentral`. |
| 28 | +6. Maven Central can be slow to index — verify on [repo1.maven.org](https://repo1.maven.org/maven2/com/langchain/smith/langsmith-java/) rather than [mvnrepository.com](https://mvnrepository.com/artifact/com.langchain.smith/langsmith-java), which lags behind. |
| 29 | + |
| 30 | +> **Note:** If lint fixes or other changes are pushed to the release-please branch after a version bump, the publish action can fail. Always ensure CI is green before approving. |
| 31 | +
|
| 32 | +## Development setup |
| 33 | + |
| 34 | +### Prerequisites |
| 35 | + |
| 36 | +- Java 8+ (tested against 8 and 21) |
| 37 | +- Gradle (uses the included `gradlew` wrapper) |
| 38 | + |
| 39 | +### Building |
| 40 | + |
| 41 | +```bash |
| 42 | +./scripts/build |
| 43 | +``` |
| 44 | + |
| 45 | +### Formatting |
| 46 | + |
| 47 | +The project uses [ktfmt](https://github.com/facebook/ktfmt) (`--kotlinlang-style`) for Kotlin and [Palantir Java Format](https://github.com/palantir/palantir-java-format) for Java. |
| 48 | + |
| 49 | +```bash |
| 50 | +# Format all files |
| 51 | +./scripts/format |
| 52 | + |
| 53 | +# Format only Kotlin |
| 54 | +./gradlew formatKotlin |
| 55 | + |
| 56 | +# Format a single module |
| 57 | +./gradlew :langsmith-java-core:formatKotlin |
| 58 | +``` |
| 59 | + |
| 60 | +### Linting |
| 61 | + |
| 62 | +```bash |
| 63 | +# Lint all files |
| 64 | +./scripts/lint |
| 65 | + |
| 66 | +# Lint only Kotlin |
| 67 | +./gradlew lintKotlin |
| 68 | +``` |
| 69 | + |
| 70 | +CI blocks on lint failures. Always run `./scripts/format` before pushing. |
| 71 | + |
| 72 | +### Testing |
| 73 | + |
| 74 | +```bash |
| 75 | +# Run all tests |
| 76 | +./scripts/test |
| 77 | + |
| 78 | +# Run specific tests |
| 79 | +./gradlew :langsmith-java-core:test --tests "com.langchain.smith.prompts.*" |
| 80 | + |
| 81 | +# Force re-run (skip Gradle cache) |
| 82 | +./gradlew :langsmith-java-core:test --tests "..." --rerun |
| 83 | + |
| 84 | +# See stdout output |
| 85 | +./gradlew :langsmith-java-core:test --tests "..." --rerun --info |
| 86 | +``` |
| 87 | + |
| 88 | +#### Integration tests |
| 89 | + |
| 90 | +Integration tests require API keys and skip gracefully via `assumeTrue` if they're missing: |
| 91 | + |
| 92 | +```bash |
| 93 | +export LANGSMITH_API_KEY="lsv2_pt_..." |
| 94 | +export OPENAI_API_KEY="sk-..." |
| 95 | +export ANTHROPIC_API_KEY="sk-ant-..." |
| 96 | +``` |
| 97 | + |
| 98 | +## CI |
| 99 | + |
| 100 | +CI runs three jobs on every push and PR: |
| 101 | + |
| 102 | +1. **lint** — `./scripts/lint` |
| 103 | +2. **build** — `./scripts/build` |
| 104 | +3. **test** — `./scripts/test` |
| 105 | + |
| 106 | +All three must pass before merging. |
| 107 | + |
| 108 | +## Code style |
| 109 | + |
| 110 | +See [AGENTS.md](AGENTS.md) for detailed Kotlin conventions, including: |
| 111 | + |
| 112 | +- Prefer `buildMap`/`buildList` over mutable collections |
| 113 | +- Use `partition` instead of double `filter` |
| 114 | +- Use parameterized tests for table-driven cases |
| 115 | +- Avoid `@Suppress("UNCHECKED_CAST")` — restructure with safe casts |
| 116 | +- `toString()` should follow the `ClassName{field=value}` convention |
| 117 | + |
| 118 | +## Dependencies |
| 119 | + |
| 120 | +- **Anthropic SDK** is a `compileOnly` dependency — users must add it themselves. Methods using Anthropic types should catch `NoClassDefFoundError` and throw `IllegalStateException` with a clear message. |
| 121 | +- **SLF4J** (`slf4j-api`) is an `api` dependency for logging. Tests use `slf4j-simple`. |
| 122 | +- **Jackson** 2.18.2 is the default, but the SDK is compatible with 2.13.4+. Tests compile against 2.14.0. |
0 commit comments