Skip to content

feat(assets): add namespaced model_type tags and align tag semantics#14511

Open
synap5e wants to merge 2 commits into
masterfrom
synap5e/assets-namespaced-tags
Open

feat(assets): add namespaced model_type tags and align tag semantics#14511
synap5e wants to merge 2 commits into
masterfrom
synap5e/assets-namespaced-tags

Conversation

@synap5e

@synap5e synap5e commented Jun 17, 2026

Copy link
Copy Markdown

This PR reworks asset tags so they are no longer overloaded as model classification, upload routing, and filesystem subdirectory instructions at the same time.

It introduces namespaced model_type:<folder_name> tags for filesystem-backed model classification, preserves caller-provided tags as relaxed labels, and changes multipart asset upload routing so extra tags no longer create path components.

Note: This PR does not migrate assets tagged by the previous version of the asset system. Existing flat tags such as checkpoints remain as labels. A migration/backfill is possible as a follow-up if we want one.

What this does

  1. Backend model classification becomes explicit and namespaced. Files under registered model folders are tagged as models + model_type:<folder_name> instead of flat labels such as models + checkpoints or models + loras.
  2. Caller-provided tags stay relaxed labels. Callers may store arbitrary tags, including system-looking strings. Tags preserve case and are no longer lowercased before persistence.
  3. Multipart upload routing is narrow. New byte uploads use exactly one destination role (input, output, or models). Model uploads additionally require exactly one model_type:<folder_name> tag. Extra tags are labels only and do not create subdirectories.
  4. Filesystem-backed response location is explicit. Asset responses include file_path and display_name storage locator fields for filesystem-backed assets.
  5. Existing image upload placement stays compatible. /upload/image continues to use its existing type and subfolder form fields for storage and response compatibility. Only exact known image subfolder values (pasted, painter, webcam, threed, 3d) are mirrored as asset tags.

The backend-generated model classification shape is:

  • models: the asset has a real filesystem path under at least one allowed registered ComfyUI model folder.
  • model_type:<folder_name>: the asset path is under the registered model folder named <folder_name>, preserving the registered folder name casing.

Examples: models + model_type:checkpoints, models + model_type:loras, models + model_type:LLM.

Backend-generated classification is added only from trusted filesystem facts, such as a scanner-discovered path, an already-written /upload/image file, or the final destination of a multipart byte upload. Tag filters still operate on the single persisted tag set, so once a tag exists it is filterable regardless of whether it originated from a caller or from backend classification.

Motivation

The old asset tag behavior was not just underspecified; it produced wrong or misleading results for real ComfyUI model configurations.

  1. Extra model paths were flattened into ambiguous path labels. ComfyUI model folders are defined by folder_paths.folder_names_and_paths, and a single model type can have registered paths outside the stock <models>/<folder> layout. The old path-derived tags treated the registered folder name and parent path fragments as ordinary flat tags such as checkpoints, loras, or arbitrary subfolder names. That meant the API did not have a stable way to say “this asset belongs to the registered checkpoints model type” versus “this asset merely has a caller/path label named checkpoints.” Namespaced tags make the model type explicit: models + model_type:<folder_name>.
  2. Registered non-model folders could be treated like model upload destinations. folder_names_and_paths also contains entries that are not safe model upload targets. In particular, custom_nodes and configs should not become places where asset upload requests can write user bytes just because they are registered folder names. This PR excludes those names from model classification/upload destination resolution.
  3. Overlapping roots made one flat classification insufficient. A path can belong to more than one relevant backend fact, for example a registered model folder under the output root. The old “choose one root and then emit path fragments” shape could lose part of the truth or encode it as misleading directory labels. This PR lets backend classification keep each trusted fact as tags, e.g. output + models + model_type:* when both root and model-folder membership are true.
  4. Upload routing and tag labels were conflated. Multipart upload tags previously doubled as routing, model category, and subdirectory path components. That made models + checkpoints + foo + bar both a classifier and a filesystem placement instruction. This PR keeps routing narrow: new byte uploads use exactly one destination role (input, models, or output), model uploads use exactly one model_type:<folder_name>, and all other tags remain labels.

This PR also changes location semantics for new multipart /api/assets byte uploads. Previously, ordered tags described the destination root, model category, and nested filesystem subdirectories: for example, input + foo wrote under input/foo, and models + checkpoints + foo + bar wrote under a checkpoints folder plus foo/bar. In this PR, multipart upload location is selected only by the destination role and optional model_type:<folder_name> for model uploads. Extra tags no longer create path components, and this PR does not add a /api/assets subfolder field.

That location change is specific to multipart /api/assets byte uploads. /upload/image keeps its existing placement semantics: it still uses type and subfolder form fields to choose where the image is written. Known /upload/image subfolders such as pasted, painter, webcam, threed, and 3d are mirrored as asset tags when the already-written file is registered.

Examples

  • File under a registered checkpoint folder:

    • tags: models, model_type:checkpoints
    • file_path: storage locator such as models/checkpoints/foo.safetensors or output/checkpoints/foo.safetensors
    • matches include_tags=models,model_type:checkpoints
    • is filesystem-loadable by checkpoint loaders if the file is valid and the model-list cache sees it
  • File under a case-preserving registered model folder named LLM:

    • tags: models, model_type:LLM
    • model_type:LLM and model_type:llm are distinct tags
  • Multipart byte upload with tags models + model_type:checkpoints:

    • writes to the first allowed registered checkpoints folder using the digest filename
    • persists uploaded, models, and model_type:checkpoints
  • Multipart byte upload with tags input + model_type:checkpoints:

    • writes to input using the digest filename
    • stores model_type:checkpoints as a label
    • does not become checkpoint-loadable because the file is not written under a registered checkpoints folder
  • Multipart byte upload with tags models + model_type:checkpoints + foo + bar:

    • writes at the selected checkpoints folder root using the digest filename
    • stores foo and bar as labels
    • does not create foo/bar subdirectories
  • /api/assets/from-hash with tags models + model_type:checkpoints:

    • creates a reference-only asset label set when a new reference is created
    • does not move bytes or synthesize filesystem classification
  • /upload/image with type=input&subfolder=pasted:

    • still writes to input/pasted/<filename> using the existing image-upload fields
    • asset registration adds path-derived input, uploaded, and the known pasted tag
    • multipart asset upload destination-tag rules do not apply to this endpoint
  • /upload/image with type=input&subfolder=custom/session:

    • still writes to input/custom/session/<filename>
    • asset registration adds input + uploaded
    • does not add custom or session tags

Changes

  • Preserve tag casing in normalization instead of lowercasing every tag.
  • Add a database migration that removes the lowercase CHECK constraint from tags, with a downgrade path that lowercases/merges mixed-case tags before restoring the old constraint.
  • Add trusted path classification for backend-generated tags:
    • input
    • output
    • temp
    • models
    • model_type:<folder_name>
  • Recover exact known image-input layout tags for direct files under input/pasted, input/painter, input/webcam, input/threed, and input/3d.
  • Stop deriving model classification from caller labels alone.
  • Stop generating flat model/path labels such as checkpoints, loras, or arbitrary parent directory names from model paths.
  • Resolve multipart byte-upload destinations from exactly one destination role: input, models, or output.
  • Require exactly one model_type:<folder_name> tag for new multipart model uploads.
  • Treat extra multipart upload tags as labels, not filesystem subdirectories.
  • Keep /api/assets free of a new subfolder field; nested multipart placement is not part of this PR.
  • Reject configs and custom_nodes as model upload destinations.
  • Add uploaded to successful byte upload registrations, including already-written /upload/image registrations.
  • Mirror known /upload/image subfolders (pasted, painter, webcam, threed, 3d) as tags when registering those files as assets.
  • Keep known-hash and duplicate-byte multipart paths reference-only once the content hash is already known: they do not require destination tags, move bytes, synthesize uploaded, or copy path-derived classification.
  • Expose and document filesystem-backed file_path / display_name response locator fields.
  • Advertise supports_model_type_tags: true in server feature flags for frontend capability detection.
  • Make tag prefix querying stop lowercasing the requested prefix.
  • Add focused tests for case-preserving tags, namespaced model filters, upload destination resolution, rejected model destinations, reference-only fast paths, path classification, /api/assets schema behavior, and /upload/image subfolder compatibility.

Behavior / compatibility notes

  • Tags are still a single public label set. A persisted models tag matches include_tags=models regardless of whether it was supplied by a caller or generated from a trusted path.
  • This PR keeps generic tag mutation permissive, so arbitrary caller labels still do not by themselves prove filesystem placement. The stacked retagging fix in fix(assets): move model asset on model_type: edit to stay loader-coherent #14561 builds on this contract: when the frontend edit-type flow applies a registered model_type:<folder_name> to a filesystem-backed model asset, that follow-up moves/re-registers the file so the label and loader-visible location stay coherent.
  • New scanner/upload classifications no longer add arbitrary path subfolder labels. For example, output/foo/bar.png is classified as output, not output + foo. Direct files under known image-input directories are the narrow exception, e.g. input/pasted/foo.png gets input + pasted.
  • Multipart asset upload no longer uses extra tags as nested subdirectories, and this PR does not add a /api/assets subfolder placement field.
  • /upload/image placement is not changed: it continues to use its type and subfolder form fields rather than asset tags. Known image-upload subfolder names are also stored as tags for filtering.
  • Existing flat tags such as checkpoints are not migrated into model_type:checkpoints; clients that need transition compatibility should handle both shapes.
  • Overlapping registered roots can produce both root tags and model tags, e.g. output + models + model_type:*; persisted tags are not dynamically recomputed at response time.

Verification

  • uv run ruff check app/assets/api/schemas_in.py app/assets/api/upload.py app/assets/api/routes.py app/assets/services/ingest.py app/assets/services/path_utils.py server.py tests-unit/assets_test/test_uploads.py tests-unit/assets_test/services/test_path_utils.py
    • passed
  • uv run --with-requirements requirements.txt --with-requirements tests-unit/requirements.txt pytest tests-unit/assets_test/services/test_path_utils.py tests-unit/assets_test/test_uploads.py -q
    • 71 passed
  • uv run --with pyyaml python - <<'PY' ...
    • verified OpenAPI includes file_path / display_name and update responses reference Asset

@synap5e synap5e changed the title Add namespaced model type asset tags feat(assets): Add namespaced model_type: tags Jun 19, 2026
@synap5e synap5e changed the title feat(assets): Add namespaced model_type: tags feat(assets): Add namespaced model_type: tags and align tags semantics Jun 20, 2026
@synap5e synap5e changed the title feat(assets): Add namespaced model_type: tags and align tags semantics feat(assets): add namespaced model_type tags and align tag semantics Jun 20, 2026
@synap5e synap5e force-pushed the synap5e/assets-namespaced-tags branch from 4a757fc to 4340337 Compare June 20, 2026 01:28
@synap5e synap5e marked this pull request as ready for review June 20, 2026 01:31

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4340337c69

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/assets/database/queries/tags.py Outdated
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR makes asset tags case-sensitive throughout the stack. A migration removes the lowercase-only tags constraint and restores it on downgrade with data normalization. Upload schemas, routing, and ingest handling add explicit subfolder support and stop lowercasing tag values. Path utilities now derive backend tags and response paths from filesystem containment, and destination routing uses explicit role and model-type tags. Feature flags and OpenAPI documents add supports_model_type_tags and adjust asset field documentation. Tests are updated for the new tag naming, path handling, and case-sensitive filtering behavior.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: namespaced model_type tags and updated tag semantics.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description accurately matches the changeset and its asset-tagging, upload-routing, and API updates.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
tests-unit/assets_test/test_prune_orphaned_assets.py (1)

32-40: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Scope is no longer applied in find_asset, making these assertions cross-test ambiguous.

Line 32 drops scope-based narrowing, but callers still pass scope and use generic names (input.bin / output.bin). That can match unrelated assets and produce false pass/fail outcomes.

Suggested hardening
 def find_asset(http: requests.Session, api_base: str):
     """Query API for assets matching scope and optional name."""
-    def _find(scope: str, name: str | None = None) -> list[dict]:
+    def _find(_scope: str, name: str | None = None) -> list[dict]:
         params = {"limit": "500"}
         if name:
             params["name_contains"] = name
@@
 def test_prune_across_multiple_roots(
@@
     scope = f"multi-{uuid.uuid4().hex[:6]}"
-    input_fp = create_seed_file("input", scope, "input.bin")
-    create_seed_file("output", scope, "output.bin")
+    input_name = f"{scope}-input.bin"
+    output_name = f"{scope}-output.bin"
+    input_fp = create_seed_file("input", scope, input_name)
+    create_seed_file("output", scope, output_name)

     trigger_sync_seed_assets(http, api_base)
-    assert find_asset(scope, input_fp.name)
-    assert find_asset(scope, "output.bin")
+    assert find_asset(scope, input_name)
+    assert find_asset(scope, output_name)
@@
-    assert not find_asset(scope, input_fp.name)
-    assert find_asset(scope, "output.bin")
+    assert not find_asset(scope, input_name)
+    assert find_asset(scope, output_name)

Also applies to: 115-122

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests-unit/assets_test/test_prune_orphaned_assets.py` around lines 32 - 40,
The find_asset function no longer applies scope-based filtering when retrieving
assets, which causes test assertions to be ambiguous when multiple tests use
generic asset names like input.bin or output.bin. Modify the find_asset function
to accept and apply scope as a query parameter in the API request (similar to
how name_contains is currently handled), ensuring that the returned assets are
filtered by both scope and name to prevent false matches across different test
scopes.
🧹 Nitpick comments (1)
alembic_db/versions/0005_allow_case_sensitive_tags.py (1)

23-33: ⚡ Quick win

SQLite foreign key handling may leave FKs disabled on error.

If any statement between PRAGMA foreign_keys=OFF (line 23) and PRAGMA foreign_keys=ON (line 33) raises an exception, foreign keys remain disabled for the connection. Consider wrapping in a try/finally or using a transaction to ensure cleanup.

🛡️ Suggested safer pattern
     if bind.dialect.name == "sqlite":
-        op.execute("PRAGMA foreign_keys=OFF")
-        op.execute(
-            "CREATE TABLE tags_new ("
-            "name VARCHAR(512) NOT NULL, "
-            "CONSTRAINT pk_tags PRIMARY KEY (name)"
-            ")"
-        )
-        op.execute("INSERT INTO tags_new(name) SELECT name FROM tags")
-        op.execute("DROP TABLE tags")
-        op.execute("ALTER TABLE tags_new RENAME TO tags")
-        op.execute("PRAGMA foreign_keys=ON")
-        return
+        try:
+            op.execute("PRAGMA foreign_keys=OFF")
+            op.execute(
+                "CREATE TABLE tags_new ("
+                "name VARCHAR(512) NOT NULL, "
+                "CONSTRAINT pk_tags PRIMARY KEY (name)"
+                ")"
+            )
+            op.execute("INSERT INTO tags_new(name) SELECT name FROM tags")
+            op.execute("DROP TABLE tags")
+            op.execute("ALTER TABLE tags_new RENAME TO tags")
+        finally:
+            op.execute("PRAGMA foreign_keys=ON")
+        return
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@alembic_db/versions/0005_allow_case_sensitive_tags.py` around lines 23 - 33,
The migration code disables foreign keys at the start with `PRAGMA
foreign_keys=OFF` but if any of the subsequent `op.execute()` calls (such as
CREATE TABLE tags_new, INSERT INTO tags_new, DROP TABLE tags, or ALTER TABLE
tags_new RENAME) raise an exception, the final `PRAGMA foreign_keys=ON`
statement will not execute, leaving foreign keys permanently disabled for the
connection. Wrap the middle statements (the table creation, data insertion, and
table swap operations) in a try/finally block to ensure that `PRAGMA
foreign_keys=ON` is always executed regardless of whether an error occurs during
the migration steps.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@alembic_db/versions/0005_allow_case_sensitive_tags.py`:
- Around line 42-51: The downgrade path uses SQLite-specific SQL syntax that
will fail on PostgreSQL and MySQL databases. The operations in the downgrade
function including INSERT OR IGNORE and rowid references are not
database-agnostic. Wrap these SQLite-specific op.execute calls (the INSERT OR
IGNORE statement and the DELETE with rowid usage) in a conditional check for
SQLite dialect similar to the dialect check pattern used elsewhere in the
migration file, or rewrite the operations using portable SQL syntax that handles
both INSERT OR IGNORE (for SQLite), INSERT ... ON CONFLICT DO NOTHING (for
PostgreSQL), and INSERT IGNORE (for MySQL), and replace rowid references with
database-appropriate alternatives like ctid for PostgreSQL or proper primary key
handling.

---

Outside diff comments:
In `@tests-unit/assets_test/test_prune_orphaned_assets.py`:
- Around line 32-40: The find_asset function no longer applies scope-based
filtering when retrieving assets, which causes test assertions to be ambiguous
when multiple tests use generic asset names like input.bin or output.bin. Modify
the find_asset function to accept and apply scope as a query parameter in the
API request (similar to how name_contains is currently handled), ensuring that
the returned assets are filtered by both scope and name to prevent false matches
across different test scopes.

---

Nitpick comments:
In `@alembic_db/versions/0005_allow_case_sensitive_tags.py`:
- Around line 23-33: The migration code disables foreign keys at the start with
`PRAGMA foreign_keys=OFF` but if any of the subsequent `op.execute()` calls
(such as CREATE TABLE tags_new, INSERT INTO tags_new, DROP TABLE tags, or ALTER
TABLE tags_new RENAME) raise an exception, the final `PRAGMA foreign_keys=ON`
statement will not execute, leaving foreign keys permanently disabled for the
connection. Wrap the middle statements (the table creation, data insertion, and
table swap operations) in a try/finally block to ensure that `PRAGMA
foreign_keys=ON` is always executed regardless of whether an error occurs during
the migration steps.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c1776315-8449-45c8-acf4-3f40bb5ffd5b

📥 Commits

Reviewing files that changed from the base of the PR and between e00b556 and 4340337.

📒 Files selected for processing (26)
  • alembic_db/versions/0005_allow_case_sensitive_tags.py
  • app/assets/api/routes.py
  • app/assets/api/schemas_in.py
  • app/assets/api/upload.py
  • app/assets/database/queries/tags.py
  • app/assets/helpers.py
  • app/assets/services/ingest.py
  • app/assets/services/path_utils.py
  • comfy_api/feature_flags.py
  • openapi.yaml
  • server.py
  • tests-unit/assets_test/conftest.py
  • tests-unit/assets_test/queries/test_asset_info.py
  • tests-unit/assets_test/queries/test_tags.py
  • tests-unit/assets_test/services/test_path_utils.py
  • tests-unit/assets_test/test_assets_missing_sync.py
  • tests-unit/assets_test/test_crud.py
  • tests-unit/assets_test/test_downloads.py
  • tests-unit/assets_test/test_list_cursor.py
  • tests-unit/assets_test/test_list_filter.py
  • tests-unit/assets_test/test_metadata_filters.py
  • tests-unit/assets_test/test_prune_orphaned_assets.py
  • tests-unit/assets_test/test_tags_api.py
  • tests-unit/assets_test/test_uploads.py
  • tests-unit/feature_flags_test.py
  • tests-unit/websocket_feature_flags_test.py

Comment thread alembic_db/versions/0005_allow_case_sensitive_tags.py Outdated
@guill guill assigned guill and unassigned guill Jun 23, 2026
@mattmillerai mattmillerai added the cursor-review Trigger multi-model Cursor code review label Jun 25, 2026
Comment thread openapi.yaml
Comment thread server.py Outdated
Comment thread app/assets/api/routes.py
Comment thread app/assets/api/schemas_in.py
@synap5e synap5e force-pushed the synap5e/assets-namespaced-tags branch from cb67c0e to 45cf933 Compare June 27, 2026 02:42

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/assets/services/ingest.py`:
- Around line 105-109: The tag persistence flow in ingest should separate
caller-provided tags from backend-derived ones: in the path that uses
get_path_derived_tags_from_path(locator) and adds the injected "uploaded" tag,
keep user labels with tag_origin="manual" but persist backend-generated tags
(including input/output/models/model_type:* and uploaded) with a backend/system
origin instead. Update the write path around normalize_tags and the related tag
creation logic so the origin is assigned based on whether the tag came from the
caller or from trusted server-side state, and apply the same split in the other
affected tag-persisting block as well.

In `@openapi.yaml`:
- Line 1639: The multipart upload description in the API contract still mentions
the hash-only flow, which does not belong on the POST /api/assets upload path
because that endpoint requires file content. Update the description text in
openapi.yaml where the asset upload schema is documented to remove
hash-only/deduplicated reference creation wording, and keep that guidance only
on the /api/assets/from-hash contract so the multipart upload behavior matches
the endpoint’s actual inputs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8410f72b-69a8-4865-b6ec-48c181086096

📥 Commits

Reviewing files that changed from the base of the PR and between e520a2e and 45cf933.

📒 Files selected for processing (9)
  • app/assets/api/routes.py
  • app/assets/api/schemas_in.py
  • app/assets/api/upload.py
  • app/assets/services/ingest.py
  • app/assets/services/path_utils.py
  • openapi.yaml
  • server.py
  • tests-unit/assets_test/services/test_path_utils.py
  • tests-unit/assets_test/test_uploads.py
💤 Files with no reviewable changes (3)
  • app/assets/api/upload.py
  • app/assets/api/schemas_in.py
  • app/assets/api/routes.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • server.py

Comment thread app/assets/services/ingest.py Outdated
Comment thread openapi.yaml Outdated
@synap5e synap5e force-pushed the synap5e/assets-namespaced-tags branch from 45cf933 to df91e4b Compare June 27, 2026 02:57
@synap5e synap5e force-pushed the synap5e/assets-namespaced-tags branch from 662b09f to 44b3239 Compare June 27, 2026 03:14
@synap5e

synap5e commented Jun 27, 2026

Copy link
Copy Markdown
Author

@guill per feedback I updated the PR:

  • Restored the openapi.yaml fields
  • Removed the introduced /api/assets subfolder field entirely
  • Preserved existing /upload/image arbitrary subfolder placement behavior.
  • Refactored the known image-upload subfolder-to-tags allowlist into a centralized helper, so only exact known values like pasted, painter, webcam, threed, and 3d are mirrored as tags.
  • Added scanner/path-derived recovery for those same known image-upload input subfolders, so direct/scan-discovered files under e.g. input/pasted/<file> recover the pasted tag

Also:

  • Updated OpenAPI docs to describe the narrowed /api/assets tag routing: destination role + optional model_type:*, with extra tags stored as labels rather than path components, and removed a scope-crept doc fix unrelated to these changes (on hash only multipart upload)
  • Split upload tag provenance internally so path-derived tags are stored as automatic, while caller/upload-provided tags keep their existing origin
  • Updated related tests

@synap5e synap5e requested a review from guill June 27, 2026 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-coded cursor-review Trigger multi-model Cursor code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants