Feat/v2.7 editor sam audio memory - #174
Open
AEmotionStudio wants to merge 53 commits into
Open
Conversation
…gement improvements
…eo editor UI enhancements.
…UI components, alongside various skill and node enhancements.
…rame picker node and UI, and expand shader effects.
… TTS, and Foundation-1 Music, along with new nodes, shaders, and various enhancements and fixes.
…gside various node and UI enhancements.
…e agent node UI for expanded model support
… and clean up UI widget logic
…ting without torch installed
…ith ai_normals support
…o vram tracking list
…extended editor parameters, and update segment parsing logic
Thread a `model` selector ("4b" / "9b" / "9b_fp8") through the FLUX Klein
edit/remove paths so callers can pick the model size. The auto_mask handler
reads `_flux_klein_model` from pipeline metadata and passes it into the
editor's remove/edit calls; composer, pipeline assembler, and batch processor
forward the variant through.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vendored Sapiens2 (Meta, ICLR 2026) for human-centric tasks — pose (308 keypoints), segmentation, surface normals, pointmaps, matting, and pretrain features — with detector, model definitions, FP8 conversion/runtime, weight I/O, task registry, rendering, and an orchestrator. Exposed via the `sapiens2_synthesizer` module and registered in the VRAM manager's synthesizer list for cleanup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add configurable square VAE tile size and overlap to the SeedVR upscaler's model loader and generation phases (defaults 512 / 64), and update the memory manager accordingly so tiling can be tuned to fit available VRAM. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a `sam_version` selector ("sam3.1" default / "sam3") to the Effects
Builder and Load Video Path nodes, with per-version checkpoint discovery and
model caches in core/sam3_masker.py.
For SAM 3.1 video masking, run ComfyUI's native SAM3 model in-process instead
of the upstream `sam3` pip package in a subprocess. The model loads as a
standard ModelPatcher (VRAM-managed, no CUDA-context leak), so no child
process is needed. Both text- and point-prompted tracking are supported,
reusing ComfyUI's forward_video/forward_segment, _extract_text_prompts, and
unpack_masks. The existing mirror checkpoint loads natively as-is.
The native path is gated by FFMPEGA_SAM3_NATIVE (default on) and falls back
automatically to the legacy subprocess + upstream path on any error. The
Load Video Path node skips its aggressive unload_all_models() when native is
active, since ComfyUI offloads only what it needs.
Fix the SAM 3.1 video OOM/hang on 12 GB GPUs: running inference without
torch.inference_mode() let autograd retain every 1008x1008 activation
(~10-11.5 GB peak -> OOM). Wrapping the native inference in inference_mode
drops peak to ~3 GB. Public API of mask_video/mask_video_subprocess is
unchanged. Adds tests in test_auto_mask.py.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…w UI - Add core/image_resize.py and wire optional resize (enable_resize, resize_width/height, upscale_method) into Load Image Path. - input_resolver: when no video/images tensor is connected, use a connected image_path as the primary source (so still images flow into ai_upscale / rembg / image-edit modes) instead of being treated only as references. - Front-end/UI: Load Last Image node, image preview (TS + compiled JS), agent/load-image node UI, and ffmpega_ui refresh; rename the VideoEditor export alias to VideoEditorNode. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cross-cutting wiring for the features added in this branch: - model_manager: register sam3_1, flux_klein_9b / flux_klein_9b_fp8, and the sapiens2_* model entries (sizes, mirror repos, manual-download notes). - install.py: SAM3 capability check that force-reinstalls sam3 from main when an existing install predates the SAM 3.1 multiplex builders; add Sapiens2 dependencies. - nollm_modes: new process_sapiens2_only handler; thread sam_version through sam3_premask and flux_klein_model through the FLUX Klein path; FlashVSR VAE tiling + still-image-source output handling in ai_upscale; fix the comparison-mode ffmpeg blend (time-animated reveal that evaluated crop width only at t=0). - agent_node: expose the sapiens2 no-LLM mode, sapiens2_task, flux_klein_model, and upscale VAE-tiling widgets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The *_HANDOFF.md docs are working scratch notes (e.g. the SAM 3.1 video OOM handoff is superseded by the native-path fix) — keep them local, not in the repo. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Session transcripts, console captures, debug screenshots and the local HuggingFace mirror cache are working scratch — they should not ship. Follows the existing internal-handoff-notes pattern. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Encoding wrote full-range (yuvj420p + color_range=pc) to avoid the darkening seen on RGB -> YUV conversion. But yuvj420p is deprecated, and players that normalise it to yuv420p re-expand the levels — crushing blacks and blowing highlights. Tag the input as full-range RGB so swscale does a correct full -> limited conversion explicitly (scale=in_range=pc:out_range=tv), matching ComfyUI's own SaveVideo. No darkening, no re-expansion. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tracks a list of images against the native in-process SAM 3.1 model, reusing the existing _load_native_sam31 loader. Consumed by the SCAIL-2 pipeline for reference-image and pose-video identity tracking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
register_blockswap() is not a custom offload engine — it leans on ComfyUI's own lowvram partial loader. Inflating EXTRA_RESERVED_VRAM for the duration of prepare_sampling shrinks the weight budget that loader computes, so it leaves that many bytes on the offload device and casts them per-layer on forward. LoRA still applies at cast time and GGUF weights keep working, both of which a hand-rolled offload would break. SVI: new blockswap_blocks (of 40 Wan 2.2 transformer blocks) and tiled_vae options. The text encoder is now evicted once all prompts are encoded up-front, so it stops competing with the UNets and VAE during sampling. FlashVSR: blockswap_blocks drives DiffSynth's num_persistent_param_in_dit budget (-1 auto-sizes from free VRAM), plus spatial decode tiling to bound TCDecoder activation memory and whole/temporal/spatial processing modes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebuilds the reference Wan21_SCAIL2 workflow inside a single synthesizer that runs entirely in-process under ComfyUI's VRAM management — the same approach that fixed the SAM 3.1 OOM, and no subprocess. Loads the SCAIL-2 fp8 diffusion model via comfy.sd.load_diffusion_model plus the Wan 2.1 VAE, UMT5 text encoder and CLIP-vision (ViT-H), reusing the SVI/Wan-Animate discovery helpers. Applies model-only LoRAs and a ModelSamplingSD3 shift, tracks the driving pose video and reference image with native SAM 3.1, colorizes per-identity masks via SCAIL2ColoredMask, builds conditioning with WanSCAILToVideo, and samples through comfy.samplers. Emits both the animation and the colored pose mask. Removes the vendored core/scail and core/scail_pose packages and core/scail_synthesizer.py (~4,100 lines) that this supersedes. model_manager also picks up small mirror/manual touch-ups for flux-klein, seedvr2 and sapiens2 alongside the new scail2 entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
seedvr2_7b_fp8_mixed keeps the final transformer block (35) in FP16 while the rest stays FP8. That removes the 7B-specific seam/grid artifacts of pure FP8 at the same VRAM footprint. Mirrored to AEmotionStudio/SeedVR2-models. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The sapiens2_size dropdown folds the fp8 model choice into the size value via a ' (fp8)' suffix, so precision rides along with the size. Bare sizes return no override and the caller falls back to 'auto'. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
FaceCam encodes camera pose as a drawn MediaPipe face mesh. The original pipeline produced that mesh by rendering a 3D Gaussian proxy head along the camera path and running a face detector over the renders — throwing away the camera pose we had already computed analytically, then paying a detector to guess it back. MediaPipe loses the mesh past roughly 40-50 degrees of yaw, which is exactly the pose a camera orbit exists to produce, so conditioning went blank at the extremes. Pose MediaPipe's own canonical face model with the same camera matrices and project it instead. Coverage is total by construction, motion is smooth because it is an analytic function of the camera path, and orbit_left/orbit_right are exact mirrors rather than differing by however well the detector coped with each direction. The canonical model is not shipped in the mediapipe wheel, but the face_landmarker task bundle already on disk is a zip containing the 468 canonical vertices — no vendored asset required. Adds the mesh_source widget and wires blockswap_blocks through the shared register_blockswap helper. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… Image Both save nodes now take multiple sources through auto-growing images_a / video_path_a / image_path_a inputs and combine them into a single side-by-side or grid result. Video panels are laid out with ffmpeg xstack, and shorter clips freeze on their last frame until the longest ends. Images are composited tensor-only in image_compare, so the image path needs no ffmpeg at all. Both share the layout math in grid_layout so panels land identically either way. New widgets: layout (auto/horizontal/vertical/grid), label_panels, labels and panel_gap. Adds the Save Image frontend handler. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…PhyFPS modes Expands no_llm_mode to 31 entries, adding scail2, sapiens2, svi, sharp, wan_animate, phyfps and video_matting. Brings 25 scail2_* widgets (geometry, sampling, pose extension, object selection/sorting, compositing, block swap, tiled VAE and SAM 3.1 detection controls), the sapiens2_size selector with its fp8 option, and the FlashVSR processing/frame_window/color_fix/decode_tile controls. upscale_model gains the flashvsr_* entries and seedvr2_7b_fp8_mixed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…drop enable_mask collapses mask_mode, mask_output_type, sam_version and show_mask_preview behind one switch, so nodes that never mask show four fewer rows. When off the backend forces mask_mode='none'; an upstream MASK connection still passes through. onConfigure detects and repairs the one-slot widgets_values shift this would otherwise cause in workflows saved before the input existed — a string landing in the BOOLEAN is the tell, and workflows predating mask_mode fall short of that index and correctly skip the repair. skip_first_frames and frame_load_cap now carry a dimmed 'N left' suffix showing unused source frames. Written to widget.label, which ComfyUI already draws in the theme's secondary colour and truncates on narrow nodes — a widget-level draw override would have replaced the built-in rendering wholesale instead of layering onto it. Video files can now be dropped anywhere on the node. ComfyUI routes graph drops through a document listener that dispatches to app.dragOverNode, which is only ever set by a dragover listener on the canvas; the node's DOM widgets sit above the canvas, so the whole preview area was dead and crossing onto it actually cancelled an already-valid drag. New shared attachFileDropZone helper handles the DOM side with an enter/leave depth counter, and a dashed overlay covers the preview while dragging. The upload button is pinned to a fixed row height — arrangeWidgets gives computeSize widgets a fixed height and splits leftover node height among the rest, so with no computeSize the button absorbed all of it. Uploads now go through api.fetchApi rather than a bare fetch, so the route resolves via api_base + /api and carries the Comfy-User and auth headers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Generated output for the preceding source commits. ffmpega_ui.js is a single bundle spanning every frontend change, so it cannot be split along source lines. Chunk hashes rotate with content. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CHANGELOG [Unreleased] grows from 3 entries to 30 across Added/Changed/ Removed/Fixed. Several already-committed features had never been logged at all — MatAnyone2, FlashVSR, SCAIL, Visual Chronometer, Wan-Animate, Sapiens2, SVI and PhyFPS each had zero mentions in the file. README gains an 'In Development (Unreleased)' section above the collapsed v2.19.0 block, ten missing rows in the AI Models table (with their storage paths, mirror repos, dependency warnings and the non-commercial licences on MatAnyone2 and SHARP), and the full 31-entry no_llm_mode list, which was still showing 24. No version tag cut — everything stays under [Unreleased]. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
core/video/encode_opts.py becomes the single source of truth for the colour policy, the output format table, ffmpeg argument construction and the tensor->bytes conversion; core/video/metadata.py handles embedding the workflow into the container. The metadata module follows ComfyUI's native convention (prompt/workflow container tags written with -movflags use_metadata_tags) rather than VideoHelperSuite's comment FFMETADATA pass, because the stock frontend already reads those tags back -- dropping a saved mp4 onto the canvas restores the workflow with no client-side code of our own. Matroska and WebM uppercase their tag keys, so those containers additionally get a comment tag for readers that only look there. Both are imported lazily by callers rather than re-exported from core/video/__init__.py: they pull in torch, which must not become an import-time cost for core.video.analyzer users. Nothing routes through them yet; the encoders follow. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Each encoder had drifted to its own colour handling, and several disagreed with the samples they actually wrote: - media_converter tagged output yuvj420p full-range, which players normalise back to yuv420p and re-expand -- crushing blacks and blowing highlights. - nollm_modes (_encode_frames_to_video, SHARP renderer) and svi_synthesizer passed -color_range pc while swscale wrote limited-range samples, so levels that were never compressed got expanded anyway. - images_to_video (Video Editor, Shader Overlay, FacePoke, Load Last Video) wrote untagged BT.601, disagreeing with everything else in the pack. - video_compare stacked panels with xstack, which does not reconcile inputs with different or missing colour tags, so a BT.601 clip beside a BT.709 one showed a visible seam. Panels are converted to BT.709 and the result tagged to match. Two conversion bugs fixed with them: images_to_video cast frames with an unclamped (x * 255).astype(uint8), so Wan's slightly out-of-range VAE output wrapped instead of clipping and 1.004 came out black; and the cast truncated rather than rounded, sending 0.999 to 254 and darkening every frame by 1/255. export.py passes no colour arguments on purpose -- ffmpeg carries the source's properties through the filter graph, so a tagged input stays tagged across the multi-pass chain and an untagged one has nothing we could honestly invent for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A node pair for extending a shot across queue runs. FFMPEGASaveLastFrame writes the trailing frame(s) of a generation into a named slot under output/ffmpega_last_frame/<slot>/; FFMPEGALoadLastFrame reads that slot back, so a later run starts where the previous one ended. Built for i2v chaining (Wan 2.2 and similar), where continuing a shot means handing the model the frame you finished on and no authored end-frame exists. When images is connected the frame comes straight from the IMAGE tensor and is written to PNG with no h264 round-trip -- extracting from the encoded file instead bakes in compression artifacts and yuv420p chroma subsampling, which compound visibly across a chain of generations. video_path remains as an ffmpeg fallback for any video on disk. Named slots let several chains coexist without cross-talk and make the Save/Load pairing an explicit contract rather than "newest file anywhere wins"; names are sanitized to [A-Za-z0-9_-] before any path join. A slot holds exactly frame_count files at fixed zero-padded names and stale files from a longer previous run are pruned, so loading never returns a mix of two runs -- keep_history switches to an accumulating archive instead. on_missing (fallback / empty / error) plus a fallback_image input handle the cold start, so the first run of a chain uses your original start image rather than feeding a black frame into the sampler. Both nodes show a thumbnail strip of whatever the slot currently holds, filled from /ffmpega/last_frame/slot as soon as the node is placed -- without it you would have to run the graph just to see which frame you are continuing from. They are absent from NODE_COLORS on purpose: registerNodeStyling short-circuits the handler chain, and these two need a real handler. SaveLastFrame exposes a last_frame IMAGE passthrough -- the exact tensor written -- which is the correct way to chain inside one workflow. Two unconnected nodes have no guaranteed execution order and caching is decided before execution begins, so a same-graph Load would read the previous run's frame; a wildcard trigger input is provided as an explicit ordering hint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
frame_select_mode gains a `last` entry that selects only the final frame, for the same scene-continuation use case the Last Frame nodes serve. The back-off from the end is frame-relative (0.5 / fps) rather than the fixed 0.01s that first_last uses, which at 100fps is a full frame period and would land on the second-to-last frame. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
attachPlayheadTracker reports playhead movement on a <video>: the position, whether playback is running, and why it moved. requestVideoFrameCallback fires once per rendered frame, so a readout built on it matches the picture rather than trailing it; timeupdate (~4Hz) is the fallback. Seeks, pauses and metadata loads are reported too, so a readout stays live while parked. The cause is what makes it more than a convenience: a caller that snaps the playhead around can act only on "frame" and leave seeks alone -- undoing a seek fights whoever asked for it. frameAtTime and rangeEndSeconds carry the maths that select_every_nth makes subtle, where the count of selected frames and the span of source time they cover come apart. Both are pure, and ui_helpers.test.ts covers them -- the pack's first frontend unit test, on the vitest/happy-dom setup that was already configured with no test files. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eview FFMPEGASaveVideo gains a full encoding surface, so webm/ProRes/lossless output no longer means falling back to VideoHelperSuite. Every new widget is optional, so workflows saved before them keep working unchanged. All of it sits behind one show_advanced toggle, off by default, leaving the node's resting size unchanged. Visibility is two-level -- the toggle reveals the section, and within it any widget the chosen format cannot use collapses on its own (VP9/AV1 take a deadline rather than an x264 preset, ProRes and FFV1 have fixed quality, GIF/WebP carry no audio). Hiding is display-only: values are kept and still honoured, so collapsing never silently changes an encode. The default stays a plain shutil.copy2 with no ffmpeg call at all. When only the container differs -- or the source already holds the codec the chosen format produces -- the file is stream-copied, which is lossless and near instant; a full re-encode happens only when the codec has to change, and an ffmpeg failure falls back to a plain copy rather than losing the render. bit_depth=10 streams 16-bit rgb48le and encodes yuv420p10le, moving the 8-bit quantisation into swscale and greatly reducing banding on gradients. frame_output (preview (64) / all / none) makes the previously silent 64-frame downsample of the images output explicit and skippable. A connected AUDIO input is now muxed into an image encode, which used to drop it silently. The preview's info bar gains the frame count: 1920x1080 | 120f @ 24fps | 5.0s | 12.3 MB, with a live playhead while playing. Both numbers are probed from the file that was written -- reusing probe_video_stats() -- rather than derived from the fps widget or images.shape[0], so pingpong, loop_count and pass-through sources report the truth. A <video> exposes neither, so they ride along in the UI payload next to file_size; where ffprobe is unavailable the segment is omitted and the bar looks as it did before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…counter Dragging the preview scrubber past the trim range's out-point jumped the playhead to the in-point, paused or not. With frame_load_cap set (81 frames of a 30s clip ends the range around 3s) nearly the whole scrubber was unreachable, and the "Jump: Middle / End" menu items were undone the moment they landed. The range clamp lived in a timeupdate listener, which also fires while seeking and never checked whether the video was playing. It now runs off attachPlayheadTracker and loops back only when playback runs off the out-point on its own: seeks are never reversed, and a previous-tick test means playing on from a spot the user deliberately parked past the out-point is left alone too. Two more defects in the same code: - The out-point ignored select_every_nth. It used availFrames / effFps, but 60 frames taken every 2nd are spread across 120 source frames, so playback was cut off halfway. Now via rangeEndSeconds(). - Any trim-widget edit re-seeked to the in-point, and the widget-poll cache started empty so a spurious "everything changed" pass seeked to 0 about 800ms after the node appeared. The seek now fires only when the in-point actually moves, and the cache is seeded from the widgets. The live frame counter never appeared: it was gated on _srcMeta.fps > 0, set only if the /ffmpega/video_info probe returned an fps, while the info bar beside it fell back to _srcMeta.fps || 24. Whenever that probe failed or lagged the bar rendered 24fps happily and the counter stayed hidden forever. Both share the one fallback now. The readout also gained its f unit and stopped duplicating the frame total already in the bar: given a playhead that segment becomes the playhead and moves to the front, where a number changing several times a second is easiest to read and cannot be mistaken for the static total it replaced. It tracks paused scrubbing too, since the frame you are parked on is the number skip_first_frames needs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Covers the Save/Load Last Frame nodes, Load Last Video's last mode, Save Video's advanced output options and frame count, the shared encoding module, the colour-policy fixes across every encoder, and the Load Video Path scrubber and frame-counter fixes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Regenerated from src/ by vite. Picks up the Last Frame node UI, the Save Video preview's frame count, the Load Video Path scrubber and frame-counter fixes, and the shared playhead tracker they route through. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Adds seedvr2_3b_int8 / seedvr2_7b_int8 upscale models. The loader detects ComfyUI's int8_tensorwise + block-Hadamard layout from the per-layer comfy_quant tags, swaps the matching nn.Linear layers for Int8ConvRotLinear before the state dict is applied, and dispatches to comfy_kitchen.int8_linear so the weight is never dequantized. Remaining FP16 tensors are cast to BF16, and an architecture check refuses a checkpoint for the wrong variant instead of loading noise under strict=False. Also: models/diffusion_models/ is searched alongside models/SEEDVR2/, the download gate now only fires for files that are actually missing, the INT8 entries are added to every model list (node, skill, nollm) with a test that keeps them in sync, and agent intermediates inherit the source fps instead of a hardcoded 24. _comfy_stubs.py gives both conftests a shared folder_paths model-folder stub so the discovery code exercises its normal branches. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LoadVideoPathNode borrowed SaveVideoNode._extract_frames without a mode and inherited its "preview (64)" default, so any clip over 64 frames was evenly resampled and played back near double speed downstream. Decoding now goes through core.media_converter.decode_video_frames() for both nodes; the loader reports frame_count from the decoded tensor, and the save node's _extract_frames requires an explicit mode. Save Video's images output defaults to "all", and fps is a FLOAT so NTSC rates are expressible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Snaps a requested size and frame count to what each video model can actually take (Wan /16 grid + 4n+1, H3 /32 + 17k+5, ...), registered as FFMPEGAVideoResolution. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_panel_count defaulted to 2, so a run with no depth/normals pass was SBS-unpacked to iw/2. It now defaults to 1 and unpack_sbs is a no-op for a single panel. Also fix the LoadLast decoder on ffmpeg 8+: -vsync was removed upstream, so every dense decode failed and callers that swallow the error returned a 512x512 zero tensor. Use -fps_mode and retry with -vsync only when ffmpeg reports it as unknown, matching core/last_frame.py. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Implements the onNodeOutputsUpdated extension hook to rebuild the player from app.nodeOutputs on tab switch / queue-history recovery, and persists a descriptor in node properties so reloads and server restarts restore it too. Adds a comfyui/* test alias with a minimal stub so the pure helpers are unit-testable under vitest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ew persistence Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Feat, bug, and regression checks needed.