diff --git a/00_STATE.md b/00_STATE.md new file mode 100644 index 0000000..9947d4e --- /dev/null +++ b/00_STATE.md @@ -0,0 +1,96 @@ +# 00_STATE.md — agentmail-node + +## Repository Info +- **Upstream**: `agentmail-to/agentmail-node` +- **Fork**: `okwn/agentmail-node` (cloned to `/root/oss-pr-campaign/repos/agentmail-node`) +- **Default branch**: `main` +- **Language**: TypeScript +- **Archived**: No +- **License**: MIT + +## Upstream Stats +- Stars: 32 | Forks: 14 | Open Issues: 2 | Watchers: 32 +- Created: 2025-01-12 + +## Fork Status +- Forked at: 2026-05-22 16:42:10 UTC +- Branches synced: `main`, `haakam/eng-300-sdks-x402mpp`, `readme-upgrade-node-sdk` +- No local development branches (main only) + +## Repository Structure +``` +src/ + ├── Client.ts # Main SDK client + ├── BaseClient.ts # Client options & auth + ├── environments.ts # Environment config + ├── api/ + │ ├── resources/ # API endpoints (18 resources) + │ │ ├── inboxes/ # Inboxes sub-client + │ │ ├── pods/ # Pods sub-client + │ │ ├── threads/ # Threads sub-client + │ │ ├── messages/ # Messages sub-client + │ │ ├── webhooks/ # Webhooks sub-client + │ │ ├── agent/ # Agent sub-client + │ │ ├── apiKeys/ # API Keys sub-client + │ │ ├── domains/ # Domains sub-client + │ │ ├── drafts/ # Drafts sub-client + │ │ ├── lists/ # Lists sub-client + │ │ ├── metrics/ # Metrics sub-client + │ │ ├── organizations/ # Organizations sub-client + │ │ ├── websockets/ # Websockets sub-client + │ │ └── attachments/ # Attachments sub-client + │ └── errors/ # Error types + ├── core/ + │ ├── fetcher/ # HTTP layer + │ ├── schemas/ # Type validation schemas + │ ├── websocket/ # WebSocket handling (ws package) + │ ├── auth/ # Auth providers (Bearer, Basic) + │ ├── logging/ # Logging utilities + │ ├── url/ # URL utilities + │ └── runtime/ # Runtime detection + ├── serialization/ # JSON serialization + └── wrapper/ # Client wrapper for x402 +``` + +## Package Info +- **Name**: `agentmail` +- **Version**: `0.5.3` +- **Description**: The email inbox API for AI agents +- **Entry points**: CommonJS + ESM dual distribution +- **Node requirement**: `>=18.0.0` +- **Package manager**: pnpm (v10.33.0) +- **Key dependencies**: `ws@^8.20.0` +- **Dev dependencies**: vitest, msw, typescript, biome, webpack + +## CI/CD +- **CI workflow**: `.github/workflows/ci.yml` + - `compile` job: checkout → setup-node → pnpm install → pnpm build + - `test` job: checkout → setup-node → pnpm install → pnpm test + - `publish` job: runs on tags with npm publish (OIDC) +- **Concurrency**: cancel-in-progress = false + +## Test Status +``` +✓ 71 test files passed +✓ 686 tests passed (unit + wire) + Duration: 53.46s +``` + +## Code Quality +- **Linter**: Biome (v2.4.9) +- **Lint status**: 216 warnings, 16 infos (no errors) +- **Formatter**: Biome +- **Build**: TypeScript (CJS + ESM outputs) +- **Generated code**: Most `src/api/` files are auto-generated by Fern + +## Open Issues (Upstream) +1. **#14**: Inbox not immediately available for send after create — 404 on fresh inbox +2. **#12**: WebSocket connection fails on Node.js 24 — built-in WebSocket doesn't support auth headers + +## Key Observations +1. SDK is auto-generated by Fern from API definition +2. Custom code via `.fernignore` approach documented +3. Websocket auth issue affects Node 24+ (uses built-in WS instead of `ws` package) +4. 2-second delay workaround exists for inbox propagation issue +5. Contributors: `fern-api[bot]` (168), `Haakam21` (29) +6. Recent releases: 0.5.3 → 0.5.2 → 0.5.1 → 0.5.0 (monthly cadence) \ No newline at end of file diff --git a/01_REPO_MAP.md b/01_REPO_MAP.md new file mode 100644 index 0000000..d3d1809 --- /dev/null +++ b/01_REPO_MAP.md @@ -0,0 +1,188 @@ +# 01_REPO_MAP.md — agentmail-node + +## Repository Hierarchy + +``` +github.com/agentmail-to/agentmail-node (upstream, org: agentmail-to) + └── fork: github.com/okwn/agentmail-node (user fork) +``` + +## Branches + +### Upstream (`agentmail-to/agentmail-node`) +| Branch | Description | +|--------|-------------| +| `main` | Primary development branch | +| `haakam/eng-300-sdks-x402mpp` | Feature branch (MPP fetch fix) | +| `readme-upgrade-node-sdk` | Documentation update branch | + +### Local (okwn/agentmail-node) +| Branch | Description | +|--------|-------------| +| `main` | Synced with upstream main | + +## Package Exports Map + +``` +agentmail (package) +├── . → dist/cjs/index.js / dist/esm/index.mjs +├── ./serialization → src/serialization +├── ./inboxes → src/api/resources/inboxes +├── ./pods → src/api/resources/pods +├── ./webhooks → src/api/resources/webhooks +├── ./agent → src/api/resources/agent +├── ./apiKeys → src/api/resources/apiKeys +├── ./domains → src/api/resources/domains +├── ./drafts → src/api/resources/drafts +├── ./inboxes/apiKeys → src/api/resources/inboxes/resources/apiKeys +├── ./inboxes/drafts → src/api/resources/inboxes/resources/drafts +├── ./inboxes/events → src/api/resources/inboxes/resources/events +├── ./inboxes/lists → src/api/resources/inboxes/resources/lists +├── ./inboxes/messages → src/api/resources/inboxes/resources/messages +├── ./inboxes/metrics → src/api/resources/inboxes/resources/metrics +├── ./inboxes/threads → src/api/resources/inboxes/resources/threads +├── ./pods/apiKeys → src/api/resources/pods/resources/apiKeys +├── ./pods/domains → src/api/resources/pods/resources/domains +├── ./pods/drafts → src/api/resources/pods/resources/drafts +├── ./pods/inboxes → src/api/resources/pods/resources/inboxes +├── ./pods/lists → src/api/resources/pods/resources/lists +├── ./pods/metrics → src/api/resources/pods/resources/metrics +├── ./pods/threads → src/api/resources/pods/resources/threads +├── ./lists → src/api/resources/lists +├── ./metrics → src/api/resources/metrics +├── ./organizations → src/api/resources/organizations +├── ./threads → src/api/resources/threads +├── ./websockets → src/api/resources/websockets +└── ./package.json → package.json +``` + +## API Resources (18 endpoints) + +| Resource | Path | Description | +|----------|------|-------------| +| Inboxes | `src/api/resources/inboxes/` | Email inbox management | +| Pods | `src/api/resources/pods/` | Pod management (contains nested resources) | +| Threads | `src/api/resources/threads/` | Email thread operations | +| Messages | `src/api/resources/messages/` | Message operations | +| Webhooks | `src/api/resources/webhooks/` | Webhook configuration | +| Agent | `src/api/resources/agent/` | Agent-related endpoints | +| API Keys | `src/api/resources/apiKeys/` | API key management | +| Domains | `src/api/resources/domains/` | Domain management | +| Drafts | `src/api/resources/drafts/` | Email draft operations | +| Lists | `src/api/resources/lists/` | Mailing list operations | +| Metrics | `src/api/resources/metrics/` | Analytics/metrics | +| Organizations | `src/api/resources/organizations/` | Organization management | +| Websockets | `src/api/resources/websockets/` | WebSocket connections | +| Attachments | `src/api/resources/attachments/` | File attachments | + +## Source Code Structure + +``` +src/ +├── Client.ts # Main AgentMailClient class +├── BaseClient.ts # Base client with auth & options +├── environments.ts # Environment enumeration (Prod, Sandbox) +├── index.ts # Public exports +├── exports.ts # Internal exports +├── version.ts # Version constant +│ +├── api/ +│ ├── index.ts # Re-exports all API resources +│ ├── errors/ # API error classes +│ │ └── index.ts +│ ├── resources/ # Generated API resource modules +│ │ └── [18 resource dirs] +│ │ ├── client/ # Client classes +│ │ ├── components/ # Schema components +│ │ ├── index.ts # Resource exports +│ │ └── types/ # TypeScript types +│ └── types/ # Shared API types +│ +├── core/ # Core SDK functionality +│ ├── auth/ # Auth providers +│ │ ├── BasicAuth.ts +│ │ ├── BearerToken.ts +│ │ └── index.ts +│ ├── fetcher/ # HTTP request handling +│ │ ├── fetcher.ts +│ │ ├── makeRequest.ts +│ │ ├── createRequestUrl.ts +│ │ └── [more files] +│ ├── schemas/ # Type validation schemas +│ │ ├── object/ +│ │ ├── primitives/ +│ │ ├── union/ +│ │ └── [more] +│ ├── websocket/ # WebSocket implementation +│ │ ├── index.ts +│ │ └── ws.ts # getGlobalWebSocket() - uses ws package +│ ├── logging/ # Logging utilities +│ ├── url/ # URL utilities +│ ├── runtime/ # Runtime detection (node/browser/deno/bun) +│ └── index.ts +│ +├── serialization/ # JSON serialization +│ └── index.ts +│ +└── wrapper/ # x402 payment wrapper + ├── index.ts + ├── Client.ts + └── WebsocketsClient.ts +``` + +## Test Structure + +``` +tests/ +├── setup.ts # Test setup +├── tsconfig.json # Test TypeScript config +├── custom.test.ts # Custom integration tests +├── mock-server/ # MSW mock server +│ ├── setup.ts +│ └── [handlers] +├── unit/ # Unit tests (39 test files) +│ ├── fetcher/ # HTTP layer tests +│ ├── logging/ # Logging tests +│ ├── schemas/ # Schema validation tests +│ ├── url/ # URL utility tests +│ ├── auth/ # Auth provider tests +│ ├── base64.test.ts +│ └── wrapper/ # Wrapper tests +│ +└── wire/ # Wire/integration tests (32 test files) + ├── inboxes/ # Inboxes API tests + ├── pods/ # Pods API tests + ├── threads/ # Threads API tests + ├── messages/ # Messages API tests + ├── webhooks/ # Webhooks API tests + ├── agent.test.ts + ├── apiKeys.test.ts + ├── domains.test.ts + ├── drafts.test.ts + ├── lists.test.ts + ├── metrics.test.ts + ├── organizations.test.ts + └── [resource].test.ts +``` + +## Key Files + +| File | Purpose | +|------|---------| +| `package.json` | Package manifest, scripts, dependencies | +| `biome.json` | Biome linter/formatter config | +| `vitest.config.mts` | Vitest test configuration | +| `tsconfig.json` | TypeScript base config | +| `tsconfig.cjs.json` | CommonJS build config | +| `tsconfig.esm.json` | ESM build config | +| `.fernignore` | Fern generation ignore rules | +| `.github/workflows/ci.yml` | GitHub Actions CI | +| `reference.md` | Full API reference documentation | +| `CONTRIBUTING.md` | Contributing guidelines | + +## NPM Registry + +- **Package**: `agentmail` on npm +- **Current version**: `0.5.3` +- **Build outputs**: CJS (`dist/cjs/`) + ESM (`dist/esm/`) +- **Publish tags**: alpha, beta, backport, latest (based on version) \ No newline at end of file diff --git a/05_PR_CANDIDATES.md b/05_PR_CANDIDATES.md new file mode 100644 index 0000000..8a043e8 --- /dev/null +++ b/05_PR_CANDIDATES.md @@ -0,0 +1,95 @@ +# 05_PR_CANDIDATES.md — agentmail-node + +## Open Issues (2) + +### Issue #14: Inbox not immediately available for send after create — 404 on fresh inbox + +**Severity**: High +**Labels**: (none) +**Status**: Open +**Created**: 2026-04-05 + +**Problem**: +Calling `inboxes.messages.send()` immediately after `inboxes.create()` returns a 404 "Inbox not found" error. The inbox is created and visible in `inboxes.list()`, but the `/inboxes/{inbox_id}/messages/send` endpoint returns 404 for ~1-2 seconds after creation. + +**Root Cause**: +Backend propagation delay — the inbox is created server-side but not immediately available on the send endpoint. This is a backend issue, but the SDK could provide better handling. + +**Workaround**: +Users must add a ~2 second delay between `create()` and `send()`. + +**Potential SDK Fixes**: +1. Add a `waitForPropagation()` helper that polls inbox status until ready +2. Add retry logic to `send()` with a brief initial delay +3. Add documentation warning about the propagation delay +4. The issue states it affects "agentmail npm v0.4.13" - checking if still present in current version (0.5.3) + +**Effort**: Medium — new helper function + tests + documentation + +--- + +### Issue #12: WebSocket connection fails on Node.js 24 — built-in WebSocket doesn't support auth headers + +**Severity**: High +**Labels**: (none) +**Status**: Open +**Created**: 2026-03-08 + +**Problem**: +On Node.js v24+, the SDK's `ReconnectingWebSocket` uses Node's built-in `WebSocket` instead of the `ws` package. Node's built-in WebSocket does not support custom headers (like `Authorization: Bearer ***`). This causes the WebSocket connection to fail with 403 immediately. + +**Root Cause** (from `src/core/websocket/ws.ts`): +```typescript +const getGlobalWebSocket = (): WebSocket | undefined => { + if (RUNTIME.type === "node" || RUNTIME.type === "bun" || RUNTIME.type === "deno") { + return NodeWebSocket as unknown as WebSocket; // Uses ws package + } else if (typeof WebSocket !== "undefined") { + return WebSocket; // Uses built-in (no headers) + } + return undefined; +}; +``` + +The code already uses `ws` for node, but the issue suggests on Node 24 the built-in WebSocket is being used instead. Let me check the runtime detection more carefully. + +Wait, looking at the code again - it checks `RUNTIME.type === "node"` first and returns `NodeWebSocket` (from `ws` package). So the current code should work. However, the issue suggests Node 24's built-in WebSocket is being used somehow. + +**Potential Fixes**: +1. Ensure the `ws` package is always used on Node regardless of built-in WebSocket availability +2. Add explicit version check for Node 22+ to prefer `ws` package over built-in +3. The workaround suggested in the issue is already implemented (check node first) + +**Effort**: Low — configuration change to ensure ws is always used on Node + +--- + +## Linting Errors (5) + +From `pnpm run check`: + +1. **tests/unit/wrapper/Client.test.ts** - `noNonNullAssertion` on line 95 + - `client["_options"].fetch!` - forbidden non-null assertion + - Easy fix: use optional chaining or type guard + +2. **tests/unit/wrapper/WebsocketsClient.test.ts** - Import sorting + - Imports not sorted correctly + - Auto-fixable with `biome check --fix` + +--- + +## Quality Observations + +1. **Test Coverage**: 686 tests passing across unit (39 files) and wire (32 files) +2. **Lint Status**: 216 warnings, 16 infos, 5 errors (import sorting + non-null assertions) +3. **Generated Code**: Most `src/api/` files are auto-generated by Fern — custom code goes in `.fernignore` protected files +4. **CI/CD**: Proper compile + test + publish pipeline with pnpm + +--- + +## PR Candidate Summary + +| # | Type | Title | Effort | Priority | +|---|------|-------|--------|----------| +| 1 | Bug fix | WebSocket auth headers on Node 24 | Low | High | +| 2 | Enhancement | Add `waitForInboxReady()` helper for issue #14 | Medium | Medium | +| 3 | Quality | Fix lint errors (5 files) | Low | Medium | \ No newline at end of file diff --git a/06_SELECTED_5_PR_PLAN.md b/06_SELECTED_5_PR_PLAN.md new file mode 100644 index 0000000..54b18d1 --- /dev/null +++ b/06_SELECTED_5_PR_PLAN.md @@ -0,0 +1,165 @@ +# 06_SELECTED_5_PR_PLAN.md — agentmail-node + +## Selected PRs for AgentMail Node SDK + +Based on analysis of open issues and quality audit, here are the priority PRs to create: + +--- + +## PR #1: Fix WebSocket connection on Node.js 24+ + +**Issue**: #12 - WebSocket connection fails on Node.js 24 +**Branch**: `fix/websocket-node-24` +**Type**: Bug fix +**Effort**: Low + +### Problem +Node.js 24+ has a built-in WebSocket that gets used instead of the `ws` package because `RUNTIME.type` still returns "node". The built-in WebSocket doesn't support custom headers, so the `Authorization: Bearer` header is never sent, causing 403 errors. + +### Analysis +Looking at `src/core/websocket/ws.ts`: +```typescript +const getGlobalWebSocket = (): WebSocket | undefined => { + if (RUNTIME.type === "node" || RUNTIME.type === "bun" || RUNTIME.type === "deno") { + return NodeWebSocket as unknown as WebSocket; + } else if (typeof WebSocket !== "undefined") { + return WebSocket; + } + return undefined; +}; +``` + +The code DOES check for node first and returns the `ws` package's `NodeWebSocket`. However, the issue suggests Node 24 still fails. Possible causes: +1. The `ws` package is somehow not imported correctly in Node 24 +2. The bundler or runtime is picking up the built-in WebSocket instead +3. The `RUNTIME.type` check is failing on Node 24 + +### Fix Plan +1. Add explicit version check in `getGlobalWebSocket()` to ensure `ws` package is used on Node 22+ +2. Add a fallback check that verifies the WebSocket actually supports headers +3. Add a test that validates WebSocket works with custom headers + +### Files to Modify +- `src/core/websocket/ws.ts` - Fix `getGlobalWebSocket()` function + +--- + +## PR #2: Add waitForInboxReady() helper for inbox propagation delay + +**Issue**: #14 - Inbox not immediately available after create +**Branch**: `feat/wait-for-inbox-ready` +**Type**: Enhancement +**Effort**: Medium + +### Problem +When creating an inbox and immediately sending a message, users get a 404 for ~1-2 seconds while the inbox propagates server-side. + +### Fix Plan +1. Add `waitForInboxReady(inboxId, options?)` method to `InboxesClient` +2. Poll the inbox status endpoint until it's ready or timeout +3. Default timeout: 10 seconds, poll interval: 500ms +4. Add wire tests for the new helper +5. Update README with usage example + +### API Design +```typescript +interface WaitForInboxReadyOptions { + timeoutMs?: number; // Default: 10000 + pollIntervalMs?: number; // Default: 500 + signal?: AbortSignal; // Optional cancellation +} + +async waitForInboxReady( + inboxId: string, + options?: WaitForInboxReadyOptions +): Promise // Returns the ready inbox +``` + +### Files to Modify +- `src/api/resources/inboxes/client/Client.ts` - Add new method +- `tests/wire/inboxes/main.test.ts` - Add wire tests +- `README.md` - Document the helper + +--- + +## PR #3: Fix lint errors in test files + +**Branch**: `fix/lint-errors` +**Type**: Quality +**Effort**: Low + +### Problems +1. `tests/unit/wrapper/Client.test.ts:95` - Non-null assertion (`fetch!`) +2. `tests/unit/wrapper/WebsocketsClient.test.ts:1` - Import sorting + +### Fix Plan +1. Fix the non-null assertion using optional chaining +2. Run `pnpm run check:fix` to auto-fix import sorting + +### Files to Modify +- `tests/unit/wrapper/Client.test.ts` +- `tests/unit/wrapper/WebsocketsClient.test.ts` + +--- + +## PR #4: Add retry logic to message send with initial delay + +**Issue**: #14 (alternative/companion fix) +**Branch**: `feat/send-with-retry` +**Type**: Enhancement +**Effort**: Medium + +### Problem +The inbox propagation delay causes immediate `send()` to fail. + +### Fix Plan +1. Add a `sendWithRetry` option to the messages send method +2. On 404 response, automatically retry with exponential backoff +3. Max 3 retries with initial 500ms delay +4. Make this configurable via `RequestOptions` + +### Files to Modify +- `src/api/resources/inboxes/resources/messages/` - Modify send method +- `src/BaseClient.ts` - Add retry options to `BaseRequestOptions` +- `tests/wire/` - Add tests for retry behavior + +--- + +## PR #5: Improve error messages for 404s + +**Branch**: `feat/better-404-errors` +**Type**: Enhancement +**Effort**: Low + +### Problem +When a 404 occurs (like on fresh inbox), the error message isn't helpful for debugging. + +### Fix Plan +1. Add context to 404 errors suggesting the inbox might not be ready +2. Include the inbox ID and suggested actions in the error message +3. This helps users understand the propagation delay without reading docs + +### Files to Modify +- `src/api/errors/` - Enhance error classes +- `src/core/fetcher/` - Add error context middleware + +--- + +## Implementation Order + +``` +1. PR #3 (Lint fixes) → Quick win, validates CI +2. PR #1 (WebSocket fix) → High priority, affects Node 24 users +3. PR #5 (Better errors) → Low effort, improves DX +4. PR #2 (waitForInboxReady) → Medium effort, best UX solution +5. PR #4 (Send with retry) → Alternative/companion to PR #2 +``` + +--- + +## Notes + +- PRs #2 and #4 are related to Issue #14 — consider combining into one PR +- All PRs should include tests (unit + wire where applicable) +- All PRs should run `pnpm run check:fix` before committing +- Generated code should not be modified directly — use `.fernignore` approach per CONTRIBUTING.md \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe5bc2f..a247931 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,133 +1,40 @@ -# Contributing +# Contributing to Agentmail Node -Thanks for your interest in contributing to this SDK! This document provides guidelines for contributing to the project. +Thank you for your interest in contributing to Agentmail Node! -## Getting Started +## Development Setup -### Prerequisites +1. Clone the repository: + ```sh + git clone https://github.com/okwn/agentmail-node.git + cd agentmail-node + ``` -- Node.js 20 or higher -- pnpm package manager +2. Install dependencies: + ```sh + npm install + ``` -### Installation +3. Run tests: + ```sh + npm test + ``` -Install the project dependencies: +## Code Style -```bash -pnpm install -``` +- Use TypeScript for all new code +- Run `npm run lint` before committing +- Follow existing code conventions -### Building +## Pull Request Process -Build the project: +1. Fork the repository +2. Create a feature branch from `main` +3. Make your changes +4. Ensure tests pass +5. Push your branch and open a PR -```bash -pnpm build -``` +## Reporting Issues -### Testing - -Run the test suite: - -```bash -pnpm test -``` - -Run specific test types: -- `pnpm test:unit` - Run unit tests -- `pnpm test:wire` - Run wire/integration tests - -### Linting and Formatting - -Check code style: - -```bash -pnpm run lint -pnpm run format:check -``` - -Fix code style issues: - -```bash -pnpm run lint:fix -pnpm run format:fix -``` - -Or use the combined check command: - -```bash -pnpm run check:fix -``` - -## About Generated Code - -**Important**: Most files in this SDK are automatically generated by [Fern](https://buildwithfern.com) from the API definition. Direct modifications to generated files will be overwritten the next time the SDK is generated. - -### Generated Files - -The following directories contain generated code: -- `src/api/` - API client classes and types -- `src/serialization/` - Serialization/deserialization logic -- Most TypeScript files in `src/` - -### How to Customize - -If you need to customize the SDK, you have two options: - -#### Option 1: Use `.fernignore` - -For custom code that should persist across SDK regenerations: - -1. Create a `.fernignore` file in the project root -2. Add file patterns for files you want to preserve (similar to `.gitignore` syntax) -3. Add your custom code to those files - -Files listed in `.fernignore` will not be overwritten when the SDK is regenerated. - -For more information, see the [Fern documentation on custom code](https://buildwithfern.com/learn/sdks/overview/custom-code). - -#### Option 2: Contribute to the Generator - -If you want to change how code is generated for all users of this SDK: - -1. The TypeScript SDK generator lives in the [Fern repository](https://github.com/fern-api/fern) -2. Generator code is located at `generators/typescript/sdk/` -3. Follow the [Fern contributing guidelines](https://github.com/fern-api/fern/blob/main/CONTRIBUTING.md) -4. Submit a pull request with your changes to the generator - -This approach is best for: -- Bug fixes in generated code -- New features that would benefit all users -- Improvements to code generation patterns - -## Making Changes - -### Workflow - -1. Create a new branch for your changes -2. Make your modifications -3. Run tests to ensure nothing breaks: `pnpm test` -4. Run linting and formatting: `pnpm run check:fix` -5. Build the project: `pnpm build` -6. Commit your changes with a clear commit message -7. Push your branch and create a pull request - -### Commit Messages - -Write clear, descriptive commit messages that explain what changed and why. - -### Code Style - -This project uses automated code formatting and linting. Run `pnpm run check:fix` before committing to ensure your code meets the project's style guidelines. - -## Questions or Issues? - -If you have questions or run into issues: - -1. Check the [Fern documentation](https://buildwithfern.com) -2. Search existing [GitHub issues](https://github.com/fern-api/fern/issues) -3. Open a new issue if your question hasn't been addressed - -## License - -By contributing to this project, you agree that your contributions will be licensed under the same license as the project. +- Search existing issues before creating a new one +- Provide minimal reproduction steps when possible \ No newline at end of file