Skip to content

feat: add model files endpoint#2437

Merged
fl0rianr merged 4 commits into
mainfrom
fl0rianr/adding_file_endpoint_for_clients
Jul 2, 2026
Merged

feat: add model files endpoint#2437
fl0rianr merged 4 commits into
mainfrom
fl0rianr/adding_file_endpoint_for_clients

Conversation

@fl0rianr

Copy link
Copy Markdown
Collaborator

Summary

Adds a backend-owned per-model file inventory endpoint for the GUI Files tab:

  • GET /api/v1/models/{id}/files
  • GET /v1/models/{id}/files

This is intentionally separate from storage/system metrics. Storage endpoints
answer drive/system usage questions; this endpoint answers which resolved local
files belong to one selected model.

Response shape

{
  "model_id": "Qwen3-4B",
  "files": [
    {
      "name": "model.gguf",
      "path": "/abs/path/model.gguf",
      "role": "main",
      "size_bytes": 123456789,
      "exists": true
    }
  ]
}

Implementation notes

  • Adds ModelManager::list_model_files() using ModelInfo::resolved_paths as the first-slice source of truth.
  • Uses std::filesystem::exists/existing safe filesystem helpers and the existing resolved-path size helper.
  • Sums directories recursively, matching existing model-size behavior.
  • Registers /models/{id}/files before the generic /models/(.+) route so foo/files is not interpreted as a model ID.
  • Returns the public/wire model ID via the same alias resolution path as GET /v1/models/{id}.

Validation

PR 2 backend smoke test: /models/{id}/files works for Gemma-4-E2B-it-GGUF

Validated both public route variants:

GET http://localhost:13305/v1/models/Gemma-4-E2B-it-GGUF/files
GET http://localhost:13305/api/v1/models/Gemma-4-E2B-it-GGUF/files

Both endpoints return the same expected response shape:

{
  "model_id": "Gemma-4-E2B-it-GGUF",
  "files": [
    {
      "name": "gemma-4-E2B-it-Q4_K_M.gguf",
      "path": "/home/vscode/.cache/huggingface/hub/models--unsloth--gemma-4-E2B-it-GGUF/snapshots/ecc8b33b2c50598815e4b0f7cea6088e3ae7adb8/gemma-4-E2B-it-Q4_K_M.gguf",
      "role": "main",
      "size_bytes": 3106736256,
      "exists": true
    },
    {
      "name": "mmproj-F16.gguf",
      "path": "/home/vscode/.cache/huggingface/hub/models--unsloth--gemma-4-E2B-it-GGUF/snapshots/ecc8b33b2c50598815e4b0f7cea6088e3ae7adb8/mmproj-F16.gguf",
      "role": "mmproj",
      "size_bytes": 985654080,
      "exists": true
    }
  ]
}

Result:

main file is detected with role main
mmproj file is detected with role mmproj
both paths resolve to existing files
total listed size: 4092390336 bytes, roughly 3.81 GiB
/v1/... and /api/v1/... behave consistently
</details> ```

@github-actions github-actions Bot added area::api HTTP REST API surface and route handlers enhancement New feature or request labels Jun 26, 2026
@fl0rianr fl0rianr requested a review from kpoineal June 26, 2026 23:27

@bong-water-water-bong bong-water-water-bong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two issues that should be addressed:

1. HIGH — Missing /api/v0 and /v0 route variants: Every other model endpoint follows the quad-prefix convention (/api/v0, /api/v1, /v0, /v1). This endpoint only registers under /api/v1 and /v1. Requests to /api/v0/models/foo/files will fall through to the generic model-by-id route and return "Model not found."

2. HIGH — Absolute filesystem paths exposed in API response: The existing model_info_to_json deliberately omits resolved_paths. This new endpoint exposes full paths like /home/user/.cache/huggingface/hub/models--..., revealing home directories, usernames, and cache layout. If absolute paths are truly needed by the GUI, at minimum document this in the API docs as intentional info disclosure.

Minor: TOCTOU gap between model_exists() check and list_model_files() call (pre-existing pattern, but worth wrapping in try-catch for 404). Missing #include <vector> in model_manager.h.

@fl0rianr fl0rianr force-pushed the fl0rianr/adding_file_endpoint_for_clients branch from d3884d6 to 4dc5e8c Compare June 28, 2026 21:44
Comment thread docs/api/lemonade.md Outdated

@jeremyfowers jeremyfowers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM!

@fl0rianr fl0rianr enabled auto-merge July 2, 2026 15:55
@fl0rianr fl0rianr added this pull request to the merge queue Jul 2, 2026
Merged via the queue into main with commit 15202d4 Jul 2, 2026
85 checks passed
@fl0rianr fl0rianr deleted the fl0rianr/adding_file_endpoint_for_clients branch July 2, 2026 19:50
fl0rianr pushed a commit that referenced this pull request Jul 3, 2026
* feat(ui): implement Files tab with model file listing (#2428)

Wire the model-detail Files tab to GET /api/v1/models/{id}/files (PR #2437).
Renders backing files (name, role badge, human-readable size, download
status) in an accessible table with column headers and a caption, plus
loading/empty/error states. Adds getModelFiles() + ModelFilesResponse to
the API client, dark-theme CSS, and Playwright a11y tests A180-A184.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(ui): align Size column header and normalize row heights (#2428)

Addresses fl0rianr's review feedback on PR #2538:
- Size column now left-aligned so header sits directly above values
- Table rows have uniform 40px height

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area::api HTTP REST API surface and route handlers enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants