fix(sdd): parse model spec at first separator and consolidate duplicated parsers#374
Conversation
…ee bug Both extractModelFromAgent and ReadCurrentModelAssignments incorrectly preferred colon over slash when splitting model strings. For OpenRouter free models like openrouter/qwen/qwen3.6-plus:free, this produced openrouter/qwen/qwen3.6-plus/free instead of the correct :free suffix. Fix: find the FIRST occurrence of either / or : (whichever comes first), matching the correct implementation already present in parseModelSpec.
… parsing Consolidates three identical copies of the "split on first '/' or ':'" logic into a shared helper in the model package: - internal/cli/sync.go -> parseModelSpec - internal/components/sdd/profiles.go -> extractModelFromAgent - internal/components/sdd/read_assignments.go -> ReadCurrentModelAssignments No behavior change. Addresses review feedback on Gentleman-Programming#242.
Adds test coverage per review feedback on Gentleman-Programming#242: - Dedicated TestExtractModelFromAgent (previously no coverage) - Regression case for openrouter/qwen/qwen3.6-plus:free in read_assignments_test.go. The combined slash-then-colon format motivating issue Gentleman-Programming#260 must be split at the first separator (the leading '/'), not at ':'.
|
Gracias por la mención, estoy ansioso por revisar esta PR |
Alan-TheGentleman
left a comment
There was a problem hiding this comment.
This is a good candidate to merge after a current CI pass.
The parser extraction is scoped and the regression coverage hits the OpenRouter /free case, but the branch has old validation noise in the history. Please refresh against current main so we merge a clean branch.
Alan-TheGentleman
left a comment
There was a problem hiding this comment.
Looks good. The shared parser fixes the OpenRouter /free regression without widening behavior, and the new tests cover the mixed slash/colon cases that matter.
|
CI is blocked on |
…ssion After the recent main update, ReadCurrentModelAssignments normalizes the legacy "sdd-orchestrator" config key to "gentle-orchestrator" in the returned map. The regression test was still asserting the legacy key and failed with "phase missing". Update the assertion to "gentle-orchestrator" while keeping the legacy key in the JSON fixture — this preserves the original issue Gentleman-Programming#260 scenario (unsynced config) and now also covers the legacy alias normalization in the same test.
|
@Alan-TheGentleman pushed the fix you flagged → commit f972839. FixThe regression test was asserting Local validationAll relevant tests pass:
Remaining CI red is not from this PRCI Evidence this is upstream, not this PR:
Looks like the Pi test needs either a skip when |
|
@Basparin — heads-up: this PR's Unit Tests failure is Your branch still expects the old form, so the CI run uses the pre-#660 assertion and fails. Fix: rebase against current Pseudocode: git fetch upstream main
git rebase upstream/main
# resolve any conflicts (likely none for this PR's scope)
git push --force-with-leaseThe other PR you have open (and #371 + #374 + #372) all show the same failure for the same reason — same rebase fixes all three. Thanks for sticking with these. |
Alan-TheGentleman
left a comment
There was a problem hiding this comment.
Thanks for picking this up and preserving @ACDPDEV's original commit — the refactor is clean and the new tests are solid. The multi-slash openrouter/anthropic/claude-sonnet-4 case and the :free regression are exactly right, and everything passes locally with no conflicts against main.
One blocker before merge: this fixes the wrong layer of #260.
The issue's symptom is the TUI writing opencode/qwen3.6-plus-free into opencode.json. That string is built at inject.go:1884 from assignment.FullID() (ProviderID + "/" + ModelID), and ProviderID comes from state.SelectedProvider in model_picker.go:272 — i.e. the model is being offered under the wrong provider in the catalog (the issue's own "Additional finding": it shows under OpenCode Zen but only works under OpenRouter).
Your change only fixes parsing model strings read back from config — a real and worthwhile bug — but it doesn't stop the bad prefix from being written. So Closes #260 would auto-close an issue whose main symptom is still present.
Could you either:
- (a) narrow the scope: change
Closes #260→Refs #260(and link the colon-first parse bug it actually fixes), or - (b) extend the PR to address the catalog/provider-mapping write path so #260's repro actually produces
openrouter/...:free?
Small nit: gofmt on split_test.go to align the struct columns.
🔗 Linked Issue
Closes #260
🔄 Continuation Notice
This PR continues and supersedes #242 by @ACDPDEV, who explicitly handed off the work in #242 (comment) (university commitments prevented him from landing the review suggestions himself).
Full credit for the original fix goes to @ACDPDEV — his commit
28c3378is preserved verbatim with original author metadata intact. This PR applies @Alan-TheGentleman's two review suggestions from #242 on top:SplitProviderModelhelper — consolidates three identical copies of the first-separator logic. This matches @ACDPDEV's final ask in the handoff: "abstraer lo que se repite en una función"./freeformat + dedicated coverage forextractModelFromAgent, which previously had no direct tests.Once this PR lands, #242 can be closed — the full contribution (with review feedback applied) lives here.
🏷️ PR Type
type:bug— Bug fix (non-breaking change that fixes an issue)type:featuretype:docstype:refactortype:choretype:breaking-change📝 Summary
openrouter/qwen/qwen3.6-plus:freewas split at:before the leading/, producing a brokenProviderID=openrouter/qwen/qwen3.6-plus,ModelID=free.SplitProviderModelhelper in themodelpackage.extractModelFromAgent.📂 Changes
internal/model/split.goSplitProviderModel(spec) (provider, model, ok)helperinternal/model/split_test.gointernal/cli/sync.goparseModelSpecnow delegates to the shared helperinternal/components/sdd/profiles.goextractModelFromAgentnow delegates to the shared helperinternal/components/sdd/read_assignments.gointernal/components/sdd/profiles_test.goTestExtractModelFromAgent— no previous coverageinternal/components/sdd/read_assignments_test.goTestReadCurrentModelAssignmentsOpenRouterFreeSuffixregression testNet: +255 / −41, 7 files. No behavior change in the happy path — existing
TestReadCurrentModelAssignments*suite still passes unchanged.🧪 Test Plan
Unit Tests
go test ./internal/model/... ./internal/cli/... ./internal/components/sdd/...E2E Tests (Docker required)
Pre-existing test failures in the Windows sandbox around
unique-names-generator/bun installare unrelated to this PR — they're tracked in a separate PR (#372).cd e2e && ./docker-test.sh)🤖 Automated Checks
Closes #260status:approvedstatus:approvedtype:*Labeltype:bug✅ Contributor Checklist
status:approved(Configure Opencode Models writes invalid model ID prefix (opencode/ instead of openrouter/) #260)type:*label to this PR (pending maintainer — external contributors cannot apply labels)Co-Authored-Bytrailers💬 Notes for Reviewers
28c3378) is @ACDPDEV's verbatim, author metadata intact. GitHub should surface him as a co-contributor via commit history.refactor(model): extract SplitProviderModel helper...andtest(sdd): add OpenRouter free suffix regression coverage.internal/modelbecauseModelAssignmentalready lives there and bothcliandsddpackages import it — zero import-cycle risk.