feat(tools): add OptionsAhoyTool for equity-compensation tax calculations#6148
feat(tools): add OptionsAhoyTool for equity-compensation tax calculations#6148AlvisoOculus wants to merge 4 commits into
Conversation
…ions Add a keyless OptionsAhoyTool that wraps the OptionsAhoy public REST API. A single tool exposes seven calculators via a calculator selector and an inputs object: incentive stock option (ISO) exercise under the alternative minimum tax (AMT), non-qualified stock option (NSO) exercise, restricted stock unit (RSU) sell-versus-hold, single-stock concentration, protective put pricing, qualified small business stock (QSBS) eligibility, and funding a cash goal from equity lots. Uses the existing requests dependency, requires no API key, and registers in the package exports. Includes a README and mocked unit tests with no network access.
📝 WalkthroughWalkthroughThis PR adds a new OptionsAhoyTool that integrates with the public OptionsAhoy REST API (seven calculators). It includes input schema and validation, payload construction (preserving nullable terminationDate), HTTP POST execution with structured error handling, tests, README, and package exports. ChangesOptionsAhoy Tool Integration
sequenceDiagram
participant Caller
participant OptionsAhoyTool
participant Validator
participant PayloadBuilder
participant OptionsAhoyAPI
Caller->>OptionsAhoyTool: run(calculator, inputs)
OptionsAhoyTool->>Validator: _check_required(calculator, inputs)
Validator-->>OptionsAhoyTool: validated
OptionsAhoyTool->>PayloadBuilder: _build_payload(inputs)
PayloadBuilder-->>OptionsAhoyTool: payload (None filtered except terminationDate)
OptionsAhoyTool->>OptionsAhoyAPI: POST /api/v1/{calculator} with JSON + timeout
alt Success (200 + JSON)
OptionsAhoyAPI-->>OptionsAhoyTool: JSON response
OptionsAhoyTool-->>Caller: pretty JSON string (result)
else HTTPError
OptionsAhoyAPI-->>OptionsAhoyTool: error response
OptionsAhoyTool-->>Caller: structured error JSON (status + parsed body)
else Request Exception
OptionsAhoyAPI-->>OptionsAhoyTool: connection/timeout error
OptionsAhoyTool-->>Caller: structured error JSON (exception message)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
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
`@lib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/optionsahoy_tool.py`:
- Around line 159-173: The pre-flight check in _check_required only tests for
presence of keys and therefore misses required inputs that are present but set
to None (which _build_payload later strips), so update _check_required to treat
a required field as missing when it is either not present in inputs or its value
is None (except for keys explicitly allowed to be null via _KEEP_NULL, e.g.,
terminationDate); change the missing list comprehension to something like:
missing = [field for field in required if field not in inputs or
(inputs.get(field) is None and field not in _KEEP_NULL)] so validation fails for
None-valued required fields.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 1745a862-741a-4085-a267-ab15bf6d3ff3
📒 Files selected for processing (6)
lib/crewai-tools/src/crewai_tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/README.mdlib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/__init__.pylib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/optionsahoy_tool.pylib/crewai-tools/tests/tools/optionsahoy_tool_test.py
|
Thanks for the catch. Fixed: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
lib/crewai-tools/tests/tools/optionsahoy_tool_test.py (1)
100-114: ⚡ Quick winTighten the regression assertion to the specific missing field.
The current regex is broad and can pass for unrelated missing-field failures. Assert that
strikeis the reported missing required field to keep this regression precise.Suggested test assertion update
- with pytest.raises(ValueError, match="missing required input field"): + with pytest.raises( + ValueError, match=r"missing required input field\(s\): strike" + ):🤖 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 `@lib/crewai-tools/tests/tools/optionsahoy_tool_test.py` around lines 100 - 114, The test's ValueError assertion is too generic; update the pytest.raises match to assert the error specifically names the missing "strike" field by changing match="missing required input field" to a tighter pattern that includes "strike" (for example match="missing required input field.*strike" or an exact message mentioning strike) for the tool.run call so the regression verifies that "strike" is the reported missing field.
🤖 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.
Nitpick comments:
In `@lib/crewai-tools/tests/tools/optionsahoy_tool_test.py`:
- Around line 100-114: The test's ValueError assertion is too generic; update
the pytest.raises match to assert the error specifically names the missing
"strike" field by changing match="missing required input field" to a tighter
pattern that includes "strike" (for example match="missing required input
field.*strike" or an exact message mentioning strike) for the tool.run call so
the regression verifies that "strike" is the reported missing field.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 3b556726-1bbd-49c3-a5ed-c1a53b87020b
📒 Files selected for processing (2)
lib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/optionsahoy_tool.pylib/crewai-tools/tests/tools/optionsahoy_tool_test.py
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/optionsahoy_tool.py
|
Thanks for the review. The one item CodeRabbit flagged is addressed: required fields whose value is The branch has fallen a little behind |
|
Quick status nudge on this one. It's approved by the review bot and now conflict-free with Is there anything else you'd like changed before this can be considered for merge? Happy to address any feedback. Thanks for crewAI. @greysonlalonde if you have a moment to take a look, much appreciated. |
Summary
Adds
OptionsAhoyTool, a built-in tool that computes the tax outcome of common equity-compensation decisions using the OptionsAhoy public REST API. Each calculation runs against the federal tax code and all fifty states plus the District of Columbia.The API is keyless, so the tool needs no API key and no new dependency. It uses
requests, which is already a core dependency.A single tool exposes seven calculators through a
calculatorselector and aninputsobject:amt-iso: optimize a multi-year incentive stock option (ISO) exercise schedule under the alternative minimum tax (AMT)nso: tax and after-tax proceeds of exercising non-qualified stock options (NSOs), holding versus sellingrsu-sell-vs-hold: selling vested restricted stock units (RSUs) at vest versus holding, on an after-tax, risk-adjusted basisconcentration: analyze a concentrated single-stock position and the after-tax cost of diversifying itprotective-put: price a protective put hedge at a given downside protection level and tenorqsbs: check qualified small business stock (QSBS) eligibility and the resulting capital-gains exclusionequity-funding: plan which equity lots to sell, and when, to fund a cash goal by a target date at the least after-tax costThis follows the existing single-API tool pattern in the catalog (for example
SerperDevTool, which also wraps one provider's HTTP endpoint withrequests).Usage
Changes
lib/crewai-tools/src/crewai_tools/tools/optionsahoy_tool/— tool, package__init__.py, and READMEOptionsAhoyToolincrewai_tools/tools/__init__.pyandcrewai_tools/__init__.pylib/crewai-tools/tests/tools/optionsahoy_tool_test.py— unit tests (mocked HTTP, no network, no key)Testing
uv run pytest tests/tools/optionsahoy_tool_test.py— 7 passeduv run ruff checkandruff format --check— cleanuv run pyrighton the new files — 0 errorsSummary by CodeRabbit
New Features
Documentation
Tests