Skip to content

[MISC] Fix adapter-ops skill cost-tracking guidance and stale paths#2163

Merged
chandrasekharan-zipstack merged 4 commits into
mainfrom
misc/adapter-ops-cost-guidance
Jul 14, 2026
Merged

[MISC] Fix adapter-ops skill cost-tracking guidance and stale paths#2163
chandrasekharan-zipstack merged 4 commits into
mainfrom
misc/adapter-ops-cost-guidance

Conversation

@chandrasekharan-zipstack

Copy link
Copy Markdown
Contributor

What

Fixes the adapter-ops skill, which gave adapter authors incorrect guidance about cost tracking and shipped broken script paths.

Why

The cost guidance was wrong

The skill said, in three places, that get_provider() drives cost calculation, and pointed at platform-service/src/unstract/platform_service/helper/cost_calculation.py as the enforcement site.

That file no longer exists. provider is now just a metadata column on the usage row (sdk1/audit.py), never consulted for pricing.

Cost is actually looked up from the prefixed model string that validate_model() emits:

Path Site
LLM sdk1/audit.pycost_per_token(model=model_name)
Embedding sdk1/usage_handler.pylitellm.cost_per_token(...)

Both call sites catch every exception and fall back to 0.0. A miss is silent — no test fails, no build breaks. The only symptom is revenue-affecting: zero-cost usage rows.

This gap has already bitten us

PR #2156 (MiniMax LLM adapter) follows the skill's documented check correctlyget_provider() returns "minimax", which matches LiteLLM's litellm_provider exactly — and still bills $0. It subclasses OpenAICompatibleLLMParameters, whose validate_model() unconditionally prepends custom_openai/, and no LiteLLM cost-map key uses that prefix:

cost_per_token("custom_openai/MiniMax-M3") -> raises  => cost = 0.0
cost_per_token("minimax/MiniMax-M3")       -> $0.30 / $1.20 per 1M tokens

A correct get_provider() does not, on its own, guarantee cost resolution. The skill never said so.

What changed

  • Reframed the mandatory check from "verify the provider name" to "verify the model prefix resolves in LiteLLM's cost map", with the real call sites named.

  • Added a base-class decision table. If LiteLLM has a native provider for the vendor → BaseChatCompletionParameters, emit {provider}/{model} (follow OpenRouterLLMParameters). If LiteLLM prices nothing for the vendor → OpenAICompatibleLLMParameters, pin api_base (follow NvidiaBuildLLMParameters).

    NvidiaBuildLLMParameters is only a safe template because LiteLLM prices zero nvidia_nim/ chat models (3 entries, all rerankers, all $0.0) — there is no cost to forfeit. Copying its shape for a vendor LiteLLM does price is how Add MiniMax LLM adapter #2156 went wrong.

  • Swapped curl of upstream model_prices_and_context_window.json for a snippet that queries the pinned LiteLLM in the sdk1 venv — the version that actually runs.

  • Re-scoped get_provider() to what it genuinely controls: the static schema path (static/{get_provider()}.json, case-sensitive) and the usage row's provider column.

  • Repointed every documented script path from the skill's old directory name (unstract-adapter-extension) to adapter-ops. Every copy-pasteable command in SKILL.md was broken.

Checks

The verification snippet now documented in the skill was run as written and reproduces the bug it exists to catch:

$ cd unstract/sdk1 && uv run python -c "..."
[<LlmProviders.MINIMAX: 'minimax'>]
['minimax/speech-02-hd', 'minimax/speech-02-turbo', 'minimax/speech-2.6-hd']
minimax/MiniMax-M3 (0.3, 1.2)
custom_openai/MiniMax-M3 RAISES => cost silently recorded as 0.0

Docs-only change to .claude/skills/ — no runtime code touched. Pre-commit hooks pass (ruff, ruff-format, markdownlint, secret scan).

🤖 Generated with Claude Code

https://claude.ai/code/session_015i26iF1GS3x55XHEjStUeP

The skill told adapter authors that `get_provider()` drives cost
calculation and pointed at
`platform-service/.../helper/cost_calculation.py` as the enforcement
site. That file no longer exists, and `provider` is now only a metadata
column on the usage row.

Cost is actually looked up from the prefixed model string that
`validate_model()` emits, via `litellm.cost_per_token()` in
`sdk1/audit.py` (LLM) and `sdk1/usage_handler.py` (embedding). Both call
sites swallow the exception and fall back to $0, so a miss is silent.

This gap let a branded OpenAI-compatible adapter pass the documented
check — returning a `get_provider()` that matches `litellm_provider`
exactly — while still billing $0, because `OpenAICompatibleLLMParameters`
prepends `custom_openai/` and no cost-map key uses that prefix.

Rewrite the guidance to verify the model prefix instead, add a base-class
decision table (native LiteLLM provider -> BaseChatCompletionParameters;
no priced models -> OpenAICompatibleLLMParameters), and swap the curl of
upstream JSON for a snippet that queries the pinned LiteLLM in the sdk1
venv.

Also repoint every documented script path from the skill's old directory
name (`unstract-adapter-extension`) to `adapter-ops`; all copy-pasteable
commands in SKILL.md were broken.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015i26iF1GS3x55XHEjStUeP
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 885b235e-58bf-43b1-9fcc-305c7566eff0

📥 Commits

Reviewing files that changed from the base of the PR and between 4f7bcbc and cbfee5c.

📒 Files selected for processing (1)
  • .claude/skills/adapter-ops/SKILL.md

Summary by CodeRabbit

  • Documentation
    • Updated adapter-ops guidance to use the current script locations and command paths.
    • Replaced provider-name verification with critical model-prefix verification based on the validated model string used for LiteLLM cost lookups.
    • Clarified how missing pricing entries can lead to $0 and how to verify prefix resolution against the pinned LiteLLM.
    • Expanded guidance for OpenAI-compatible/branded adapters to avoid model-key mismatches (e.g., custom_openai/*).
  • Chores
    • Adjusted adapter update script logging: informational output now goes to stderr, while JSON output remains on stdout.

Walkthrough

Updated adapter-ops command documentation and repository-root references, changed update-checker output handling, and replaced provider-name validation guidance with prefixed model verification focused on LiteLLM cost tracking and OpenAI-compatible adapter prefixes.

Changes

Adapter operations guidance

Layer / File(s) Summary
Script paths and operational behavior
.claude/skills/adapter-ops/SKILL.md, .claude/skills/adapter-ops/scripts/*
Commands now reference the current adapter-ops scripts directory, initializer repository-root references match the layout, and update-checker diagnostics are written to stderr for parseable JSON stdout.
Prefixed model cost verification
.claude/skills/adapter-ops/SKILL.md, .claude/skills/adapter-ops/references/*
Guidance now describes LiteLLM lookup using validated prefixed model names, $0 fallback on lookup failure, verification in the pinned environment, and base-class selection for OpenAI-compatible adapters.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning It covers What/Why/changes/testing, but omits required template sections, especially breakage analysis and the checklist. Add the missing template sections, including breakage analysis, database migrations, env config, related issues, dependencies, notes on testing, screenshots, and the checklist.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main adapter-ops docs update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch misc/adapter-ops-cost-guidance

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chandrasekharan-zipstack chandrasekharan-zipstack marked this pull request as ready for review July 10, 2026 15:12

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.claude/skills/adapter-ops/SKILL.md (1)

193-197: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the accepted management action name.

manage_models.py accepts add-enum, not add; this documented command exits with an invalid-choice error.

-     --action add \
+     --action add-enum \
🤖 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 @.claude/skills/adapter-ops/SKILL.md around lines 193 - 197, Update the
documented manage_models.py example to use the accepted action name add-enum
instead of add, preserving the existing adapter, provider, and models arguments.
🤖 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 @.claude/skills/adapter-ops/references/provider_capabilities.md:
- Around line 151-165: Remove the instructions directing readers to curl
LiteLLM’s upstream main pricing JSON near the pricing verification guidance.
Replace them with instructions to validate model-prefix pricing against the
pinned sdk1 environment and its installed LiteLLM data, keeping the guidance
consistent with production dependencies.

In @.claude/skills/adapter-ops/SKILL.md:
- Around line 241-251: Update check_adapter_updates.py so its --json mode emits
only the json.dumps(...) payload on stdout; route the “SDK1 Adapters Path”
diagnostic to stderr or suppress it when JSON output is enabled, while
preserving the diagnostic for normal output.
- Line 359: Insert a blank line between the “Common provider names” label and
the table beginning with “Display Name” to satisfy markdownlint MD058.

---

Outside diff comments:
In @.claude/skills/adapter-ops/SKILL.md:
- Around line 193-197: Update the documented manage_models.py example to use the
accepted action name add-enum instead of add, preserving the existing adapter,
provider, and models arguments.
🪄 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

Run ID: 8c70cb48-b48e-46d1-b0cd-087c997c4613

📥 Commits

Reviewing files that changed from the base of the PR and between 09b6834 and 93abe9d.

📒 Files selected for processing (5)
  • .claude/skills/adapter-ops/SKILL.md
  • .claude/skills/adapter-ops/references/adapter_patterns.md
  • .claude/skills/adapter-ops/references/provider_capabilities.md
  • .claude/skills/adapter-ops/scripts/init_embedding_adapter.py
  • .claude/skills/adapter-ops/scripts/init_llm_adapter.py

Comment thread .claude/skills/adapter-ops/references/provider_capabilities.md
Comment thread .claude/skills/adapter-ops/SKILL.md
Comment thread .claude/skills/adapter-ops/SKILL.md
@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR updates the adapter-ops skill guidance and helper references.

  • Replaces stale unstract-adapter-extension command paths with adapter-ops paths.
  • Rewrites cost-tracking guidance around LiteLLM model-prefix resolution.
  • Adds base-class guidance for OpenAI-compatible adapter implementations.
  • Moves the update-checker path banner to stderr for JSON output.

Confidence Score: 4/5

This is close, but the documented management workflow should be fixed before merging.

  • The cost-tracking guidance updates are consistent with the changed documentation.
  • The latest command fix changes the action name but leaves the command pointing at a script path that is not added by this PR.
  • Following that documented step can still fail before any model update runs.

.claude/skills/adapter-ops/SKILL.md

Important Files Changed

Filename Overview
.claude/skills/adapter-ops/SKILL.md Updates adapter setup, maintenance, and cost-tracking guidance, but one documented management command still points at a missing script path.
.claude/skills/adapter-ops/references/adapter_patterns.md Updates adapter pattern guidance to verify LiteLLM model-prefix cost resolution.
.claude/skills/adapter-ops/references/provider_capabilities.md Updates provider capability guidance to query the pinned LiteLLM environment.
.claude/skills/adapter-ops/scripts/check_adapter_updates.py Sends the SDK adapters path banner to stderr so JSON output stays parseable.
.claude/skills/adapter-ops/scripts/init_embedding_adapter.py Refreshes the repo-root path comment for the renamed skill directory.
.claude/skills/adapter-ops/scripts/init_llm_adapter.py Refreshes the repo-root path comment for the renamed skill directory.

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
.claude/skills/adapter-ops/SKILL.md:193
**Management script missing**

The command now uses `--action add-enum`, but it still invokes `.claude/skills/adapter-ops/scripts/manage_models.py`. This PR does not add that script under `adapter-ops/scripts/`, so an adapter author following this step can still hit a file-not-found error before the model update runs. Please add the script at this path or point the example at the supported model-management command.

Reviews (4): Last reviewed commit: "[MISC] Fix invalid --action in manage_mo..." | Re-trigger Greptile

chandrasekharan-zipstack and others added 2 commits July 13, 2026 21:37
- provider_capabilities.md: replace curl-to-litellm-main verification with
  the pinned sdk1-venv query, matching SKILL.md — upstream main can price
  models the pinned version doesn't, defeating the check.
- check_adapter_updates.py: send the "SDK1 Adapters Path" diagnostic to
  stderr so `--json` stdout is valid JSON for jq/automation.
- SKILL.md: blank line before the provider-names table (markdownlint MD058).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread .claude/skills/adapter-ops/SKILL.md
SKILL.md showed `--action add`, which argparse rejects (valid choices are
add-enum/remove-enum/set-default/…). Corrected to `add-enum` so the
documented command runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Comment thread .claude/skills/adapter-ops/SKILL.md
@github-actions

Copy link
Copy Markdown
Contributor

Unstract test results

Per-group results

Status Group Tier Passed Failed Errors Skipped Duration (s)
e2e-login e2e 2 0 0 0 2.0
e2e-smoke e2e 2 0 0 0 1.2
integration-backend integration 56 0 0 27 47.5
integration-connectors integration 1 0 0 7 8.2
unit-backend unit 126 0 0 0 19.6
unit-connectors unit 63 0 0 0 9.6
unit-core unit 27 0 0 0 1.2
unit-platform-service unit 15 0 0 0 2.3
unit-rig unit 69 0 0 0 3.3
unit-sdk1 unit 435 0 0 0 24.2
unit-workers unit 0 0 0 0 28.6
TOTAL 796 0 0 34 147.7

Critical paths

⚠️ Critical paths not yet covered

  • workflow-create-execute — Create a workflow, configure source+destination, execute, poll, fetch result. (entry: POST /api/v1/workflow/{id}/execute/; declared coverage: e2e-workflow)
  • api-deployment-run — Deploy a workflow as an API, POST a document, receive structured JSON. (entry: POST /deployment/api/{org}/{name}/; declared coverage: e2e-api-deployment)
  • prompt-studio-fetch-response — Prompt Studio: create project, add prompt, run single-pass, get response. (entry: POST /api/v1/prompt-studio/prompt-studio-tool/{id}/fetch_response/; declared coverage: e2e-prompt-studio)
  • pipeline-etl-execute — Run an ETL pipeline from source connector to destination. (entry: POST /api/v1/pipeline/{id}/execute/; declared coverage: no groups declared)
  • usage-token-tracking — Per-execution token usage is recorded and retrievable. (entry: GET /api/v1/usage/get_token_usage/; declared coverage: no groups declared)
  • workflow-execution-fan-out — Multi-file workflow execution fans out to file-processing workers and rejoins. (entry: internal: backend → rabbitmq → workers/file_processing; declared coverage: no groups declared)
  • callback-result-delivery — Async results are posted back via the callback worker. (entry: internal: workers/callback → backend /internal endpoints; declared coverage: no groups declared)
✅ Covered critical paths
  • auth-login — covered by e2e-login
  • adapter-register-llm — covered by integration-backend

@chandrasekharan-zipstack chandrasekharan-zipstack merged commit 9609ec0 into main Jul 14, 2026
11 checks passed
@chandrasekharan-zipstack chandrasekharan-zipstack deleted the misc/adapter-ops-cost-guidance branch July 14, 2026 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants