From b0d458bdd342e71814c68dfa2cf031e39119f233 Mon Sep 17 00:00:00 2001 From: DevelopmentCats Date: Thu, 5 Nov 2026 18:47:43 +0000 Subject: [PATCH] internal: rename provider to engine, catalog to resolve, module to llm-helper First step of moving engine, model and recipe knowledge out of Go and into the catalogue. Each catalogue kind is now read by the internal package of the same name (engine, recipe, hardware), and the package that combines them with a model's card no longer shares a name with catalogue/. The module path matches the repo. No behaviour change. On-disk names (the config dir, VLLM_HELPER_* env vars, PROVIDER, VLLM_BIN, service names) are unchanged. --- .goreleaser.yaml | 4 +- AGENTS.md | 2 +- catalogue/engines/README.md | 2 +- cmd/vllm-helper-docs/main.go | 2 +- docs/docs_test.go | 2 +- docs/providers.md | 2 +- go.mod | 2 +- internal/cli/capabilities.go | 4 +- internal/cli/clusterrunner.go | 10 +-- internal/cli/clusterrunner_internal_test.go | 2 +- internal/cli/detectcmds.go | 38 +++++----- internal/cli/doctor_internal_test.go | 8 +-- internal/cli/editset.go | 10 +-- internal/cli/engines_internal_test.go | 12 ++-- internal/cli/engines_test.go | 8 +-- internal/cli/enginescmd.go | 18 ++--- internal/cli/gendocs.go | 2 +- internal/cli/gendocs_internal_test.go | 2 +- internal/cli/ggufplugin.go | 4 +- internal/cli/hardware_test.go | 2 +- internal/cli/hardwarecmd.go | 6 +- internal/cli/memfit.go | 6 +- internal/cli/memfit_darwin.go | 2 +- internal/cli/memfit_darwin_internal_test.go | 2 +- internal/cli/memfit_internal_test.go | 2 +- internal/cli/memfit_linux.go | 2 +- internal/cli/metal_darwin.go | 4 +- internal/cli/metallimit.go | 2 +- internal/cli/metallimit_darwin.go | 6 +- internal/cli/metallimit_internal_test.go | 2 +- internal/cli/metallimit_other.go | 4 +- internal/cli/node_test.go | 2 +- internal/cli/nodecmd.go | 4 +- internal/cli/nodecmd_internal_test.go | 6 +- internal/cli/plugins.go | 6 +- internal/cli/poolserve.go | 4 +- internal/cli/profiles.go | 30 ++++---- internal/cli/recipehealth.go | 4 +- internal/cli/recipehealth_internal_test.go | 2 +- internal/cli/recipelaunch.go | 18 ++--- internal/cli/recipelaunch_internal_test.go | 12 ++-- internal/cli/recipes.go | 2 +- internal/cli/recipes_internal_test.go | 2 +- internal/cli/root.go | 18 ++--- internal/cli/run_test.go | 4 +- internal/cli/search.go | 32 ++++----- internal/cli/serve.go | 2 +- internal/cli/service.go | 4 +- internal/cli/setup.go | 32 ++++----- internal/cli/shard_internal_test.go | 6 +- internal/cli/shard_mp.go | 6 +- internal/cli/shardcmd.go | 6 +- internal/cli/start.go | 4 +- internal/cli/upgrade.go | 4 +- internal/cli/upgrade_internal_test.go | 4 +- internal/cli/vllmargs.go | 34 ++++----- internal/cli/vllmargs_internal_test.go | 20 +++--- internal/cli/vllmbin_internal_test.go | 2 +- internal/cli/watch.go | 4 +- internal/cli/watch_internal_test.go | 6 +- internal/config/config_test.go | 2 +- internal/config/shellwords_test.go | 2 +- internal/control/control.go | 14 ++-- internal/control/control_internal_test.go | 6 +- internal/control/gguf.go | 4 +- internal/control/gpus.go | 4 +- internal/detect/classify.go | 2 +- internal/detect/container_test.go | 2 +- internal/detect/endpoint_test.go | 2 +- internal/detect/fixtures_internal_test.go | 2 +- internal/detect/hardware_internal_test.go | 2 +- internal/detect/hardware_test.go | 2 +- internal/detect/process.go | 2 +- internal/detect/process_internal_test.go | 2 +- internal/detect/report.go | 2 +- internal/{provider => engine}/engine.go | 8 +-- internal/{provider => engine}/engine_test.go | 72 +++++++++---------- internal/{provider => engine}/local.go | 2 +- .../provider.go => engine/registry.go} | 7 +- .../registry_test.go} | 42 +++++------ internal/hardware/hardware.go | 2 +- internal/hardware/hardware_test.go | 2 +- internal/hf/snippet.go | 2 +- internal/hf/testsupport.go | 2 +- internal/nodes/registry.go | 2 +- internal/plugin/coder/adopt_test.go | 2 +- internal/plugin/coder/client_test.go | 2 +- .../plugin/coder/options_internal_test.go | 2 +- internal/plugin/coder/prune_test.go | 2 +- internal/plugin/coder/route_test.go | 2 +- internal/plugin/coder/sync.go | 10 +-- internal/plugin/coder/sync_internal_test.go | 6 +- internal/plugin/plugin.go | 4 +- internal/plugin/registry.go | 2 +- internal/plugin/registry_internal_test.go | 2 +- internal/plugin/spark/spark.go | 8 +-- internal/profile/generated_test.go | 4 +- internal/profile/profile.go | 4 +- internal/profile/profile_test.go | 6 +- internal/recipe/args.go | 2 +- internal/recipe/container.go | 4 +- internal/recipe/launch.go | 10 +-- internal/recipe/local.go | 2 +- internal/recipe/tested.go | 28 ++++---- internal/recipe/tested_internal_test.go | 2 +- internal/recipe/validate_internal_test.go | 2 +- .../catalog.go => resolve/resolve.go} | 20 +++--- .../resolve_internal_test.go} | 38 +++++----- internal/{catalog => resolve}/tiktoken.go | 6 +- .../tiktoken_internal_test.go | 4 +- internal/toolchain/toolchain_darwin.go | 2 +- internal/vllm/validate.go | 2 +- internal/web/activate.go | 4 +- internal/web/api.go | 6 +- internal/web/docs.go | 2 +- internal/web/docs_internal_test.go | 2 +- internal/web/docssite.go | 2 +- internal/web/docssite_internal_test.go | 2 +- internal/web/models.go | 44 ++++++------ internal/web/server.go | 8 +-- internal/web/server_internal_test.go | 6 +- main.go | 2 +- scripts/gendocs/main.go | 4 +- tools/recipediff/go.mod | 2 +- 124 files changed, 453 insertions(+), 454 deletions(-) rename internal/{provider => engine}/engine.go (99%) rename internal/{provider => engine}/engine_test.go (80%) rename internal/{provider => engine}/local.go (99%) rename internal/{provider/provider.go => engine/registry.go} (96%) rename internal/{provider/provider_test.go => engine/registry_test.go} (81%) rename internal/{catalog/catalog.go => resolve/resolve.go} (97%) rename internal/{catalog/catalog_internal_test.go => resolve/resolve_internal_test.go} (96%) rename internal/{catalog => resolve}/tiktoken.go (98%) rename internal/{catalog => resolve}/tiktoken_internal_test.go (98%) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index af2e53c..984b2a2 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -30,8 +30,8 @@ builds: # Commit is what identifies a dev build: they all share one moving # release tag, so the version string can't tell two of them apart. - -s -w - -X github.com/coder/vllm-helper/internal/cli.Version={{.Version}} - -X github.com/coder/vllm-helper/internal/cli.Commit={{.FullCommit}} + -X github.com/coder/llm-helper/internal/cli.Version={{.Version}} + -X github.com/coder/llm-helper/internal/cli.Commit={{.FullCommit}} # The same binary under its old name. 'upgrade' in v0.5.0 and earlier # unpacks the file called vllm-helper and nothing else, so dropping it would # strand every existing install on the release it has. diff --git a/AGENTS.md b/AGENTS.md index 690b3ef..048c4de 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ llm-helper is one Go binary that manages inference servers (vLLM, mlx-lm, llama. ## Repository layout -`internal/` holds the packages the binary builds from: `cli` for the commands, `control` for what the CLI and the web panel share, `web` for the panel, and the rest one package per feature. `catalogue/` holds the shipped data definitions (engines, recipes, hardware) with the Go that embeds them in `catalogue/catalogue.go`. `docs/` is the shipped documentation, and `tools/recipediff` is a separate module. +`internal/` holds the packages the binary builds from: `cli` for the commands, `control` for what the CLI and the web panel share, `web` for the panel, and the rest one package per feature. `catalogue/` holds the shipped data definitions (engines, recipes, hardware) with the Go that embeds them in `catalogue/catalogue.go`; each kind is read by the `internal/` package of the same name (`engine`, `recipe`, `hardware`), and `resolve` combines them with a model's card and config into launch settings. `docs/` is the shipped documentation, and `tools/recipediff` is a separate module. ## Essential commands diff --git a/catalogue/engines/README.md b/catalogue/engines/README.md index 049c732..8e5ff01 100644 --- a/catalogue/engines/README.md +++ b/catalogue/engines/README.md @@ -5,7 +5,7 @@ Each file here is one inference server llm-helper can launch, named after the en To add an engine, copy the closest file to `.json` and change it. No Go code is needed: shared code acts on the engine's `capabilities`, never on its name. -The file is checked when it loads, and the tests in `internal/provider` render every file here for every rank. +The file is checked when it loads, and the tests in `internal/engine` render every file here for every rank. The fields are described in "Contributing an engine" in [docs/providers.md](../../docs/providers.md). To try an engine without rebuilding, put its file in `~/.config/vllm-helper/engines.d/` instead. diff --git a/cmd/vllm-helper-docs/main.go b/cmd/vllm-helper-docs/main.go index f86cc3b..701bef4 100644 --- a/cmd/vllm-helper-docs/main.go +++ b/cmd/vllm-helper-docs/main.go @@ -22,7 +22,7 @@ import ( "syscall" "time" - "github.com/coder/vllm-helper/internal/web" + "github.com/coder/llm-helper/internal/web" ) func main() { diff --git a/docs/docs_test.go b/docs/docs_test.go index f1973d6..e741e8f 100644 --- a/docs/docs_test.go +++ b/docs/docs_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) // The manifest is the docs engine's contract with the panel: one entry per diff --git a/docs/providers.md b/docs/providers.md index 67444f0..ad22ab2 100644 --- a/docs/providers.md +++ b/docs/providers.md @@ -185,7 +185,7 @@ A definition holds `schema_version` and the engine's fields, and says: The definition is checked when it loads. An unknown field, an unknown placeholder, a key that would land on the command line, or a container with no role that serves HTTP is refused with the reason. A file whose name is not its id is refused too. -The tests in `internal/provider` render every shipped engine for every rank, so a new engine is covered once its file is in `catalogue/engines/`. +The tests in `internal/engine` render every shipped engine for every rank, so a new engine is covered once its file is in `catalogue/engines/`. To try an engine without rebuilding, put its file under `~/.config/vllm-helper/engines.d/`, in the same shape and named the same way as a file in `catalogue/engines/`. A local file can only add engines with new ids; it cannot change how a shipped engine is launched. diff --git a/go.mod b/go.mod index c12f86f..bf5b0ab 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/coder/vllm-helper +module github.com/coder/llm-helper go 1.26.5 diff --git a/internal/cli/capabilities.go b/internal/cli/capabilities.go index 4de2172..ae80d27 100644 --- a/internal/cli/capabilities.go +++ b/internal/cli/capabilities.go @@ -4,8 +4,8 @@ import ( "fmt" "os" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/vllm" ) // vllmCaps asks the configured vLLM what it supports, caching under the state diff --git a/internal/cli/clusterrunner.go b/internal/cli/clusterrunner.go index 127237e..7c0bf17 100644 --- a/internal/cli/clusterrunner.go +++ b/internal/cli/clusterrunner.go @@ -10,11 +10,11 @@ import ( "strconv" "strings" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/recipe" - "github.com/coder/vllm-helper/internal/service" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/service" ) // clusterRunner drives a recipe that serves from containers on the nodes it diff --git a/internal/cli/clusterrunner_internal_test.go b/internal/cli/clusterrunner_internal_test.go index 17c302a..296401a 100644 --- a/internal/cli/clusterrunner_internal_test.go +++ b/internal/cli/clusterrunner_internal_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/nodes" ) // status reads this vocabulary, so a mistranslation here is what makes a diff --git a/internal/cli/detectcmds.go b/internal/cli/detectcmds.go index 5100d3d..2b52c98 100644 --- a/internal/cli/detectcmds.go +++ b/internal/cli/detectcmds.go @@ -10,16 +10,16 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" - "github.com/coder/vllm-helper/internal/toolchain" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/toolchain" ) // doctorReport is everything doctor learns, in one machine-readable shape. @@ -139,14 +139,14 @@ func gatherDoctor() doctorReport { HarmonyVocab: hasHarmonyVocab(cfg.Dirs.Data), CoderConfigured: cfg.CoderConfigured(), } - if prov, err := provider.Lookup(cfg.Provider()); err != nil { + if prov, err := engine.Lookup(cfg.Provider()); err != nil { r.Config.Provider = cfg.Provider() r.Config.ProviderError = err.Error() } else { r.Config.Provider = prov.Name() - if prov.Name() != provider.VLLM { + if prov.Name() != engine.VLLM { r.Config.ProviderBin = cfg.Lookup(prov.BinKey(), "") - r.Config.ProviderBinOK = provider.Executable(r.Config.ProviderBin) + r.Config.ProviderBinOK = engine.Executable(r.Config.ProviderBin) } } } @@ -274,7 +274,7 @@ func hardwareWarnings(hw detect.Hardware) []string { for _, err := range hardware.LocalErrors() { w = append(w, "a local hardware definition was skipped: "+err.Error()) } - for _, err := range provider.LocalErrors() { + for _, err := range engine.LocalErrors() { w = append(w, "a local engine definition was skipped: "+err.Error()) } for _, err := range recipe.LocalErrors() { @@ -387,7 +387,7 @@ func renderDoctor(r doctorReport, yes bool) { if hw.GPUsHidden > 0 { fmt.Printf(" %d more hidden from the server by CUDA_VISIBLE_DEVICES\n", hw.GPUsHidden) } - newProfiles := provider.VLLM + newProfiles := engine.VLLM if r.Config != nil { newProfiles = r.Config.Provider } @@ -433,8 +433,8 @@ func renderDoctor(r doctorReport, yes bool) { switch { case c.ProviderError != "": fmt.Printf(" provider: %s\n", c.ProviderError) - case c.Provider != provider.VLLM: - p, _ := provider.Lookup(c.Provider) + case c.Provider != engine.VLLM: + p, _ := engine.Lookup(c.Provider) fmt.Printf(" provider: %s (new profiles)\n", c.Provider) // "server", not " bin": the line above names the provider, // and a longer name would push the value out of the column. @@ -451,7 +451,7 @@ func renderDoctor(r doctorReport, yes bool) { } } switch { - case c.VLLMBin == "" && c.Provider != provider.VLLM: + case c.VLLMBin == "" && c.Provider != engine.VLLM: // Not a fault: vLLM is optional once new profiles go elsewhere. case c.VLLMBin == "": fmt.Println(" vllm bin: NOT SET -- set VLLM_BIN in config.env") @@ -789,7 +789,7 @@ func adoptService(cfg *config.Config, s detect.Server) bool { // server is not vLLM's backend, and telling its user to install vllm-metal // would send them after something they do not need. func appleBackend(hw detect.Hardware, newProfiles string) string { - if hw.GPUVendor != "apple" || newProfiles != provider.VLLM { + if hw.GPUVendor != "apple" || newProfiles != engine.VLLM { return "" } if !hw.Metal { diff --git a/internal/cli/doctor_internal_test.go b/internal/cli/doctor_internal_test.go index f6fccb2..5a2eb69 100644 --- a/internal/cli/doctor_internal_test.go +++ b/internal/cli/doctor_internal_test.go @@ -13,10 +13,10 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/profile" ) // Nothing in this package's tests runs in parallel: they swap os.Stdout and diff --git a/internal/cli/editset.go b/internal/cli/editset.go index 988a2d1..7f4b6e4 100644 --- a/internal/cli/editset.go +++ b/internal/cli/editset.go @@ -10,9 +10,9 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/profile" ) // standardProfileKeys are the keys every profile is expected to carry. @@ -24,7 +24,7 @@ var standardProfileKeys = map[string]bool{ "KV_CACHE_MEMORY_BYTES": true, "EXTRA_ARGS": true, profile.RecipeKey: true, - provider.Key: true, + engine.Key: true, } func newEditCmd() *cobra.Command { @@ -164,7 +164,7 @@ func validateProfile(p *profile.Profile, name string) error { if p.Model() == "" { return fmt.Errorf("profile '%s' has no MODEL= line -- it can't be served like this", name) } - if _, err := provider.Lookup(p.Provider()); err != nil { + if _, err := engine.Lookup(p.Provider()); err != nil { return fmt.Errorf("profile '%s': %w", name, err) } if extra := p.ExtraArgs(); extra != "" { diff --git a/internal/cli/engines_internal_test.go b/internal/cli/engines_internal_test.go index f7ce624..c33982f 100644 --- a/internal/cli/engines_internal_test.go +++ b/internal/cli/engines_internal_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/recipe" ) func glmRecipe(t *testing.T) recipe.TestedRecipe { @@ -63,9 +63,9 @@ func TestCheckStagedNamesWhatIsMissing(t *testing.T) { t.Fatalf("%s pins %d models into cache %q", r.ID, len(refs), cache) } weights, drafter := refs["weights"], refs["drafter"] - stage := func(m provider.ModelRef) { + stage := func(m engine.ModelRef) { t.Helper() - dir := filepath.Join(home, provider.SnapshotPath(cache, m)) + dir := filepath.Join(home, engine.SnapshotPath(cache, m)) if err := os.MkdirAll(dir, 0o755); err != nil { t.Fatal(err) } @@ -92,7 +92,7 @@ func TestCheckStagedNamesWhatIsMissing(t *testing.T) { // A snapshot directory with nothing in it is a download that did not // finish. - if err := os.MkdirAll(filepath.Join(home, provider.SnapshotPath(cache, drafter)), 0o755); err != nil { + if err := os.MkdirAll(filepath.Join(home, engine.SnapshotPath(cache, drafter)), 0o755); err != nil { t.Fatal(err) } if err := checkStaged(r, []recipeMember{local}, ""); err == nil || !strings.Contains(err.Error(), drafter.ID) { diff --git a/internal/cli/engines_test.go b/internal/cli/engines_test.go index 60e0196..76ad76e 100644 --- a/internal/cli/engines_test.go +++ b/internal/cli/engines_test.go @@ -7,8 +7,8 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/recipe" ) const toyEngine = `{"schema_version":1,"id":"toy","display_name":"Toy","why":"a test engine",` + @@ -21,7 +21,7 @@ const toyEngine = `{"schema_version":1,"id":"toy","display_name":"Toy","why":"a // named rather than taking the others with it. func TestRunEnginesListShowsLocalDefinitions(t *testing.T) { configDir, _ := newTree(t) - dir := filepath.Join(configDir, provider.LocalDir) + dir := filepath.Join(configDir, engine.LocalDir) if err := os.MkdirAll(dir, 0o755); err != nil { t.Fatal(err) } @@ -37,7 +37,7 @@ func TestRunEnginesListShowsLocalDefinitions(t *testing.T) { } // Later tests in this process must not see this directory's engines. t.Cleanup(func() { - provider.UseLocal(filepath.Join(dir, "gone")) + engine.UseLocal(filepath.Join(dir, "gone")) recipe.UseLocal(filepath.Join(dir, "gone")) }) diff --git a/internal/cli/enginescmd.go b/internal/cli/enginescmd.go index c9823e0..bfe16d3 100644 --- a/internal/cli/enginescmd.go +++ b/internal/cli/enginescmd.go @@ -10,8 +10,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" ) func newEnginesCmd() *cobra.Command { @@ -62,12 +62,12 @@ func newEnginesShowCmd() *cobra.Command { // engineRow is one engine as 'engines list --json' prints it. type engineRow struct { - provider.Engine + engine.Engine // Source is the engines.d file a local engine came from, or "shipped". Source string `json:"source"` } -func engineSource(e provider.Engine) string { +func engineSource(e engine.Engine) string { if e.Source == "" { return "shipped" } @@ -75,11 +75,11 @@ func engineSource(e provider.Engine) string { } func runEnginesList(out, errOut io.Writer, jsonOut bool) error { - for _, err := range provider.LocalErrors() { + for _, err := range engine.LocalErrors() { fmt.Fprintf(errOut, "warning: skipped a local engine definition file: %v\n", err) } var rows []engineRow - for _, e := range provider.Default().Engines() { + for _, e := range engine.Default().Engines() { rows = append(rows, engineRow{Engine: e, Source: engineSource(e)}) } if jsonOut { @@ -93,14 +93,14 @@ func runEnginesList(out, errOut io.Writer, jsonOut bool) error { if err := tw.Flush(); err != nil { return err } - fmt.Fprintf(out, "\nLocal engines go in %s.\n", filepath.Join(config.ResolveDirs().Config, provider.LocalDir)) + fmt.Fprintf(out, "\nLocal engines go in %s.\n", filepath.Join(config.ResolveDirs().Config, engine.LocalDir)) return nil } func runEnginesShow(out io.Writer, id string, jsonOut bool) error { - e, ok := provider.Default().Get(id) + e, ok := engine.Default().Get(id) if !ok { - return fmt.Errorf("no engine %q (have: %s)", id, strings.Join(provider.Names(), ", ")) + return fmt.Errorf("no engine %q (have: %s)", id, strings.Join(engine.Names(), ", ")) } if jsonOut { return printJSONTo(out, engineRow{Engine: e, Source: engineSource(e)}) diff --git a/internal/cli/gendocs.go b/internal/cli/gendocs.go index 305a27e..39d3c61 100644 --- a/internal/cli/gendocs.go +++ b/internal/cli/gendocs.go @@ -15,7 +15,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) // CLIReferencePath is the manifest route whose children GenerateCLIRoutes diff --git a/internal/cli/gendocs_internal_test.go b/internal/cli/gendocs_internal_test.go index cb75425..e31703a 100644 --- a/internal/cli/gendocs_internal_test.go +++ b/internal/cli/gendocs_internal_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) // The committed reference must be exactly what the current command tree diff --git a/internal/cli/ggufplugin.go b/internal/cli/ggufplugin.go index a9eb6f7..a2cb2a7 100644 --- a/internal/cli/ggufplugin.go +++ b/internal/cli/ggufplugin.go @@ -8,8 +8,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" ) // ggufMissingMessage explains the gap and how to close it, naming the diff --git a/internal/cli/hardware_test.go b/internal/cli/hardware_test.go index b8433e9..dc4035c 100644 --- a/internal/cli/hardware_test.go +++ b/internal/cli/hardware_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // A hardware.d file is loaded before every command, so 'hardware list' shows diff --git a/internal/cli/hardwarecmd.go b/internal/cli/hardwarecmd.go index 22f6d4b..b165c8c 100644 --- a/internal/cli/hardwarecmd.go +++ b/internal/cli/hardwarecmd.go @@ -9,9 +9,9 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/hardware" ) func newHardwareCmd() *cobra.Command { diff --git a/internal/cli/memfit.go b/internal/cli/memfit.go index 6de1675..2574ae8 100644 --- a/internal/cli/memfit.go +++ b/internal/cli/memfit.go @@ -5,9 +5,9 @@ import ( "math" "strconv" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/detect" ) // useServerGPUs tells detect which GPUs a server started with these env diff --git a/internal/cli/memfit_darwin.go b/internal/cli/memfit_darwin.go index c9837de..f69f122 100644 --- a/internal/cli/memfit_darwin.go +++ b/internal/cli/memfit_darwin.go @@ -3,7 +3,7 @@ package cli import ( "fmt" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) // fitMemUtilization keeps --gpu-memory-utilization within what this Mac can diff --git a/internal/cli/memfit_darwin_internal_test.go b/internal/cli/memfit_darwin_internal_test.go index c9b1275..6e6a4ba 100644 --- a/internal/cli/memfit_darwin_internal_test.go +++ b/internal/cli/memfit_darwin_internal_test.go @@ -5,7 +5,7 @@ package cli import ( "testing" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) // vllm-metal sizes its cache against the Metal working set and checks for diff --git a/internal/cli/memfit_internal_test.go b/internal/cli/memfit_internal_test.go index 95291b6..2cbae8b 100644 --- a/internal/cli/memfit_internal_test.go +++ b/internal/cli/memfit_internal_test.go @@ -4,7 +4,7 @@ import ( "strconv" "testing" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) func TestClampMemUtilization(t *testing.T) { diff --git a/internal/cli/memfit_linux.go b/internal/cli/memfit_linux.go index dbf5a18..54f7f02 100644 --- a/internal/cli/memfit_linux.go +++ b/internal/cli/memfit_linux.go @@ -3,7 +3,7 @@ package cli import ( "fmt" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) // fitMemUtilization keeps --gpu-memory-utilization within what this machine can diff --git a/internal/cli/metal_darwin.go b/internal/cli/metal_darwin.go index f73ac80..a4ceb14 100644 --- a/internal/cli/metal_darwin.go +++ b/internal/cli/metal_darwin.go @@ -1,8 +1,8 @@ package cli import ( - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/vllm" ) // useMetalProbe tells detect how to find out whether bin serves on the Apple diff --git a/internal/cli/metallimit.go b/internal/cli/metallimit.go index d3d9394..14b4e0a 100644 --- a/internal/cli/metallimit.go +++ b/internal/cli/metallimit.go @@ -11,7 +11,7 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // metalWiredLimitKey is the config.env key that records the wired limit diff --git a/internal/cli/metallimit_darwin.go b/internal/cli/metallimit_darwin.go index 6014bf1..f9a3064 100644 --- a/internal/cli/metallimit_darwin.go +++ b/internal/cli/metallimit_darwin.go @@ -9,9 +9,9 @@ import ( "strings" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/vllm" ) func runMetalLimit(o metalLimitOpts) error { diff --git a/internal/cli/metallimit_internal_test.go b/internal/cli/metallimit_internal_test.go index f894fd8..e249d6a 100644 --- a/internal/cli/metallimit_internal_test.go +++ b/internal/cli/metallimit_internal_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) const ( diff --git a/internal/cli/metallimit_other.go b/internal/cli/metallimit_other.go index 791621d..b90df58 100644 --- a/internal/cli/metallimit_other.go +++ b/internal/cli/metallimit_other.go @@ -5,8 +5,8 @@ package cli import ( "errors" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" ) // runMetalLimit refuses off macOS. The command still exists here so the diff --git a/internal/cli/node_test.go b/internal/cli/node_test.go index 3940298..e2a6119 100644 --- a/internal/cli/node_test.go +++ b/internal/cli/node_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/nodes" ) // Re-adding a node is how its URL gets corrected. It used to replace the diff --git a/internal/cli/nodecmd.go b/internal/cli/nodecmd.go index 44c74eb..b332378 100644 --- a/internal/cli/nodecmd.go +++ b/internal/cli/nodecmd.go @@ -14,8 +14,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/nodes" ) func newNodeCmd() *cobra.Command { diff --git a/internal/cli/nodecmd_internal_test.go b/internal/cli/nodecmd_internal_test.go index be77fa1..0099d4a 100644 --- a/internal/cli/nodecmd_internal_test.go +++ b/internal/cli/nodecmd_internal_test.go @@ -7,9 +7,9 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/nodes" ) // 'node ls' showed only the HTTP host, so a node whose SSH target was wrong, diff --git a/internal/cli/plugins.go b/internal/cli/plugins.go index e0ed284..b3b7915 100644 --- a/internal/cli/plugins.go +++ b/internal/cli/plugins.go @@ -3,13 +3,13 @@ package cli import ( "fmt" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" // Integrations register themselves. Importing them here, rather than // from the plugin package, keeps the dependency pointing one way: // plugins may use the core, the core never imports a plugin. - _ "github.com/coder/vllm-helper/internal/plugin/coder" - _ "github.com/coder/vllm-helper/internal/plugin/spark" + _ "github.com/coder/llm-helper/internal/plugin/coder" + _ "github.com/coder/llm-helper/internal/plugin/spark" ) // localBaseURL is where this machine serves the OpenAI-compatible API. diff --git a/internal/cli/poolserve.go b/internal/cli/poolserve.go index f76501b..e19cc5d 100644 --- a/internal/cli/poolserve.go +++ b/internal/cli/poolserve.go @@ -15,8 +15,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/router" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/router" ) func newPoolServeCmd() *cobra.Command { diff --git a/internal/cli/profiles.go b/internal/cli/profiles.go index 9e38e21..4e1063c 100644 --- a/internal/cli/profiles.go +++ b/internal/cli/profiles.go @@ -10,13 +10,13 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/catalog" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/resolve" + "github.com/coder/llm-helper/internal/vllm" ) // profileInfo is the machine-readable shape of one saved profile. @@ -195,11 +195,11 @@ func newNewCmd() *cobra.Command { // Refusing here rather than at startup matters: activating a profile restarts // the service, so a model that cannot load takes the running one down with it // and leaves the machine serving nothing. -func resolveQuant(ctx context.Context, cfg *config.Config, repo, want string) (*catalog.Choice, error) { +func resolveQuant(ctx context.Context, cfg *config.Config, repo, want string) (*resolve.Choice, error) { if want == "" { return nil, nil } - prov, err := provider.Lookup(cfg.Provider()) + prov, err := engine.Lookup(cfg.Provider()) if err != nil { return nil, err } @@ -207,14 +207,14 @@ func resolveQuant(ctx context.Context, cfg *config.Config, repo, want string) (* return nil, fmt.Errorf("--quant picks one GGUF file out of a repo, but new profiles here are served by %s, which does not load GGUF; drop --quant and name a repo of that quant instead", prov.Name()) } if !prov.Capabilities().VLLMArgs { - return catalog.ChooseGGUFQuant(ctx, repo, want) + return resolve.ChooseGGUFQuant(ctx, repo, want) } m, err := hf.Lookup(ctx, repo) if err != nil { return nil, fmt.Errorf("looking up %s: %w", repo, err) } d := inspectModel(ctx, m, cfg) - v, ok := catalog.FindVariant(d.All, want) + v, ok := resolve.FindVariant(d.All, want) if !ok { // A repo holding one copy has nothing to choose between, and listing // its single placeholder label back ("it has: default") reads as a @@ -242,12 +242,12 @@ func resolveQuant(ctx context.Context, cfg *config.Config, repo, want string) (* if v.GGUF && !d.GGUFReady { return nil, errors.New(ggufMissingMessage(cfg)) } - return &catalog.Choice{Variant: v, BaseModel: d.BaseModel}, nil + return &resolve.Choice{Variant: v, BaseModel: d.BaseModel}, nil } // pullAndSwitch is `new` minus the flag parsing, so `search` can funnel // into it with its own options. -func pullAndSwitch(ctx context.Context, cfg *config.Config, repo string, choice *catalog.Choice, opts watchOpts) error { +func pullAndSwitch(ctx context.Context, cfg *config.Config, repo string, choice *resolve.Choice, opts watchOpts) error { name := profile.NameFromRepo(repo) if choice != nil { if _, ok := choice.Variant.Selector(); ok { @@ -263,7 +263,7 @@ func pullAndSwitch(ctx context.Context, cfg *config.Config, repo string, choice } fmt.Println("Pulling new model:", repo) - prov, err := provider.Lookup(cfg.Provider()) + prov, err := engine.Lookup(cfg.Provider()) if err != nil { return err } @@ -274,7 +274,7 @@ func pullAndSwitch(ctx context.Context, cfg *config.Config, repo string, choice fmt.Println("chat template for known crash patterns...") caps = vllmCaps(cfg) } - plan := catalog.PrepareFor(ctx, cfg.Dirs, prov, repo, choice, caps, cfg.KVContextTarget()) + plan := resolve.PrepareFor(ctx, cfg.Dirs, prov, repo, choice, caps, cfg.KVContextTarget()) for _, n := range plan.Notes { fmt.Println(n) } diff --git a/internal/cli/recipehealth.go b/internal/cli/recipehealth.go index a7c8672..88b7042 100644 --- a/internal/cli/recipehealth.go +++ b/internal/cli/recipehealth.go @@ -11,8 +11,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" ) // Two consecutive misses, two minutes apart, before relaunching. One miss is diff --git a/internal/cli/recipehealth_internal_test.go b/internal/cli/recipehealth_internal_test.go index 2c4cacf..94fc3e9 100644 --- a/internal/cli/recipehealth_internal_test.go +++ b/internal/cli/recipehealth_internal_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // The watchdog's whole job is deciding when a silent endpoint means trouble. diff --git a/internal/cli/recipelaunch.go b/internal/cli/recipelaunch.go index 7eaa3ad..345aed5 100644 --- a/internal/cli/recipelaunch.go +++ b/internal/cli/recipelaunch.go @@ -13,13 +13,13 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/recipe" ) // discoverScript reports the cluster interface, both RoCE devices and this @@ -589,8 +589,8 @@ func newRecipeProfile(dirs config.Dirs, r recipe.TestedRecipe, limit string) (*p } // An engine that takes vLLM's args keeps the sizing keys, and is still // named. - if e.ID != provider.VLLM { - p.File.Set(provider.Key, e.ID) + if e.ID != engine.VLLM { + p.File.Set(engine.Key, e.ID) } return p, nil } diff --git a/internal/cli/recipelaunch_internal_test.go b/internal/cli/recipelaunch_internal_test.go index f507115..9ee3086 100644 --- a/internal/cli/recipelaunch_internal_test.go +++ b/internal/cli/recipelaunch_internal_test.go @@ -8,10 +8,10 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/recipe" ) // Locality decides the hop. Before this was a property of the node, every @@ -262,10 +262,10 @@ func TestNewRecipeProfileNamesTheEngine(t *testing.T) { if err := os.WriteFile(filepath.Join(dir, "toyv.json"), []byte(toy), 0o644); err != nil { t.Fatal(err) } - if errs := provider.UseLocal(dir); len(errs) > 0 { + if errs := engine.UseLocal(dir); len(errs) > 0 { t.Fatal(errs) } - t.Cleanup(func() { provider.UseLocal(filepath.Join(dir, "gone")) }) + t.Cleanup(func() { engine.UseLocal(filepath.Join(dir, "gone")) }) vllmLike := testRecipe(t) vllmLike.ID = "toyv-recipe" diff --git a/internal/cli/recipes.go b/internal/cli/recipes.go index 2eeed3c..47d2360 100644 --- a/internal/cli/recipes.go +++ b/internal/cli/recipes.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/recipe" ) func newRecipesCmd() *cobra.Command { diff --git a/internal/cli/recipes_internal_test.go b/internal/cli/recipes_internal_test.go index e6221b6..82d3a4e 100644 --- a/internal/cli/recipes_internal_test.go +++ b/internal/cli/recipes_internal_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/recipe" ) // The display name column was a fixed 22 wide, so a longer name such as diff --git a/internal/cli/root.go b/internal/cli/root.go index dec775c..aa56692 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -12,14 +12,14 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" - "github.com/coder/vllm-helper/internal/service" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/service" ) // Version is stamped by goreleaser via ldflags. @@ -76,7 +76,7 @@ func newRootCmd() *cobra.Command { hardware.UseLocal(filepath.Join(config.ResolveDirs().Config, hardware.LocalDir)) // Engines load after hardware, because a local engine may name a // vendor only a local hardware definition adds. - provider.UseLocal(filepath.Join(config.ResolveDirs().Config, provider.LocalDir)) + engine.UseLocal(filepath.Join(config.ResolveDirs().Config, engine.LocalDir)) // Recipes load last, because a local recipe may run on a local // engine. recipe.UseLocal(filepath.Join(config.ResolveDirs().Config, recipe.LocalDir)) diff --git a/internal/cli/run_test.go b/internal/cli/run_test.go index d42ea10..317a176 100644 --- a/internal/cli/run_test.go +++ b/internal/cli/run_test.go @@ -15,7 +15,7 @@ import ( "sync" "testing" - "github.com/coder/vllm-helper/internal/cli" + "github.com/coder/llm-helper/internal/cli" ) const sampleProfile = `# Status: TESTED AND WORKING @@ -814,7 +814,7 @@ func TestBinaryExitCodes(t *testing.T) { t.Skip("no go toolchain to build the binary with") } bin := filepath.Join(t.TempDir(), "vllm-helper") - build := exec.Command("go", "build", "-o", bin, "github.com/coder/vllm-helper") + build := exec.Command("go", "build", "-o", bin, "github.com/coder/llm-helper") if out, err := build.CombinedOutput(); err != nil { t.Fatalf("go build: %v\n%s", err, out) } diff --git a/internal/cli/search.go b/internal/cli/search.go index 6804f3b..44f5978 100644 --- a/internal/cli/search.go +++ b/internal/cli/search.go @@ -9,12 +9,12 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/catalog" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/resolve" + "github.com/coder/llm-helper/internal/vllm" ) // cmdSearch searches HuggingFace and walks the user through picking a @@ -47,9 +47,9 @@ func runSearch(ctx context.Context, args []string, jsonOut bool) error { return fmt.Errorf("search request failed (network or rate limit): %w", err) } if jsonOut { - out := make([]catalog.Result, 0, len(models)) + out := make([]resolve.Result, 0, len(models)) for _, m := range models { - out = append(out, catalog.ToResult(m)) + out = append(out, resolve.ToResult(m)) } return printJSON(out) } @@ -152,14 +152,14 @@ func runInspect(ctx context.Context, args []string, jsonOut bool) error { // inspectModel measures a model against this machine, for the provider new // profiles are served by. cfg may be nil, which just means there is no budget // to measure against. -func inspectModel(ctx context.Context, m hf.Model, cfg *config.Config) catalog.Detail { +func inspectModel(ctx context.Context, m hf.Model, cfg *config.Config) resolve.Detail { var override string var target int - prov, _ := provider.Lookup("") + prov, _ := engine.Lookup("") if cfg != nil { override = cfg.ModelBudgetGB() target = cfg.KVContextTarget() - if p, err := provider.Lookup(cfg.Provider()); err == nil { + if p, err := engine.Lookup(cfg.Provider()); err == nil { prov = p } } @@ -168,7 +168,7 @@ func inspectModel(ctx context.Context, m hf.Model, cfg *config.Config) catalog.D if prov.Capabilities().VLLMArgs { caps = vllmCaps(cfg) } - return catalog.ForProvider(catalog.Inspect(ctx, m, detect.ModelBudget(override), caps, target), prov) + return resolve.ForProvider(resolve.Inspect(ctx, m, detect.ModelBudget(override), caps, target), prov) } // firstClause keeps the head of a reason. Repeating a full sentence on every @@ -200,7 +200,7 @@ func thousands(n int64) string { return fmt.Sprintf("%.0fk", float64(n)/1000) } -func printModelDetail(d catalog.Detail, cfg *config.Config) { +func printModelDetail(d resolve.Detail, cfg *config.Config) { fmt.Println(d.ID) fmt.Println(d.URL) fmt.Printf(" license: %s\n", d.License) @@ -290,7 +290,7 @@ func printModelDetail(d catalog.Detail, cfg *config.Config) { // while its Q8_0 is 34.8 GB and fits an 84 GB budget nearly twice over. A // reader who only sees the smallest will write the repo off, or run a 2-bit // quant without ever knowing there was a choice. -func printVariants(d catalog.Detail) { +func printVariants(d resolve.Detail) { if len(d.All) < 2 { return } @@ -326,7 +326,7 @@ func printVariants(d catalog.Detail) { // The default is pre-selected and one keypress away, so the common case costs // nothing -- but a repo holding a 2-bit and an 8-bit copy should not decide // between them on the user's behalf and say nothing. -func pickQuant(cfg *config.Config, d catalog.Detail) (choice *catalog.Choice, cancelled bool) { +func pickQuant(cfg *config.Config, d resolve.Detail) (choice *resolve.Choice, cancelled bool) { servable := make([]hf.Variant, 0, len(d.All)) for _, v := range d.All { if v.Servable() && (d.GGUFReady || !v.GGUF) { @@ -382,6 +382,6 @@ func pickQuant(cfg *config.Config, d catalog.Detail) (choice *catalog.Choice, ca if _, ok := v.Selector(); !ok { return nil, false } - return &catalog.Choice{Variant: v, BaseModel: d.BaseModel}, false + return &resolve.Choice{Variant: v, BaseModel: d.BaseModel}, false } } diff --git a/internal/cli/serve.go b/internal/cli/serve.go index 9ca1a8b..03dde50 100644 --- a/internal/cli/serve.go +++ b/internal/cli/serve.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/web" + "github.com/coder/llm-helper/internal/web" ) func newServeCmd() *cobra.Command { diff --git a/internal/cli/service.go b/internal/cli/service.go index 96322db..ace27f8 100644 --- a/internal/cli/service.go +++ b/internal/cli/service.go @@ -6,8 +6,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/profile" ) func newStopCmd() *cobra.Command { diff --git a/internal/cli/setup.go b/internal/cli/setup.go index d53a555..04ee20e 100644 --- a/internal/cli/setup.go +++ b/internal/cli/setup.go @@ -13,9 +13,9 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" ) func newSetupCmd() *cobra.Command { @@ -27,8 +27,8 @@ func newSetupCmd() *cobra.Command { Args: cobra.NoArgs, RunE: func(*cobra.Command, []string) error { return runSetup(providerName) }, } - c.Flags().StringVar(&providerName, "provider", provider.VLLM, - "inference server new profiles use: "+strings.Join(provider.ProcessNames(), ", ")+" (only written to a new config)") + c.Flags().StringVar(&providerName, "provider", engine.VLLM, + "inference server new profiles use: "+strings.Join(engine.ProcessNames(), ", ")+" (only written to a new config)") return c } @@ -37,11 +37,11 @@ func newSetupCmd() *cobra.Command { // offer to adopt a running server. Idempotent; never overwrites existing // config and never restarts anything. func runSetup(providerName string) error { - prov, err := provider.Lookup(providerName) + prov, err := engine.Lookup(providerName) if err != nil { return err } - if !prov.Has(provider.RuntimeProcess) { + if !prov.Has(engine.RuntimeProcess) { return fmt.Errorf("%s runs only in a container, so the service cannot serve it; launch it with 'llm-helper recipes launch'", prov.Name()) } dirs := config.ResolveDirs() @@ -54,7 +54,7 @@ func runSetup(providerName string) error { bin := "" if statErr != nil { bin = lookBin(prov) - if prov.Name() == provider.VLLM { + if prov.Name() == engine.VLLM { useMetalProbe(bin) } } else if found, filled, err := fillMissingVLLMBin(dirs.ConfigFile(), findVLLM); err != nil { @@ -92,7 +92,7 @@ func runSetup(providerName string) error { if statErr == nil { fmt.Println("Config already exists at", dirs.ConfigFile(), "-- keeping it.") - if prov.Name() != provider.VLLM { + if prov.Name() != engine.VLLM { fmt.Printf("--provider only shapes a new config; set PROVIDER=%s and %s in it by hand.\n", prov.Name(), prov.BinKey()) } } else { @@ -133,7 +133,7 @@ TIKTOKEN_ENCODINGS_BASE=%s #CODER_AI_PROVIDER_ID= # Only needed if the deployment has more than one organization. #CODER_ORGANIZATION=default -`, strings.Join(provider.ProcessNames(), ", "), prov.Name(), prov.BinName(), prov.BinKey(), bin, +`, strings.Join(engine.ProcessNames(), ", "), prov.Name(), prov.BinName(), prov.BinKey(), bin, config.ServiceManager, config.DefaultServiceScope, config.DefaultServiceName, hw.BudgetGB, hw.BudgetReason, hw.BudgetGB, filepath.Join(dirs.Data, "tiktoken-encodings"), detect.DefaultContextTarget, detect.DefaultContextTarget) @@ -143,7 +143,7 @@ TIKTOKEN_ENCODINGS_BASE=%s fmt.Println("Wrote", dirs.ConfigFile()) if bin == "" { fmt.Println() - if prov.Name() == provider.VLLM { + if prov.Name() == engine.VLLM { for _, line := range vllmInstallHint { fmt.Println(line) } @@ -152,8 +152,8 @@ TIKTOKEN_ENCODINGS_BASE=%s fmt.Printf("'%s'), then set %s\n", prov.InstallHint(runtime.GOOS), prov.BinKey()) fmt.Println("in config.env to its full path.") } - for _, name := range provider.ProcessNames() { - other, _ := provider.Lookup(name) + for _, name := range engine.ProcessNames() { + other, _ := engine.Lookup(name) if name == prov.Name() || lookBin(other) == "" { continue } @@ -234,7 +234,7 @@ func fillMissingVLLMBin(path string, find func() string) (string, bool, error) { if err != nil { return "", false, fmt.Errorf("reading %s: %w", path, err) } - if prov, err := provider.Lookup(f.Get(provider.Key)); err != nil || prov.Name() != provider.VLLM { + if prov, err := engine.Lookup(f.Get(engine.Key)); err != nil || prov.Name() != engine.VLLM { return "", false, nil } if strings.TrimSpace(f.Get("VLLM_BIN")) != "" { @@ -256,8 +256,8 @@ func fillMissingVLLMBin(path string, find func() string) (string, bool, error) { // up beside it. Any other server is kept as found on PATH, so a package // manager's stable link is what config.env records and an upgrade does not // break it. -func lookBin(prov provider.Provider) string { - if prov.Name() == provider.VLLM { +func lookBin(prov engine.Provider) string { + if prov.Name() == engine.VLLM { return findVLLM() } p, err := exec.LookPath(prov.BinName()) diff --git a/internal/cli/shard_internal_test.go b/internal/cli/shard_internal_test.go index 6688f54..2ae9fc8 100644 --- a/internal/cli/shard_internal_test.go +++ b/internal/cli/shard_internal_test.go @@ -8,8 +8,8 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/nodes" ) func TestShardRayEnvPrefixesUseNodeLocalHostIP(t *testing.T) { @@ -108,7 +108,7 @@ func TestShardMPServeArgs(t *testing.T) { if err != nil { t.Fatal(err) } - spec := serveSpec{Spec: provider.Spec{ + spec := serveSpec{Spec: engine.Spec{ Bin: bin, Model: "org/model", Port: "8021", diff --git a/internal/cli/shard_mp.go b/internal/cli/shard_mp.go index a6e2242..632efd4 100644 --- a/internal/cli/shard_mp.go +++ b/internal/cli/shard_mp.go @@ -11,9 +11,9 @@ import ( "strings" "syscall" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/profile" ) func normalizeShardBackend(backend string, allowAll bool) (string, error) { diff --git a/internal/cli/shardcmd.go b/internal/cli/shardcmd.go index b424777..87fac37 100644 --- a/internal/cli/shardcmd.go +++ b/internal/cli/shardcmd.go @@ -11,9 +11,9 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/profile" ) func newShardCmd() *cobra.Command { diff --git a/internal/cli/start.go b/internal/cli/start.go index d4ab096..d364095 100644 --- a/internal/cli/start.go +++ b/internal/cli/start.go @@ -9,8 +9,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/profile" ) func newStartCmd() *cobra.Command { diff --git a/internal/cli/upgrade.go b/internal/cli/upgrade.go index 963bf0a..738f4bf 100644 --- a/internal/cli/upgrade.go +++ b/internal/cli/upgrade.go @@ -9,8 +9,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/update" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/update" ) // updateChannelKey selects where upgrades come from. It lives in config.env diff --git a/internal/cli/upgrade_internal_test.go b/internal/cli/upgrade_internal_test.go index ecf4cbb..d5acc03 100644 --- a/internal/cli/upgrade_internal_test.go +++ b/internal/cli/upgrade_internal_test.go @@ -5,8 +5,8 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/update" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/update" ) // Upgrading has to work on a machine that has never run setup -- that is diff --git a/internal/cli/vllmargs.go b/internal/cli/vllmargs.go index d4b5815..9b37363 100644 --- a/internal/cli/vllmargs.go +++ b/internal/cli/vllmargs.go @@ -5,27 +5,27 @@ import ( "os" "strings" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/recipe" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/recipe" ) type serveSpec struct { // Provider is nil for vLLM, so a spec built without one keeps meaning // what it meant before there was a choice. - Provider provider.Provider - provider.Spec + Provider engine.Provider + engine.Spec } func serveSpecFromActive(active *config.EnvFile) (serveSpec, error) { - prov, err := provider.Lookup(active.Get(provider.Key)) + prov, err := engine.Lookup(active.Get(engine.Key)) if err != nil { return serveSpec{}, err } - return serveSpec{Provider: prov, Spec: provider.Spec{ + return serveSpec{Provider: prov, Spec: engine.Spec{ Bin: active.Get(prov.BinKey()), Model: active.Get("MODEL"), Port: active.Get("PORT"), @@ -45,7 +45,7 @@ func serveSpecFromProfile(cfg *config.Config, p *profile.Profile, port string) ( if err != nil { return serveSpec{}, err } - return serveSpec{Provider: prov, Spec: provider.Spec{ + return serveSpec{Provider: prov, Spec: engine.Spec{ Bin: cfg.Lookup(prov.BinKey(), ""), Model: p.Model(), Port: port, @@ -61,20 +61,20 @@ func serveSpecFromProfile(cfg *config.Config, p *profile.Profile, port string) ( // own PROVIDER counts: config.env's names the default for new profiles, and // letting it reach an existing one would hand a vLLM profile's flags to // another server. -func profileProvider(p *profile.Profile) (provider.Provider, error) { - return provider.Lookup(p.Provider()) +func profileProvider(p *profile.Profile) (engine.Provider, error) { + return engine.Lookup(p.Provider()) } -func (s serveSpec) provider() provider.Provider { +func (s serveSpec) provider() engine.Provider { if s.Provider != nil { return s.Provider } - p, _ := provider.Lookup(provider.VLLM) + p, _ := engine.Lookup(engine.VLLM) return p } func (s serveSpec) validate() error { - return provider.Validate(s.provider(), s.Spec) + return engine.Validate(s.provider(), s.Spec) } // args is the provider's command line with extra appended. Validation comes @@ -177,7 +177,7 @@ func withPCIBusOrder(env []string) []string { // replaces an inherited entry of the same name, because a duplicate would // leave the server reading whichever copy its libc finds first. func withProviderEnv(env []string, s serveSpec) []string { - ep, ok := s.provider().(provider.EnvProvider) + ep, ok := s.provider().(engine.EnvProvider) if !ok { return env } diff --git a/internal/cli/vllmargs_internal_test.go b/internal/cli/vllmargs_internal_test.go index 78075f6..aa7c4b0 100644 --- a/internal/cli/vllmargs_internal_test.go +++ b/internal/cli/vllmargs_internal_test.go @@ -7,10 +7,10 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/profile" ) func TestRedactServeArgs(t *testing.T) { @@ -153,17 +153,17 @@ func TestRequireVLLM(t *testing.T) { // inherited, and a vLLM spec's environment is left as it was. func TestWithProviderEnv(t *testing.T) { t.Parallel() - llama, err := provider.Lookup(provider.LlamaCPP) + llama, err := engine.Lookup(engine.LlamaCPP) if err != nil { t.Fatal(err) } env := []string{"PATH=/usr/bin", "LLAMA_API_KEY=stale", "VLLM_API_KEY=sk-x"} - got := withProviderEnv(env, serveSpec{Provider: llama, Spec: provider.Spec{APIKey: "sk-x"}}) + got := withProviderEnv(env, serveSpec{Provider: llama, Spec: engine.Spec{APIKey: "sk-x"}}) want := []string{"PATH=/usr/bin", "VLLM_API_KEY=sk-x", "LLAMA_API_KEY=sk-x"} if !reflect.DeepEqual(got, want) { t.Errorf("llamacpp env = %q, want %q", got, want) } - if got := withProviderEnv(env, serveSpec{Spec: provider.Spec{APIKey: "sk-x"}}); !reflect.DeepEqual(got, env) { + if got := withProviderEnv(env, serveSpec{Spec: engine.Spec{APIKey: "sk-x"}}); !reflect.DeepEqual(got, env) { t.Errorf("vllm env = %q, want it unchanged", got) } } @@ -184,7 +184,7 @@ func TestServeArgsRefuseAFlagThisArchitectureAbortsOn(t *testing.T) { if err := os.WriteFile(bin, []byte("#!/bin/sh\n"), 0o755); err != nil { t.Fatal(err) } - spec := serveSpec{Spec: provider.Spec{ + spec := serveSpec{Spec: engine.Spec{ Bin: bin, Model: "m", Port: "8001", ExtraArgs: "--moe-backend deep_gemm_mega_moe", }} @@ -208,7 +208,7 @@ func TestServeArgsRefuseAFlagThisArchitectureAbortsOn(t *testing.T) { // A shard's workers run the head's command line on their own hardware, so a // worker the registry knows is a GB10 is checked before any node is touched. func TestCheckNodesRefusesAWorkerThatWouldAbort(t *testing.T) { - spec := serveSpec{Spec: provider.Spec{ + spec := serveSpec{Spec: engine.Spec{ Bin: "/opt/vllm/bin/vllm", Model: "m", Port: "8001", ExtraArgs: "--moe-backend deep_gemm_mega_moe", }} @@ -229,7 +229,7 @@ func TestCheckNodesRefusesAWorkerThatWouldAbort(t *testing.T) { // architecture for it, or a stale one. Checking it only when the command was // built let --stop-services stop every node's server first. func TestCheckNodesChecksTheHeadAgainstThisMachine(t *testing.T) { - spec := serveSpec{Spec: provider.Spec{ + spec := serveSpec{Spec: engine.Spec{ Bin: "/opt/vllm/bin/vllm", Model: "m", Port: "8001", ExtraArgs: "--moe-backend deep_gemm_mega_moe", }} diff --git a/internal/cli/vllmbin_internal_test.go b/internal/cli/vllmbin_internal_test.go index 0f3efb5..505af85 100644 --- a/internal/cli/vllmbin_internal_test.go +++ b/internal/cli/vllmbin_internal_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // /opt/homebrew/bin/vllm resolves into a versioned Cellar directory that the diff --git a/internal/cli/watch.go b/internal/cli/watch.go index 52ef4d1..529c598 100644 --- a/internal/cli/watch.go +++ b/internal/cli/watch.go @@ -6,8 +6,8 @@ import ( "os" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" ) // watchOpts controls how a restart is observed. diff --git a/internal/cli/watch_internal_test.go b/internal/cli/watch_internal_test.go index 102d150..c646c51 100644 --- a/internal/cli/watch_internal_test.go +++ b/internal/cli/watch_internal_test.go @@ -12,9 +12,9 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/nodes" - "github.com/coder/vllm-helper/internal/service" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/nodes" + "github.com/coder/llm-helper/internal/service" ) // The boot wait has to ask the machine that serves. A cluster's head can be diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 0e23aa3..e9d1c60 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -6,7 +6,7 @@ import ( "reflect" "testing" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // writeFile creates a file and the directories leading to it. diff --git a/internal/config/shellwords_test.go b/internal/config/shellwords_test.go index df7f691..9762a74 100644 --- a/internal/config/shellwords_test.go +++ b/internal/config/shellwords_test.go @@ -4,7 +4,7 @@ import ( "reflect" "testing" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) func TestSplitWords(t *testing.T) { diff --git a/internal/control/control.go b/internal/control/control.go index 20c1b27..404ee41 100644 --- a/internal/control/control.go +++ b/internal/control/control.go @@ -19,10 +19,10 @@ import ( "strings" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/profile" ) // BaseURL is where the model server answers on this machine. @@ -46,7 +46,7 @@ func BaseURL(cfg *config.Config) string { func WriteActiveEnv(cfg *config.Config, p *profile.Profile) error { // An unknown provider would otherwise surface only when the service tried // to start it, by which time the outgoing model is already down. - if _, err := provider.Lookup(p.Provider()); err != nil { + if _, err := engine.Lookup(p.Provider()); err != nil { return fmt.Errorf("profile '%s': %w", p.Name, err) } if err := os.MkdirAll(cfg.Dirs.State, 0o755); err != nil { @@ -75,7 +75,7 @@ func WriteActiveEnv(cfg *config.Config, p *profile.Profile) error { // default to override, so an install that never set one gets the file // it always got. if p.Provider() == "" && cfg.Provider() != "" { - b.WriteString(provider.Key + "=" + provider.VLLM + "\n") + b.WriteString(engine.Key + "=" + engine.VLLM + "\n") } // Written and renamed rather than truncated in place: a crash halfway @@ -182,7 +182,7 @@ func ActiveHealthPath(cfg *config.Config) string { if err != nil { return "" } - e, err := provider.LookupEngine(active.Get(provider.Key)) + e, err := engine.LookupEngine(active.Get(engine.Key)) if err != nil { return "" } diff --git a/internal/control/control_internal_test.go b/internal/control/control_internal_test.go index 8b5e461..1ee9c34 100644 --- a/internal/control/control_internal_test.go +++ b/internal/control/control_internal_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/profile" ) // active.env is sourced by the service, so what goes into it decides the argv diff --git a/internal/control/gguf.go b/internal/control/gguf.go index ddc5f81..ef522b7 100644 --- a/internal/control/gguf.go +++ b/internal/control/gguf.go @@ -9,8 +9,8 @@ import ( "os/exec" "path/filepath" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/vllm" ) // GGUF support left vLLM core in 0.27.1 and lives in an out-of-tree package. diff --git a/internal/control/gpus.go b/internal/control/gpus.go index 8523819..267f632 100644 --- a/internal/control/gpus.go +++ b/internal/control/gpus.go @@ -3,8 +3,8 @@ package control import ( "os" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" ) // CUDAVisible is the CUDA_VISIBLE_DEVICES a server started with these env diff --git a/internal/detect/classify.go b/internal/detect/classify.go index d60bb02..04fbfd1 100644 --- a/internal/detect/classify.go +++ b/internal/detect/classify.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // What decided whether a GPU's memory is shared with the CPU, strongest diff --git a/internal/detect/container_test.go b/internal/detect/container_test.go index 6d82784..c0c7634 100644 --- a/internal/detect/container_test.go +++ b/internal/detect/container_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) func TestScanContainersAgainstTheRealRuntime(t *testing.T) { diff --git a/internal/detect/endpoint_test.go b/internal/detect/endpoint_test.go index e7ae715..f0dd1af 100644 --- a/internal/detect/endpoint_test.go +++ b/internal/detect/endpoint_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) // serveOn starts an OpenAI-shaped server and returns the port it listens on. diff --git a/internal/detect/fixtures_internal_test.go b/internal/detect/fixtures_internal_test.go index 97e54cd..15a8216 100644 --- a/internal/detect/fixtures_internal_test.go +++ b/internal/detect/fixtures_internal_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // fixtureDir holds the hardware reports the definitions are tested against. diff --git a/internal/detect/hardware_internal_test.go b/internal/detect/hardware_internal_test.go index 55e9244..441d325 100644 --- a/internal/detect/hardware_internal_test.go +++ b/internal/detect/hardware_internal_test.go @@ -4,7 +4,7 @@ import ( "testing" "testing/fstest" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // unifiedFor classifies one NVIDIA GPU the way the probe does. diff --git a/internal/detect/hardware_test.go b/internal/detect/hardware_test.go index d6d3f89..ffc2e1f 100644 --- a/internal/detect/hardware_test.go +++ b/internal/detect/hardware_test.go @@ -5,7 +5,7 @@ package detect_test import ( "testing" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/detect" ) // The budget drives whether `search` calls a model too big, so a zero here diff --git a/internal/detect/process.go b/internal/detect/process.go index 232919e..892257a 100644 --- a/internal/detect/process.go +++ b/internal/detect/process.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // Server is one detected vLLM server and everything we learned about it. diff --git a/internal/detect/process_internal_test.go b/internal/detect/process_internal_test.go index 47502a3..f1680ba 100644 --- a/internal/detect/process_internal_test.go +++ b/internal/detect/process_internal_test.go @@ -5,7 +5,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // Real-world argv observed on a GB10 box (venv console-script form). diff --git a/internal/detect/report.go b/internal/detect/report.go index 949bd81..0cac2b7 100644 --- a/internal/detect/report.go +++ b/internal/detect/report.go @@ -1,7 +1,7 @@ package detect import ( - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // Report is what 'hardware report' prints and what a hardware fixture holds: diff --git a/internal/provider/engine.go b/internal/engine/engine.go similarity index 99% rename from internal/provider/engine.go rename to internal/engine/engine.go index c9ab999..2030457 100644 --- a/internal/provider/engine.go +++ b/internal/engine/engine.go @@ -1,4 +1,4 @@ -package provider +package engine import ( "bytes" @@ -13,9 +13,9 @@ import ( "slices" "strings" - "github.com/coder/vllm-helper/catalogue" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/catalogue" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/hardware" ) // SchemaVersion is the engine definitions format this build reads. A file diff --git a/internal/provider/engine_test.go b/internal/engine/engine_test.go similarity index 80% rename from internal/provider/engine_test.go rename to internal/engine/engine_test.go index 649bd00..6b3ca70 100644 --- a/internal/provider/engine_test.go +++ b/internal/engine/engine_test.go @@ -1,4 +1,4 @@ -package provider_test +package engine_test import ( "io/fs" @@ -9,8 +9,8 @@ import ( "testing" "testing/fstest" - "github.com/coder/vllm-helper/catalogue" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/catalogue" + "github.com/coder/llm-helper/internal/engine" ) const secretKey = "sk-never-on-argv" @@ -20,15 +20,15 @@ const secretKey = "sk-never-on-argv" // user on the machine. func TestShippedEnginesHoldTheContract(t *testing.T) { t.Parallel() - for _, e := range provider.Shipped().Engines() { + for _, e := range engine.Shipped().Engines() { if strings.TrimSpace(e.Why) == "" { t.Errorf("%s: no why", e.ID) } - if e.Has(provider.RuntimeProcess) { + if e.Has(engine.RuntimeProcess) { if e.InstallHint("linux") == "" || e.InstallHint("darwin") == "" { t.Errorf("%s: a process engine needs an install hint on every OS", e.ID) } - argv, err := e.Command(provider.Spec{Bin: "/x", Model: "org/m", Port: "8001", APIKey: secretKey}) + argv, err := e.Command(engine.Spec{Bin: "/x", Model: "org/m", Port: "8001", APIKey: secretKey}) if err != nil { t.Fatalf("%s: %v", e.ID, err) } @@ -42,7 +42,7 @@ func TestShippedEnginesHoldTheContract(t *testing.T) { } } } - if !e.Has(provider.RuntimeContainer) { + if !e.Has(engine.RuntimeContainer) { continue } serving := 0 @@ -54,16 +54,16 @@ func TestShippedEnginesHoldTheContract(t *testing.T) { if serving != 1 { t.Errorf("%s: %d roles serve HTTP, want 1", e.ID, serving) } - models := map[string]provider.ModelRef{} + models := map[string]engine.ModelRef{} for _, role := range e.UsesModelPaths() { - models[role] = provider.ModelRef{ID: "org/" + role, Revision: strings.Repeat("a", 40)} + models[role] = engine.ModelRef{ID: "org/" + role, Revision: strings.Repeat("a", 40)} } for rank := range 4 { r, err := e.RoleFor(rank) if err != nil { t.Fatalf("%s: %v", e.ID, err) } - _, args, env := e.RenderRole(r, provider.RoleValues{ + _, args, env := e.RenderRole(r, engine.RoleValues{ Model: "m", Port: 8000, Rank: rank, Nodes: 4, MasterAddr: "10.0.0.1", MasterPort: 29500, Args: []string{"--x", "1"}, Models: models, }) @@ -91,11 +91,11 @@ func TestShippedEnginesHoldTheContract(t *testing.T) { // CUDA, so neither may be overridden. func TestTensorFoldPythonKeepsTheImageEntrypointAndTakesNoKey(t *testing.T) { t.Parallel() - e, ok := provider.Shipped().Get("tensorfold-python") + e, ok := engine.Shipped().Get("tensorfold-python") if !ok { t.Fatal("tensorfold-python is not shipped") } - if e.Has(provider.RuntimeProcess) { + if e.Has(engine.RuntimeProcess) { t.Error("tensorfold-python runs only in a container") } if e.Capabilities().APIKey || e.ContainerKeyEnv() != "" { @@ -103,7 +103,7 @@ func TestTensorFoldPythonKeepsTheImageEntrypointAndTakesNoKey(t *testing.T) { } for rank := range 2 { r, _ := e.RoleFor(rank) - if ep, _, _ := e.RenderRole(r, provider.RoleValues{}); ep != "" { + if ep, _, _ := e.RenderRole(r, engine.RoleValues{}); ep != "" { t.Errorf("rank %d overrides the image entrypoint with %q", rank, ep) } } @@ -154,7 +154,7 @@ const toyProcess = `{ func TestParseIsStrict(t *testing.T) { t.Parallel() for _, base := range []string{toyContainer, toyProcess} { - if _, err := provider.Parse([]byte(base)); err != nil { + if _, err := engine.Parse([]byte(base)); err != nil { t.Fatalf("the base definition does not parse: %v", err) } } @@ -182,7 +182,7 @@ func TestParseIsStrict(t *testing.T) { if data == tc.base && tc.name != "trailing data" { t.Fatalf("%s: the edit matched nothing", tc.name) } - _, err := provider.Parse([]byte(data)) + _, err := engine.Parse([]byte(data)) if err == nil || !strings.Contains(err.Error(), tc.want) { t.Errorf("%s: err = %v, want it to mention %q", tc.name, err, tc.want) } @@ -194,12 +194,12 @@ func TestParseIsStrict(t *testing.T) { func TestLaunchArgsFillSharedValues(t *testing.T) { t.Parallel() data := strings.Replace(toyContainer, `"api_key": "none"`, `"api_key": "none", "launch_args": ["--served-model-name", "{model}", "--threads", "{threads}"]`, 1) - r, err := provider.Parse([]byte(data)) + r, err := engine.Parse([]byte(data)) if err != nil { t.Fatal(err) } e, _ := r.Get("toy") - got := e.LaunchArgs(provider.RoleValues{Model: "org/m", Port: 8000}) + got := e.LaunchArgs(engine.RoleValues{Model: "org/m", Port: 8000}) if want := []string{"--served-model-name", "org/m", "--threads", "4"}; !slices.Equal(got, want) { t.Errorf("LaunchArgs = %v, want %v", got, want) } @@ -209,7 +209,7 @@ func TestLaunchArgsFillSharedValues(t *testing.T) { // chat template's {{bos_token}} is not a placeholder. func TestRenderRoleLeavesArgsAlone(t *testing.T) { t.Parallel() - r, err := provider.Parse([]byte(toyContainer)) + r, err := engine.Parse([]byte(toyContainer)) if err != nil { t.Fatal(err) } @@ -219,7 +219,7 @@ func TestRenderRoleLeavesArgsAlone(t *testing.T) { t.Fatal(err) } tmpl := "{{bos_token}}{model}" - _, args, _ := e.RenderRole(role, provider.RoleValues{Model: "org/m", Port: 8000, Nodes: 1, Args: []string{"--chat-template", tmpl}}) + _, args, _ := e.RenderRole(role, engine.RoleValues{Model: "org/m", Port: 8000, Nodes: 1, Args: []string{"--chat-template", tmpl}}) if got := args[len(args)-1]; got != tmpl { t.Errorf("--chat-template = %q, want %q as written", got, tmpl) } @@ -227,7 +227,7 @@ func TestRenderRoleLeavesArgsAlone(t *testing.T) { func TestExtendOnlyAdds(t *testing.T) { t.Parallel() - r, err := provider.Shipped().Extend([]byte(toyContainer), "/etc/toy.json") + r, err := engine.Shipped().Extend([]byte(toyContainer), "/etc/toy.json") if err != nil { t.Fatal(err) } @@ -235,19 +235,19 @@ func TestExtendOnlyAdds(t *testing.T) { if !ok || e.Source != "/etc/toy.json" { t.Fatalf("toy = %+v, %v", e, ok) } - if _, ok := provider.Shipped().Get("toy"); ok { + if _, ok := engine.Shipped().Get("toy"); ok { t.Error("Extend changed the registry it extended") } redefine := strings.Replace(toyContainer, `"id": "toy"`, `"id": "vllm"`, 1) - if _, err := provider.Shipped().Extend([]byte(redefine), "x.json"); err == nil || !strings.Contains(err.Error(), "already defined") { + if _, err := engine.Shipped().Extend([]byte(redefine), "x.json"); err == nil || !strings.Contains(err.Error(), "already defined") { t.Errorf("redefining vllm: err = %v", err) } invalid := strings.Replace(toyContainer, `"{threads}"`, `"{nope}"`, 1) - if _, err := provider.Shipped().Extend([]byte(invalid), "toy.json"); err == nil { + if _, err := engine.Shipped().Extend([]byte(invalid), "toy.json"); err == nil { t.Error("an invalid local engine was accepted") } - if _, err := provider.Shipped().Extend([]byte(toyContainer), "/etc/other.json"); err == nil || !strings.Contains(err.Error(), "toy.json") { + if _, err := engine.Shipped().Extend([]byte(toyContainer), "/etc/other.json"); err == nil || !strings.Contains(err.Error(), "toy.json") { t.Errorf("a file named for another engine: err = %v", err) } } @@ -255,10 +255,10 @@ func TestExtendOnlyAdds(t *testing.T) { // Load refuses a folder whose file names and ids disagree, naming the file. func TestLoadHoldsFilesToTheirIDs(t *testing.T) { t.Parallel() - if _, err := provider.Load(fstest.MapFS{"toy.json": {Data: []byte(toyContainer)}}); err != nil { + if _, err := engine.Load(fstest.MapFS{"toy.json": {Data: []byte(toyContainer)}}); err != nil { t.Fatalf("a well-named folder: %v", err) } - _, err := provider.Load(fstest.MapFS{"toy.json": {Data: []byte(toyContainer)}, "box.json": {Data: []byte(toyProcess)}}) + _, err := engine.Load(fstest.MapFS{"toy.json": {Data: []byte(toyContainer)}, "box.json": {Data: []byte(toyProcess)}}) if err == nil || !strings.Contains(err.Error(), "box.json") || !strings.Contains(err.Error(), "toyp.json") { t.Errorf("a misnamed file: err = %v", err) } @@ -273,7 +273,7 @@ func TestShippedEnginesAreOneFileEach(t *testing.T) { t.Fatal(err) } var ids []string - for _, e := range provider.Shipped().Engines() { + for _, e := range engine.Shipped().Engines() { ids = append(ids, e.ID+".json") } if !slices.Equal(names, ids) { @@ -297,9 +297,9 @@ func TestUseLocalSkipsAndReportsBadFiles(t *testing.T) { t.Fatal(err) } } - t.Cleanup(func() { provider.UseLocal(filepath.Join(t.TempDir(), "gone")) }) + t.Cleanup(func() { engine.UseLocal(filepath.Join(t.TempDir(), "gone")) }) - errs := provider.UseLocal(dir) + errs := engine.UseLocal(dir) // A file is named after the engine it defines, so the misnamed one is // refused too. wantErrs := []string{"broken.json", "misnamed.json", "vllm.json"} @@ -311,29 +311,29 @@ func TestUseLocalSkipsAndReportsBadFiles(t *testing.T) { t.Errorf("error %d = %v, want it to name %s", i, errs[i], name) } } - if got := provider.LocalErrors(); len(got) != len(wantErrs) { + if got := engine.LocalErrors(); len(got) != len(wantErrs) { t.Errorf("LocalErrors = %v", got) } for _, id := range []string{"toy", "toyp"} { - e, ok := provider.Default().Get(id) + e, ok := engine.Default().Get(id) if !ok || !strings.HasPrefix(e.Source, dir) { t.Errorf("%s = %+v, %v; a good file after a bad one must still load", id, e, ok) } } - if e, _ := provider.Default().Get("vllm"); e.Source != "" { + if e, _ := engine.Default().Get("vllm"); e.Source != "" { t.Errorf("vllm comes from %q; a local file redefined it", e.Source) } - if _, err := provider.LookupEngine("toyp"); err != nil { + if _, err := engine.LookupEngine("toyp"); err != nil { t.Errorf("a local engine cannot be selected: %v", err) } - if errs := provider.UseLocal(filepath.Join(dir, "missing")); len(errs) != 0 { + if errs := engine.UseLocal(filepath.Join(dir, "missing")); len(errs) != 0 { t.Errorf("a missing directory is an error: %v", errs) } - if _, ok := provider.Default().Get("toy"); ok { + if _, ok := engine.Default().Get("toy"); ok { t.Error("UseLocal kept engines from a directory it no longer reads") } - if len(provider.LocalErrors()) != 0 { + if len(engine.LocalErrors()) != 0 { t.Error("UseLocal kept errors from a directory it no longer reads") } } diff --git a/internal/provider/local.go b/internal/engine/local.go similarity index 99% rename from internal/provider/local.go rename to internal/engine/local.go index 90aa00d..0d7edc8 100644 --- a/internal/provider/local.go +++ b/internal/engine/local.go @@ -1,4 +1,4 @@ -package provider +package engine import ( "errors" diff --git a/internal/provider/provider.go b/internal/engine/registry.go similarity index 96% rename from internal/provider/provider.go rename to internal/engine/registry.go index ab06625..5506a2b 100644 --- a/internal/provider/provider.go +++ b/internal/engine/registry.go @@ -1,6 +1,5 @@ -// Package provider describes the inference servers a profile or recipe can -// run on. Each one is an engine, defined as data in its own file under -// catalogue/engines/. +// Package engine describes the inference servers a profile or recipe can +// run on, each defined as data in its own file under catalogue/engines/. // // An engine only decides how a profile becomes a command line: which // executable, which flags, which environment, and what that server can be @@ -13,7 +12,7 @@ // The data is parsed strictly. An unknown key, a duplicate id, or a // placeholder a template cannot fill is an error, so a typo fails when the // definition loads rather than reaching the server as an empty argument. -package provider +package engine import ( "fmt" diff --git a/internal/provider/provider_test.go b/internal/engine/registry_test.go similarity index 81% rename from internal/provider/provider_test.go rename to internal/engine/registry_test.go index caf0de8..324d7b8 100644 --- a/internal/provider/provider_test.go +++ b/internal/engine/registry_test.go @@ -1,4 +1,4 @@ -package provider_test +package engine_test import ( "os" @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/engine" ) // Every install from before providers existed has no PROVIDER line, and must @@ -15,11 +15,11 @@ import ( func TestLookupDefaultsToVLLM(t *testing.T) { t.Parallel() for _, name := range []string{"", " ", "vllm", "VLLM"} { - p, err := provider.Lookup(name) + p, err := engine.Lookup(name) if err != nil { t.Fatalf("Lookup(%q): %v", name, err) } - if p.Name() != provider.VLLM { + if p.Name() != engine.VLLM { t.Errorf("Lookup(%q) = %s, want vllm", name, p.Name()) } } @@ -27,7 +27,7 @@ func TestLookupDefaultsToVLLM(t *testing.T) { func TestLookupRejectsUnknownNamingTheChoices(t *testing.T) { t.Parallel() - _, err := provider.Lookup("ollama") + _, err := engine.Lookup("ollama") if err == nil { t.Fatal("an unknown provider must be an error, not a silent fallback to vLLM") } @@ -41,8 +41,8 @@ func TestLookupRejectsUnknownNamingTheChoices(t *testing.T) { // The argv vLLM gets is pinned, so moving it behind the seam changes nothing. func TestVLLMCommand(t *testing.T) { t.Parallel() - p, _ := provider.Lookup(provider.VLLM) - got, err := p.Command(provider.Spec{ + p, _ := engine.Lookup(engine.VLLM) + got, err := p.Command(engine.Spec{ Bin: "/opt/vllm/bin/vllm", Model: "Qwen/Qwen3-32B", Port: "8001", MaxModelLen: "32768", MemUtilization: "0.85", APIKey: "sk-x", KVCacheBytes: "1000", ExtraArgs: `--tool-call-parser hermes --chat-template "/a b.jinja"`, @@ -63,8 +63,8 @@ func TestVLLMCommand(t *testing.T) { // is an argparse error that crash-loops the service. func TestMLXCommandCarriesNoVLLMFlags(t *testing.T) { t.Parallel() - p, _ := provider.Lookup(provider.MLX) - got, err := p.Command(provider.Spec{ + p, _ := engine.Lookup(engine.MLX) + got, err := p.Command(engine.Spec{ Bin: "/v/bin/mlx_lm.server", Model: "mlx-community/Qwen3-4B-4bit", Port: "8001", MaxModelLen: "32768", MemUtilization: "0.85", APIKey: "sk-x", KVCacheBytes: "1000", ExtraArgs: "--host 0.0.0.0 --max-tokens 8192", @@ -88,7 +88,7 @@ func TestMLXCommandCarriesNoVLLMFlags(t *testing.T) { // and status look for. func TestLlamaCPPCommand(t *testing.T) { t.Parallel() - p, _ := provider.Lookup(provider.LlamaCPP) + p, _ := engine.Lookup(engine.LlamaCPP) bin := "/opt/homebrew/bin/llama-server" for _, tc := range []struct { name, model, apiKey, source string @@ -100,7 +100,7 @@ func TestLlamaCPPCommand(t *testing.T) { {"relative file", "qwen3-32b-q8_0.GGUF", "sk-x", "-m", true}, {"no key", "Qwen/Qwen2.5-0.5B-Instruct-GGUF", "", "-hf", false}, } { - got, err := p.Command(provider.Spec{ + got, err := p.Command(engine.Spec{ Bin: bin, Model: tc.model, Port: "8001", APIKey: tc.apiKey, MaxModelLen: "32768", MemUtilization: "0.85", KVCacheBytes: "1000", ExtraArgs: `-c 65536 --chat-template-file "/a b.jinja"`, @@ -119,7 +119,7 @@ func TestLlamaCPPCommand(t *testing.T) { if !reflect.DeepEqual(got, want) { t.Errorf("%s: argv\n got %q\nwant %q", tc.name, got, want) } - envp, ok := p.(provider.EnvProvider) + envp, ok := p.(engine.EnvProvider) if !ok { t.Fatalf("llamacpp does not pass its key through the environment") } @@ -127,7 +127,7 @@ func TestLlamaCPPCommand(t *testing.T) { if tc.wantKey { wantEnv = []string{"LLAMA_API_KEY=" + tc.apiKey} } - if gotEnv := envp.Env(provider.Spec{APIKey: tc.apiKey}); !reflect.DeepEqual(gotEnv, wantEnv) { + if gotEnv := envp.Env(engine.Spec{APIKey: tc.apiKey}); !reflect.DeepEqual(gotEnv, wantEnv) { t.Errorf("%s: env = %q, want %q", tc.name, gotEnv, wantEnv) } } @@ -138,9 +138,9 @@ func TestLlamaCPPCommand(t *testing.T) { func TestCommandRejectsUnparseableExtraArgs(t *testing.T) { t.Parallel() - for _, name := range provider.Names() { - p, _ := provider.Lookup(name) - if _, err := p.Command(provider.Spec{Bin: "/x", Model: "m", Port: "1", ExtraArgs: `--a "unterminated`}); err == nil { + for _, name := range engine.Names() { + p, _ := engine.Lookup(name) + if _, err := p.Command(engine.Spec{Bin: "/x", Model: "m", Port: "1", ExtraArgs: `--a "unterminated`}); err == nil { t.Errorf("%s: unbalanced quote in EXTRA_ARGS was accepted", name) } } @@ -150,8 +150,8 @@ func TestCommandRejectsUnparseableExtraArgs(t *testing.T) { // told to fix VLLM_BIN. func TestValidateNamesTheProvidersBinKey(t *testing.T) { t.Parallel() - p, _ := provider.Lookup(provider.MLX) - err := provider.Validate(p, provider.Spec{Model: "m", Port: "1"}) + p, _ := engine.Lookup(engine.MLX) + err := engine.Validate(p, engine.Spec{Model: "m", Port: "1"}) if err == nil || !strings.Contains(err.Error(), "MLX_LM_BIN") { t.Fatalf("Validate with no bin = %v, want it to name MLX_LM_BIN", err) } @@ -160,7 +160,7 @@ func TestValidateNamesTheProvidersBinKey(t *testing.T) { if err := os.WriteFile(notExec, nil, 0o644); err != nil { t.Fatal(err) } - if err := provider.Validate(p, provider.Spec{Bin: notExec, Model: "m", Port: "1"}); err == nil { + if err := engine.Validate(p, engine.Spec{Bin: notExec, Model: "m", Port: "1"}); err == nil { t.Fatal("a non-executable bin passed validation") } @@ -168,10 +168,10 @@ func TestValidateNamesTheProvidersBinKey(t *testing.T) { if err := os.WriteFile(bin, nil, 0o755); err != nil { t.Fatal(err) } - if err := provider.Validate(p, provider.Spec{Bin: bin, Port: "1"}); err == nil || !strings.Contains(err.Error(), "MODEL") { + if err := engine.Validate(p, engine.Spec{Bin: bin, Port: "1"}); err == nil || !strings.Contains(err.Error(), "MODEL") { t.Fatalf("Validate with no model = %v", err) } - if err := provider.Validate(p, provider.Spec{Bin: bin, Model: "m", Port: "1"}); err != nil { + if err := engine.Validate(p, engine.Spec{Bin: bin, Model: "m", Port: "1"}); err != nil { t.Fatalf("a complete spec failed validation: %v", err) } } diff --git a/internal/hardware/hardware.go b/internal/hardware/hardware.go index 2e2ab93..b8ee8ba 100644 --- a/internal/hardware/hardware.go +++ b/internal/hardware/hardware.go @@ -31,7 +31,7 @@ import ( "slices" "strings" - "github.com/coder/vllm-helper/catalogue" + "github.com/coder/llm-helper/catalogue" ) // SchemaVersion is the definitions format this build reads. A file written diff --git a/internal/hardware/hardware_test.go b/internal/hardware/hardware_test.go index fd1bbff..8192dc1 100644 --- a/internal/hardware/hardware_test.go +++ b/internal/hardware/hardware_test.go @@ -8,7 +8,7 @@ import ( "testing" "testing/fstest" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // The definitions replaced one hardcoded pattern. Until a definition is added diff --git a/internal/hf/snippet.go b/internal/hf/snippet.go index ea41475..5080df1 100644 --- a/internal/hf/snippet.go +++ b/internal/hf/snippet.go @@ -4,7 +4,7 @@ import ( "regexp" "strings" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // ownedFlags are set by vllm-helper itself from config and the profile, so a diff --git a/internal/hf/testsupport.go b/internal/hf/testsupport.go index aee6373..57aa1a2 100644 --- a/internal/hf/testsupport.go +++ b/internal/hf/testsupport.go @@ -3,7 +3,7 @@ package hf // SetBaseURLForTest points the Hub client at a test server and returns a // function that restores the previous value. // -// Exported because catalog's tests need it as well: the judgements worth +// Exported because resolve's tests need it as well: the judgements worth // testing -- which quants are offered, what is refused -- live there, and // they need a Hub that answers predictably. It is inert outside a test, since // nothing else ever calls it. diff --git a/internal/nodes/registry.go b/internal/nodes/registry.go index 575dda1..b81ae9a 100644 --- a/internal/nodes/registry.go +++ b/internal/nodes/registry.go @@ -8,7 +8,7 @@ import ( "sort" "sync" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // NIC describes a network interface. diff --git a/internal/plugin/coder/adopt_test.go b/internal/plugin/coder/adopt_test.go index 16e0794..637a6df 100644 --- a/internal/plugin/coder/adopt_test.go +++ b/internal/plugin/coder/adopt_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/plugin/coder" + "github.com/coder/llm-helper/internal/plugin/coder" ) // listing serves a fixed collection to every path, the way newClient does. diff --git a/internal/plugin/coder/client_test.go b/internal/plugin/coder/client_test.go index 9ed86af..f8546b5 100644 --- a/internal/plugin/coder/client_test.go +++ b/internal/plugin/coder/client_test.go @@ -7,7 +7,7 @@ import ( "net/http/httptest" "testing" - "github.com/coder/vllm-helper/internal/plugin/coder" + "github.com/coder/llm-helper/internal/plugin/coder" ) // Where a current deployment keeps the collection. The stand-in below answers diff --git a/internal/plugin/coder/options_internal_test.go b/internal/plugin/coder/options_internal_test.go index ab2e125..b013b84 100644 --- a/internal/plugin/coder/options_internal_test.go +++ b/internal/plugin/coder/options_internal_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) func cfgWith(kv map[string]string) *config.Config { diff --git a/internal/plugin/coder/prune_test.go b/internal/plugin/coder/prune_test.go index 503f90c..965f12c 100644 --- a/internal/plugin/coder/prune_test.go +++ b/internal/plugin/coder/prune_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/plugin/coder" + "github.com/coder/llm-helper/internal/plugin/coder" ) // The collection is deployment-wide: an Anthropic model sits in the same list diff --git a/internal/plugin/coder/route_test.go b/internal/plugin/coder/route_test.go index c31156d..9082c9b 100644 --- a/internal/plugin/coder/route_test.go +++ b/internal/plugin/coder/route_test.go @@ -9,7 +9,7 @@ import ( "sync" "testing" - "github.com/coder/vllm-helper/internal/plugin/coder" + "github.com/coder/llm-helper/internal/plugin/coder" ) const ( diff --git a/internal/plugin/coder/sync.go b/internal/plugin/coder/sync.go index 58a1d00..5edfc34 100644 --- a/internal/plugin/coder/sync.go +++ b/internal/plugin/coder/sync.go @@ -12,10 +12,10 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/profile" ) // Configuration keys. All three are required: a URL without a token, or @@ -356,7 +356,7 @@ func modelConfig(cfg *config.Config, p *profile.Profile, enabled bool) (ModelCon // failing sync for that would leave the previous model enabled after a // switch. An unknown PROVIDER gets no such grace: it cannot be served, // and inventing a context limit would hide that. - if prov, err := provider.Lookup(p.Provider()); err == nil && !prov.Capabilities().VLLMArgs { + if prov, err := engine.Lookup(p.Provider()); err == nil && !prov.Capabilities().VLLMArgs { raw = strconv.Itoa(profile.DefaultMaxModelLen) } } diff --git a/internal/plugin/coder/sync_internal_test.go b/internal/plugin/coder/sync_internal_test.go index af4f054..733ff00 100644 --- a/internal/plugin/coder/sync_internal_test.go +++ b/internal/plugin/coder/sync_internal_test.go @@ -10,9 +10,9 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/profile" ) func profileWith(t *testing.T, body string) *profile.Profile { diff --git a/internal/plugin/plugin.go b/internal/plugin/plugin.go index 4086579..12ee993 100644 --- a/internal/plugin/plugin.go +++ b/internal/plugin/plugin.go @@ -18,8 +18,8 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/profile" ) // Event is a point in a profile's life that a plugin can react to. diff --git a/internal/plugin/registry.go b/internal/plugin/registry.go index 4cbeba3..d72efc3 100644 --- a/internal/plugin/registry.go +++ b/internal/plugin/registry.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // registered is the built-in set, populated by each plugin's init. Plugins diff --git a/internal/plugin/registry_internal_test.go b/internal/plugin/registry_internal_test.go index d28cef8..d640227 100644 --- a/internal/plugin/registry_internal_test.go +++ b/internal/plugin/registry_internal_test.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) type fake struct { diff --git a/internal/plugin/spark/spark.go b/internal/plugin/spark/spark.go index ea2b63b..55f8c20 100644 --- a/internal/plugin/spark/spark.go +++ b/internal/plugin/spark/spark.go @@ -14,10 +14,10 @@ import ( "github.com/spf13/cobra" "golang.org/x/term" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/plugin" - "github.com/coder/vllm-helper/internal/toolchain" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/plugin" + "github.com/coder/llm-helper/internal/toolchain" ) func init() { plugin.Register(Plugin{}) } diff --git a/internal/profile/generated_test.go b/internal/profile/generated_test.go index aaafed7..4f12adf 100644 --- a/internal/profile/generated_test.go +++ b/internal/profile/generated_test.go @@ -5,8 +5,8 @@ import ( "path/filepath" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/profile" ) func loadFrom(t *testing.T, body string) *profile.Profile { diff --git a/internal/profile/profile.go b/internal/profile/profile.go index 3ba6e60..a547eef 100644 --- a/internal/profile/profile.go +++ b/internal/profile/profile.go @@ -12,8 +12,8 @@ import ( "strings" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" ) type Profile struct { diff --git a/internal/profile/profile_test.go b/internal/profile/profile_test.go index c811c6c..98378c7 100644 --- a/internal/profile/profile_test.go +++ b/internal/profile/profile_test.go @@ -6,9 +6,9 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/profile" ) func newDirs(t *testing.T) config.Dirs { diff --git a/internal/recipe/args.go b/internal/recipe/args.go index 1a8fb49..b695960 100644 --- a/internal/recipe/args.go +++ b/internal/recipe/args.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) // Target is the machine a recipe is resolved for. The hardware definitions diff --git a/internal/recipe/container.go b/internal/recipe/container.go index f5b343b..1c456a0 100644 --- a/internal/recipe/container.go +++ b/internal/recipe/container.go @@ -5,7 +5,7 @@ import ( "sort" "strings" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/engine" ) // ContainerSpec is everything needed to start one node of a recipe. RankSpec @@ -20,7 +20,7 @@ type ContainerSpec struct { // Mounts are host directories, as absolute paths, bind-mounted rather // than baked in so a re-launch does not re-download weights or re-JIT // kernels, which is most of the startup cost. - Mounts []provider.Mount + Mounts []engine.Mount Env map[string]string Args []string // APIKey is kept out of Env so it can be redacted when the command is diff --git a/internal/recipe/launch.go b/internal/recipe/launch.go index 9ce1411..421b80e 100644 --- a/internal/recipe/launch.go +++ b/internal/recipe/launch.go @@ -7,8 +7,8 @@ import ( "strconv" "strings" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hardware" ) // Placeholders a recipe may reference in its env values. They are discovered on @@ -73,7 +73,7 @@ func placeholderName(v string) (string, bool) { // overrides are merged in, so an override is never expanded. func (r TestedRecipe) ServeArgs() []string { e := r.Engine() - v := provider.RoleValues{Model: r.Model, Port: r.Port, Nodes: r.Nodes, Params: r.Params, Models: r.ModelRefs()} + v := engine.RoleValues{Model: r.Model, Port: r.Port, Nodes: r.Nodes, Params: r.Params, Models: r.ModelRefs()} args := e.ExpandArgs(r.Args, v) // Host and port are the launcher's business, not the model's, which is why // the recipe carries "port" as a field instead of inside args. The engine @@ -220,7 +220,7 @@ func (r TestedRecipe) RankSpec(k Rank) (ContainerSpec, error) { if err != nil { return ContainerSpec{}, err } - entry, args, env := e.RenderRole(role, provider.RoleValues{ + entry, args, env := e.RenderRole(role, engine.RoleValues{ Model: r.Model, Port: r.Port, Rank: k.Rank, Nodes: r.Nodes, MasterAddr: k.MasterAddr, MasterPort: k.MasterPort, Args: k.ServeArgs, Params: r.Params, Models: r.ModelRefs(), @@ -296,7 +296,7 @@ func (r TestedRecipe) StagingScript() string { var b strings.Builder b.WriteString(stagedFunc) for _, m := range r.Models { - dir := provider.SnapshotPath(cache, provider.ModelRef{ID: m.ID, Revision: m.Revision}) + dir := engine.SnapshotPath(cache, engine.ModelRef{ID: m.ID, Revision: m.Revision}) fmt.Fprintf(&b, "staged %s || echo %s\n", ShellQuote(dir), ShellQuote(m.ID+"@"+m.Revision)) } return b.String() diff --git a/internal/recipe/local.go b/internal/recipe/local.go index 8d2f101..b085362 100644 --- a/internal/recipe/local.go +++ b/internal/recipe/local.go @@ -29,7 +29,7 @@ var ( // launches. A missing dir is not an error; a bad file is skipped and // reported, and the files after it still load. // -// Call it after provider.UseLocal, since a local recipe may run on a local +// Call it after engine.UseLocal, since a local recipe may run on a local // engine. func UseLocal(dir string) []error { var errs []error diff --git a/internal/recipe/tested.go b/internal/recipe/tested.go index 01447af..784d914 100644 --- a/internal/recipe/tested.go +++ b/internal/recipe/tested.go @@ -13,9 +13,9 @@ import ( "sort" "strings" - "github.com/coder/vllm-helper/catalogue" - "github.com/coder/vllm-helper/internal/hardware" - "github.com/coder/vllm-helper/internal/provider" + "github.com/coder/llm-helper/catalogue" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hardware" ) // SchemaVersion is the recipe format this build reads, in a file under @@ -299,14 +299,14 @@ func (r TestedRecipe) validate() error { add("requires %q names no hardware definition", r.Requires) } } - e, err := provider.LookupEngine(r.Provider) + e, err := engine.LookupEngine(r.Provider) if err != nil { add("%v", err) - } else if !e.Has(provider.RuntimeContainer) { + } else if !e.Has(engine.RuntimeContainer) { add("engine %s has no container runtime, so it cannot launch a recipe", e.ID) } else { for name := range r.Params { - if !slices.ContainsFunc(e.Params, func(p provider.Param) bool { return p.Name == name }) { + if !slices.ContainsFunc(e.Params, func(p engine.Param) bool { return p.Name == name }) { add("params sets %q, which engine %s does not declare", name, e.ID) } } @@ -317,7 +317,7 @@ func (r TestedRecipe) validate() error { for _, m := range r.Models { have[m.Role] = true } - for _, role := range append(e.UsesModelPaths(), provider.ModelRolesIn(r.Args)...) { + for _, role := range append(e.UsesModelPaths(), engine.ModelRolesIn(r.Args)...) { if !have[role] { add("engine %s needs a pinned %s model, and models has none", e.ID, role) } @@ -333,8 +333,8 @@ func (r TestedRecipe) validate() error { add("model %q is not an org/name repo id", m.ID) case !revisionPattern.MatchString(m.Revision): add("model %s: revision %q is not a full commit sha", m.ID, m.Revision) - case !slices.Contains(provider.ModelRoles, m.Role): - add("model %s: role %q must be one of %s", m.ID, m.Role, strings.Join(provider.ModelRoles, ", ")) + case !slices.Contains(engine.ModelRoles, m.Role): + add("model %s: role %q must be one of %s", m.ID, m.Role, strings.Join(engine.ModelRoles, ", ")) case roles[m.Role]: add("model %s: a recipe pins one model per role, and %s is taken", m.ID, m.Role) case m.Staging != "download": @@ -351,16 +351,16 @@ func (r TestedRecipe) validate() error { // Engine is the engine that runs the recipe. Recipes are validated when they // load, so an unknown engine cannot get this far; the zero Engine it would // return renders nothing. -func (r TestedRecipe) Engine() provider.Engine { - e, _ := provider.LookupEngine(r.Provider) +func (r TestedRecipe) Engine() engine.Engine { + e, _ := engine.LookupEngine(r.Provider) return e } // ModelRefs are the recipe's pinned models by role. -func (r TestedRecipe) ModelRefs() map[string]provider.ModelRef { - out := map[string]provider.ModelRef{} +func (r TestedRecipe) ModelRefs() map[string]engine.ModelRef { + out := map[string]engine.ModelRef{} for _, m := range r.Models { - out[m.Role] = provider.ModelRef{ID: m.ID, Revision: m.Revision} + out[m.Role] = engine.ModelRef{ID: m.ID, Revision: m.Revision} } return out } diff --git a/internal/recipe/tested_internal_test.go b/internal/recipe/tested_internal_test.go index 65e8f00..ff5b6b2 100644 --- a/internal/recipe/tested_internal_test.go +++ b/internal/recipe/tested_internal_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/hardware" + "github.com/coder/llm-helper/internal/hardware" ) func TestTestedRecipesAreWellFormed(t *testing.T) { diff --git a/internal/recipe/validate_internal_test.go b/internal/recipe/validate_internal_test.go index 3e3c21c..e9349c3 100644 --- a/internal/recipe/validate_internal_test.go +++ b/internal/recipe/validate_internal_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/catalogue" + "github.com/coder/llm-helper/catalogue" ) func glm(t *testing.T) TestedRecipe { diff --git a/internal/catalog/catalog.go b/internal/resolve/resolve.go similarity index 97% rename from internal/catalog/catalog.go rename to internal/resolve/resolve.go index 1d56d1a..4777f4a 100644 --- a/internal/catalog/catalog.go +++ b/internal/resolve/resolve.go @@ -1,4 +1,4 @@ -// Package catalog turns a HuggingFace repo into something this machine can +// Package resolve turns a HuggingFace repo into something this machine can // serve: what a model would cost here, and the settings to serve it with. // // It sits under both the CLI and the web panel. Both need the same judgements @@ -6,7 +6,7 @@ // -- and those judgements have a safe direction that is easy to lose track of. // Keeping one copy is what stops the two interfaces from disagreeing about // whether a 200 GB model fits in 84 GB. -package catalog +package resolve import ( "context" @@ -18,12 +18,12 @@ import ( "strconv" "strings" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/vllm" ) // repoPattern is the shape of a HuggingFace repo id: one owner, one name. @@ -260,7 +260,7 @@ func cardFlags(flags hf.DetectedFlags, caps vllm.Caps) (args, note string) { // so search and the panel never offer what the server cannot load. The card's // flags are vllm serve's and this server is not taking them, so they stop // reading as detected -- a pull would not have copied them either. -func ForProvider(d Detail, prov provider.Provider) Detail { +func ForProvider(d Detail, prov engine.Provider) Detail { caps := prov.Capabilities() if caps.VLLMArgs { return d @@ -308,7 +308,7 @@ type Plan struct { // Everything PrepareProfile works out (card flags, parser checks, a sized KV // cache, the template patch) is in vLLM's terms, so a profile for any other // provider names the model and leaves the rest to that server's defaults. -func PrepareFor(ctx context.Context, dirs config.Dirs, prov provider.Provider, repo string, choice *Choice, caps vllm.Caps, contextTarget int) Plan { +func PrepareFor(ctx context.Context, dirs config.Dirs, prov engine.Provider, repo string, choice *Choice, caps vllm.Caps, contextTarget int) Plan { if prov.Capabilities().VLLMArgs { return PrepareProfile(ctx, dirs, repo, choice, caps, contextTarget) } diff --git a/internal/catalog/catalog_internal_test.go b/internal/resolve/resolve_internal_test.go similarity index 96% rename from internal/catalog/catalog_internal_test.go rename to internal/resolve/resolve_internal_test.go index 4e059cb..bdd8fb3 100644 --- a/internal/catalog/catalog_internal_test.go +++ b/internal/resolve/resolve_internal_test.go @@ -1,4 +1,4 @@ -package catalog +package resolve import ( "context" @@ -11,12 +11,12 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/vllm" ) // A repo id becomes both a URL sent to the Hub and, through NameFromRepo, part @@ -143,11 +143,11 @@ func TestPrepareForAnotherProviderNamesOnlyTheModel(t *testing.T) { defer srv.Close() defer hf.SetBaseURLForTest(srv.URL)() - mlx, _ := provider.Lookup(provider.MLX) + mlx, _ := engine.Lookup(engine.MLX) p := PrepareFor(context.Background(), config.Dirs{Data: t.TempDir()}, mlx, "mlx-community/Qwen3-4B-4bit", nil, vllm.Caps{}, 0) - if p.Opts.Provider != provider.MLX || p.Opts.Repo != "mlx-community/Qwen3-4B-4bit" { + if p.Opts.Provider != engine.MLX || p.Opts.Repo != "mlx-community/Qwen3-4B-4bit" { t.Errorf("Opts = %+v, want the repo and PROVIDER=mlx", p.Opts) } if p.Opts.ExtraArgs != "" || p.Opts.KVCacheBytes != 0 || p.Opts.MaxModelLen != "" { @@ -160,7 +160,7 @@ func TestPrepareForAnotherProviderNamesOnlyTheModel(t *testing.T) { // vLLM still gets the full treatment, and a profile that names no // provider, as every vLLM profile always has. - vl, _ := provider.Lookup(provider.VLLM) + vl, _ := engine.Lookup(engine.VLLM) v := PrepareFor(context.Background(), config.Dirs{Data: t.TempDir()}, vl, "Qwen/Qwen3-32B", nil, vllm.Caps{}, 0) if v.Opts.Provider != "" { @@ -200,14 +200,14 @@ func TestChooseGGUFQuantForLlamaCPP(t *testing.T) { defer srv.Close() defer hf.SetBaseURLForTest(srv.URL)() ctx := context.Background() - llama, _ := provider.Lookup(provider.LlamaCPP) + llama, _ := engine.Lookup(engine.LlamaCPP) choice, err := ChooseGGUFQuant(ctx, repo, "bf16") if err != nil { t.Fatalf("a split GGUF was refused: %v", err) } p := PrepareFor(ctx, config.Dirs{Data: t.TempDir()}, llama, repo, choice, vllm.Caps{}, 0) - if p.Opts.Repo != repo+":BF16" || p.Opts.Name != "qwen_qwen3-32b-gguf-bf16" || p.Opts.Provider != provider.LlamaCPP { + if p.Opts.Repo != repo+":BF16" || p.Opts.Name != "qwen_qwen3-32b-gguf-bf16" || p.Opts.Provider != engine.LlamaCPP { t.Errorf("Opts = %+v, want MODEL %s:BF16 in profile qwen_qwen3-32b-gguf-bf16", p.Opts, repo) } @@ -238,21 +238,21 @@ func TestForProvider(t *testing.T) { {Name: "Q4_K_M.gguf", Label: "Q4_K_M", SizeGB: 19, GGUF: true, Blocked: "a mixture-of-experts model"}, }, } - get := func(name string) provider.Provider { - p, err := provider.Lookup(name) + get := func(name string) engine.Provider { + p, err := engine.Lookup(name) if err != nil { t.Fatal(err) } return p } - if got := ForProvider(inspected, get(provider.VLLM)); got.ArchBlocked == "" || got.GGUFReady || got.Best != nil { + if got := ForProvider(inspected, get(engine.VLLM)); got.ArchBlocked == "" || got.GGUFReady || got.Best != nil { t.Errorf("vllm: %+v, want Inspect's view unchanged", got) } inspected.DetectedFlags = "--tokenizer Qwen/Qwen3-32B" inspected.DroppedFlags = []string{"--a-flag-this-vllm-lacks"} - llama := ForProvider(inspected, get(provider.LlamaCPP)) + llama := ForProvider(inspected, get(engine.LlamaCPP)) if !llama.GGUFReady || llama.ArchBlocked != "" { t.Errorf("llamacpp: GGUFReady %v, ArchBlocked %q, want the plugin's limits lifted", llama.GGUFReady, llama.ArchBlocked) } @@ -271,7 +271,7 @@ func TestForProvider(t *testing.T) { t.Error("ForProvider changed the Detail it was given") } - mlx := ForProvider(inspected, get(provider.MLX)) + mlx := ForProvider(inspected, get(engine.MLX)) if mlx.ArchBlocked == "" || mlx.Best != nil { t.Errorf("mlx: ArchBlocked %q, Best %+v, want the GGUF repo refused", mlx.ArchBlocked, mlx.Best) } @@ -287,10 +287,10 @@ func TestForProvider(t *testing.T) { {Name: ".", Label: "default", SizeGB: 65}, {Name: "m-Q8_0.gguf", Label: "Q8_0", SizeGB: 34, GGUF: true}, }} - if got := ForProvider(mixed, get(provider.LlamaCPP)); got.Best == nil || got.Best.Label != "Q8_0" || got.All[0].Servable() { + if got := ForProvider(mixed, get(engine.LlamaCPP)); got.Best == nil || got.Best.Label != "Q8_0" || got.All[0].Servable() { t.Errorf("llamacpp mixed repo: Best %+v, safetensors blocked %q, want Q8_0 and the safetensors ruled out", got.Best, got.All[0].Blocked) } - if got := ForProvider(mixed, get(provider.MLX)); got.Best == nil || got.Best.Label != "default" || got.All[1].Servable() { + if got := ForProvider(mixed, get(engine.MLX)); got.Best == nil || got.Best.Label != "default" || got.All[1].Servable() { t.Errorf("mlx mixed repo: Best %+v, want the safetensors and the GGUF ruled out", got.Best) } } diff --git a/internal/catalog/tiktoken.go b/internal/resolve/tiktoken.go similarity index 98% rename from internal/catalog/tiktoken.go rename to internal/resolve/tiktoken.go index f6513fa..0f5f413 100644 --- a/internal/catalog/tiktoken.go +++ b/internal/resolve/tiktoken.go @@ -1,4 +1,4 @@ -package catalog +package resolve import ( "fmt" @@ -9,8 +9,8 @@ import ( "strings" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/vllm" ) // harmonyEncodings are the vocab files the harmony tokenizer reads, by the diff --git a/internal/catalog/tiktoken_internal_test.go b/internal/resolve/tiktoken_internal_test.go similarity index 98% rename from internal/catalog/tiktoken_internal_test.go rename to internal/resolve/tiktoken_internal_test.go index 5ea5a03..1d68b90 100644 --- a/internal/catalog/tiktoken_internal_test.go +++ b/internal/resolve/tiktoken_internal_test.go @@ -1,4 +1,4 @@ -package catalog +package resolve import ( "net/http" @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/vllm" ) // setup creates the encodings directory and points vLLM at it, but nothing diff --git a/internal/toolchain/toolchain_darwin.go b/internal/toolchain/toolchain_darwin.go index b9aca79..a0fd6ce 100644 --- a/internal/toolchain/toolchain_darwin.go +++ b/internal/toolchain/toolchain_darwin.go @@ -1,6 +1,6 @@ package toolchain -import "github.com/coder/vllm-helper/internal/detect" +import "github.com/coder/llm-helper/internal/detect" // Gather checks what a macOS source build of vLLM's CPU backend needs: it // has no Apple Silicon wheels, so it is compiled locally against Apple Clang diff --git a/internal/vllm/validate.go b/internal/vllm/validate.go index 8798d2f..4aae029 100644 --- a/internal/vllm/validate.go +++ b/internal/vllm/validate.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/coder/vllm-helper/internal/config" + "github.com/coder/llm-helper/internal/config" ) // parserFlags are the flags whose values must name something in the diff --git a/internal/web/activate.go b/internal/web/activate.go index 10763fd..3f3bc45 100644 --- a/internal/web/activate.go +++ b/internal/web/activate.go @@ -10,8 +10,8 @@ import ( "path/filepath" "strings" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/profile" ) // activate switches this machine to a saved profile. diff --git a/internal/web/api.go b/internal/web/api.go index bcca212..80db119 100644 --- a/internal/web/api.go +++ b/internal/web/api.go @@ -11,9 +11,9 @@ import ( "strconv" "time" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/profile" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/profile" ) // run executes a command and reports only whether it succeeded. Used for diff --git a/internal/web/docs.go b/internal/web/docs.go index 033361e..f4110f4 100644 --- a/internal/web/docs.go +++ b/internal/web/docs.go @@ -27,7 +27,7 @@ import ( "github.com/yuin/goldmark/text" "github.com/yuin/goldmark/util" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) //go:embed docs.tmpl diff --git a/internal/web/docs_internal_test.go b/internal/web/docs_internal_test.go index ccc99aa..1b2067a 100644 --- a/internal/web/docs_internal_test.go +++ b/internal/web/docs_internal_test.go @@ -7,7 +7,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) func getDocs(t *testing.T, s *Server, path string) *httptest.ResponseRecorder { diff --git a/internal/web/docssite.go b/internal/web/docssite.go index 64428b3..fc81956 100644 --- a/internal/web/docssite.go +++ b/internal/web/docssite.go @@ -14,7 +14,7 @@ import ( "net/http" "strings" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) // docsSiteSummary is the one-line description llms.txt leads with. It is the diff --git a/internal/web/docssite_internal_test.go b/internal/web/docssite_internal_test.go index cdcadfb..c68f463 100644 --- a/internal/web/docssite_internal_test.go +++ b/internal/web/docssite_internal_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/coder/vllm-helper/docs" + "github.com/coder/llm-helper/docs" ) const testDocsBase = "https://docs.example.test" diff --git a/internal/web/models.go b/internal/web/models.go index 9e39c2c..ae68251 100644 --- a/internal/web/models.go +++ b/internal/web/models.go @@ -9,13 +9,13 @@ import ( "strings" "time" - "github.com/coder/vllm-helper/internal/catalog" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/detect" - "github.com/coder/vllm-helper/internal/hf" - "github.com/coder/vllm-helper/internal/profile" - "github.com/coder/vllm-helper/internal/provider" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/detect" + "github.com/coder/llm-helper/internal/engine" + "github.com/coder/llm-helper/internal/hf" + "github.com/coder/llm-helper/internal/profile" + "github.com/coder/llm-helper/internal/resolve" + "github.com/coder/llm-helper/internal/vllm" ) // hubTimeout bounds a call that leaves this machine. The Hub client already @@ -38,7 +38,7 @@ func repoParam(r *http.Request) (string, error) { if repo == "" { return "", errors.New("no model given") } - if !catalog.ValidRepo(repo) { + if !resolve.ValidRepo(repo) { return "", fmt.Errorf("%q is not a HuggingFace repo id -- expected something like org/model-name", repo) } return repo, nil @@ -49,7 +49,7 @@ func (s *Server) budget() detect.WeightsBudget { return detect.ModelBudget(s.cfg type searchResponse struct { Query string `json:"query"` - Results []catalog.Result `json:"results"` + Results []resolve.Result `json:"results"` } // handleSearch queries the Hub. Read-only and outbound: it tells the caller @@ -69,9 +69,9 @@ func (s *Server) handleSearch(w http.ResponseWriter, r *http.Request) { }) return } - out := make([]catalog.Result, 0, len(models)) + out := make([]resolve.Result, 0, len(models)) for _, m := range models { - out = append(out, catalog.ToResult(m)) + out = append(out, resolve.ToResult(m)) } writeJSON(w, http.StatusOK, searchResponse{Query: query, Results: out}) } @@ -80,7 +80,7 @@ func (s *Server) handleSearch(w http.ResponseWriter, r *http.Request) { // this model already exists, so the UI can offer "switch to it" rather than // a pull that would fail as a duplicate. type inspectResponse struct { - catalog.Detail + resolve.Detail ExistingProfile string `json:"existing_profile,omitempty"` } @@ -108,14 +108,14 @@ func (s *Server) handleInspect(w http.ResponseWriter, r *http.Request) { } ctx, cancel := context.WithTimeout(r.Context(), hubTimeout) defer cancel() - prov, err := provider.Lookup(s.cfg.Provider()) + prov, err := engine.Lookup(s.cfg.Provider()) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } type result struct { - d catalog.Detail + d resolve.Detail err error } ch := make(chan result, 1) @@ -131,7 +131,7 @@ func (s *Server) handleInspect(w http.ResponseWriter, r *http.Request) { if prov.Capabilities().VLLMArgs { caps = s.caps() } - ch <- result{d: catalog.ForProvider(catalog.Inspect(ctx, m, s.budget(), caps, s.cfg.KVContextTarget()), prov)} + ch <- result{d: resolve.ForProvider(resolve.Inspect(ctx, m, s.budget(), caps, s.cfg.KVContextTarget()), prov)} }() select { @@ -188,19 +188,19 @@ func (s *Server) handlePull(w http.ResponseWriter, r *http.Request) { // An explicit quant is resolved against what the repo actually holds, // so a stale page cannot ask for one that is gone -- or one that vLLM // has no way to load. - prov, err := provider.Lookup(s.cfg.Provider()) + prov, err := engine.Lookup(s.cfg.Provider()) if err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) return } - var choice *catalog.Choice + var choice *resolve.Choice if want := strings.TrimSpace(r.URL.Query().Get("quant")); want != "" && !prov.Capabilities().VLLMArgs { if !prov.Capabilities().GGUFQuant { writeJSON(w, http.StatusBadRequest, map[string]string{ "error": "a quant picks one GGUF file out of a repo, but new profiles here are served by " + prov.Name() + ", which does not load GGUF"}) return } - if choice, err = catalog.ChooseGGUFQuant(r.Context(), repo, want); err != nil { + if choice, err = resolve.ChooseGGUFQuant(r.Context(), repo, want); err != nil { writeJSON(w, http.StatusBadRequest, map[string]string{"error": err.Error()}) return } @@ -211,8 +211,8 @@ func (s *Server) handlePull(w http.ResponseWriter, r *http.Request) { "error": "could not re-read " + repo + " from HuggingFace: " + err.Error()}) return } - d := catalog.Inspect(r.Context(), m, s.budget(), s.caps(), s.cfg.KVContextTarget()) - v, ok := catalog.FindVariant(d.All, want) + d := resolve.Inspect(r.Context(), m, s.budget(), s.caps(), s.cfg.KVContextTarget()) + v, ok := resolve.FindVariant(d.All, want) switch { case !ok: writeJSON(w, http.StatusBadRequest, map[string]string{ @@ -231,7 +231,7 @@ func (s *Server) handlePull(w http.ResponseWriter, r *http.Request) { "error": "this vLLM cannot load GGUF -- install vllm-gguf-plugin first"}) return } - choice = &catalog.Choice{Variant: v, BaseModel: d.BaseModel} + choice = &resolve.Choice{Variant: v, BaseModel: d.BaseModel} } name := profile.NameFromRepo(repo) @@ -270,7 +270,7 @@ func (s *Server) handlePull(w http.ResponseWriter, r *http.Request) { if prov.Capabilities().VLLMArgs { caps = s.caps() } - plan := catalog.PrepareFor(r.Context(), s.cfg.Dirs, prov, repo, choice, caps, s.cfg.KVContextTarget()) + plan := resolve.PrepareFor(r.Context(), s.cfg.Dirs, prov, repo, choice, caps, s.cfg.KVContextTarget()) out.Notes = append(out.Notes, plan.Notes...) if _, err := profile.Create(s.cfg.Dirs, plan.Opts); err != nil { writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) diff --git a/internal/web/server.go b/internal/web/server.go index 51c0874..951e5db 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -25,10 +25,10 @@ import ( "sync" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/service" - "github.com/coder/vllm-helper/internal/vllm" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/service" + "github.com/coder/llm-helper/internal/vllm" ) // Server holds everything the handlers need. diff --git a/internal/web/server_internal_test.go b/internal/web/server_internal_test.go index 420d92c..fa3dd39 100644 --- a/internal/web/server_internal_test.go +++ b/internal/web/server_internal_test.go @@ -14,9 +14,9 @@ import ( "testing" "time" - "github.com/coder/vllm-helper/internal/config" - "github.com/coder/vllm-helper/internal/control" - "github.com/coder/vllm-helper/internal/service" + "github.com/coder/llm-helper/internal/config" + "github.com/coder/llm-helper/internal/control" + "github.com/coder/llm-helper/internal/service" ) // newTestServer builds a server over a throwaway config tree that contains diff --git a/main.go b/main.go index f984cb6..3f6017c 100644 --- a/main.go +++ b/main.go @@ -7,7 +7,7 @@ package main import ( "os" - "github.com/coder/vllm-helper/internal/cli" + "github.com/coder/llm-helper/internal/cli" ) func main() { diff --git a/scripts/gendocs/main.go b/scripts/gendocs/main.go index 13eed89..de2ccc6 100644 --- a/scripts/gendocs/main.go +++ b/scripts/gendocs/main.go @@ -15,8 +15,8 @@ import ( "regexp" "sort" - "github.com/coder/vllm-helper/docs" - "github.com/coder/vllm-helper/internal/cli" + "github.com/coder/llm-helper/docs" + "github.com/coder/llm-helper/internal/cli" ) func main() { diff --git a/tools/recipediff/go.mod b/tools/recipediff/go.mod index f7bb329..ed68cfd 100644 --- a/tools/recipediff/go.mod +++ b/tools/recipediff/go.mod @@ -1,4 +1,4 @@ -module github.com/coder/vllm-helper/tools/recipediff +module github.com/coder/llm-helper/tools/recipediff go 1.26.5