diff --git a/10_Wiki/Topics/.obsidian/app.json b/10_Wiki/Topics/.obsidian/app.json index 9e26dfee..e609a07e 100644 --- a/10_Wiki/Topics/.obsidian/app.json +++ b/10_Wiki/Topics/.obsidian/app.json @@ -1 +1,3 @@ -{} \ No newline at end of file +{ + "promptDelete": false +} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/community-plugins.json b/10_Wiki/Topics/.obsidian/community-plugins.json new file mode 100644 index 00000000..4f11771b --- /dev/null +++ b/10_Wiki/Topics/.obsidian/community-plugins.json @@ -0,0 +1,5 @@ +[ + "janitor", + "broken-links", + "consistent-attachments-and-links" +] \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/graph.json b/10_Wiki/Topics/.obsidian/graph.json index b744faa4..56239514 100644 --- a/10_Wiki/Topics/.obsidian/graph.json +++ b/10_Wiki/Topics/.obsidian/graph.json @@ -17,6 +17,6 @@ "repelStrength": 10, "linkStrength": 1, "linkDistance": 250, - "scale": 0.07123123306098605, + "scale": 0.05977147038950453, "close": true } \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/broken-links/data.json b/10_Wiki/Topics/.obsidian/plugins/broken-links/data.json new file mode 100644 index 00000000..2dd3b581 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/broken-links/data.json @@ -0,0 +1,1745 @@ +{ + "version": "1.2.2", + "previousVersion": "1.0.0", + "groupBy": 0, + "expandedFolderItems": [ + "02_Architecture_Principles", + "02_Architecture_Principles/Single Responsibility Principle (SRP).md", + "02_Architecture_Principles/SOLID Principles.md", + "03_DevOps_Environment", + "03_DevOps_Environment/Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성).md", + "03_DevOps_Environment/CI-CD Pipeline.md", + "Agent & AI", + "Agent & AI/ConnectAI_Dev_Log_20260429.md", + "AI", + "AI/_뇌와 팔다리의 분리_ - 관심사의 분리 (Separation of Concerns).md", + "AI/Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리).md", + "AI/AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처).md", + "AI/Complexity Theory.md", + "AI/Control Systems Engineering.md", + "AI/Distributed-Computing.md", + "AI/Domain-Driven-Design-DDD.md", + "AI/Drama Management Systems.md", + "AI/Elite-Strength-and-Conditioning.md", + "AI/Emotionally Intelligent Tutoring Systems (EITS).md", + "AI/Exploration vs Exploitation.md", + "AI/Frontend-Architecture.md", + "AI/Homeostasis (항상성).md", + "AI/Microservices-Architecture.md", + "AI/Skybound Protocol 코드리뷰.md", + "AI/Software-Architecture-Patterns.md", + "AI/stochastic gradient descent.md", + "AI/Swarm Intelligence.md", + "AI/Systems Thinking.md", + "AI/Uber-Base-Web-Design-System.md", + "AI/마이크로서비스 아키텍처 (Microservices Architecture).md", + "AI & Games", + "AI & Games/Combined Arms (제병협동) 전술.md", + "AI & Games/Eugen Systems 모딩 매뉴얼.md", + "AI & Games/Eugen Systems의 냉전기 가상 시나리오 및 모딩 생태계 구축.md", + "AI & Games/War-Yes - Warno-Armory (커뮤니티 데이터 분석 도구).md", + "AI & Games/War-Yes 및 Warno-Armory 도구.md", + "AI & Games/Warno 데이터 기반 설계.md", + "AI & Games/WARNO 그래픽 엔진 업그레이드 프로젝트.md", + "AI & Games/WARNO 데이터 기반 밸런싱.md", + "AI & Games/WARNO 데이터 기반 설계.md", + "AI & Games/WARNO 멀티플레이어 및 경쟁 플레이 밸런스 패치.md", + "AI & Games/WARNO 모딩.md", + "AI & Games/WARNO 밸런싱 및 사단 시스템.md", + "AI & Games/WARNO 전술 시뮬레이션 시스템.md", + "AI & Games/WARNO 커뮤니티 데이터 도구 생태계.md", + "AI & Games/WARNO 커뮤니티 모딩 생태계.md", + "AI & Games/모딩 커뮤니티 도구 (War-Yes, Warno-Armory).md", + "AI & Games/제병협동 (Combined Arms).md", + "AI & Games/제병협동 전술 (Combined Arms).md", + "AI_and_ML", + "AI_and_ML/Abstract_Syntax_Tree.md", + "AI_and_ML/Adaptive RAG.md", + "AI_and_ML/AdSense_Revenue_Blog_Architecture.md", + "AI_and_ML/Agent Memory Systems.md", + "AI_and_ML/Agentic RAG.md", + "AI_and_ML/Aggregates.md", + "AI_and_ML/AI Evaluation & Benchmarks.md", + "AI_and_ML/AI Safety & Constitutional AI.md", + "AI_and_ML/AI 기반 코드 분석 도구 (AI-Powered Code Analysis Tools).md", + "AI_and_ML/AI_and_ML.md", + "AI_and_ML/AI_Code_Review_Tools.md", + "AI_and_ML/AI_Content_Production_Pipeline.md", + "AI_and_ML/AI_Powered_Code_Analysis.md", + "AI_and_ML/AI_Powered_Code_Review.md", + "AI_and_ML/AI_Security_and_Governance.md", + "AI_and_ML/AI_기반_코드_분석_자동화Autofix_및_Triage.md", + "AI_and_ML/AI_지원_코드_리뷰_AI-Assisted_Code_Review.md", + "AI_and_ML/AI_코드_리뷰_AI_Code_Review.md", + "AI_and_ML/Anaemic Domain Model.md", + "AI_and_ML/Architecture Anti-patterns.md", + "AI_and_ML/Architecture_Styles.md", + "AI_and_ML/AST(Abstract_Syntax_Tree).md", + "AI_and_ML/Attention Mechanism.md", + "AI_and_ML/Attention Mechanisms.md", + "AI_and_ML/Autonomous Agents & Workflows.md", + "AI_and_ML/Autonomous_Agents_and_Workflows.md", + "AI_and_ML/BERT.md", + "AI_and_ML/Blog_Production_Standard_Manual.md", + "AI_and_ML/C4_Model.md", + "AI_and_ML/ChatGPT_Emoticon_Prompt_Engineering.md", + "AI_and_ML/Chrome_DevTools.md", + "AI_and_ML/Chunking & Pre-processing.md", + "AI_and_ML/Cloud-Native Computing.md", + "AI_and_ML/Cloud-Native_Architecture.md", + "AI_and_ML/Code Review Checklist.md", + "AI_and_ML/Code Review Etiquette & Communication (코드 리뷰 에티켓 및 커뮤니케이션).md", + "AI_and_ML/Code_Review.md", + "AI_and_ML/Code_Review_Methodology.md", + "AI_and_ML/Code_Smells.md", + "AI_and_ML/Code_Smells_Refactoring.md", + "AI_and_ML/Codebase_Maps_and_Interactive_Tours.md", + "AI_and_ML/Codebase_Onboarding_Guide.md", + "AI_and_ML/CodeScene.md", + "AI_and_ML/Cognition Overcoming Action.md", + "AI_and_ML/Cognitive Constraints.md", + "AI_and_ML/Cognitive Psychology & Behavioral Science.md", + "AI_and_ML/Connect-AI-Architecture.md", + "AI_and_ML/Container_Diagram_C4_Model.md", + "AI_and_ML/Containerization_and_Docker.md", + "AI_and_ML/Context Integration.md", + "AI_and_ML/Context Window & Long-Context LLMs.md", + "AI_and_ML/Conway's_Law.md", + "AI_and_ML/DDD_Domain-Driven_Design.md", + "AI_and_ML/Decision Tree & XGBoost.md", + "AI_and_ML/Dependency_Injection_(DI).md", + "AI_and_ML/Deployment Frameworks.md", + "AI_and_ML/Development Communication Standards.md", + "AI_and_ML/DevOps and Tooling.md", + "AI_and_ML/DevSecOps.md", + "AI_and_ML/Diagrams_as_Code.md", + "AI_and_ML/Distributed Processing (Context & Sequence Parallelism).md", + "AI_and_ML/Distributed-Systems.md", + "AI_and_ML/Domain-Driven_Design.md", + "AI_and_ML/Embedding Models & MRL.md", + "AI_and_ML/Event Sourcing Pattern.md", + "AI_and_ML/Event_Sourcing.md", + "AI_and_ML/Feature Engineering.md", + "AI_and_ML/Federated RAG.md", + "AI_and_ML/Fine-Tuning & Alignment.md", + "AI_and_ML/Flash Attention.md", + "AI_and_ML/GAME_SYSTEM_DESIGN_PROMPT.md", + "AI_and_ML/Git_Synchronization_Protocol.md", + "AI_and_ML/GitHub_Artifacts.md", + "AI_and_ML/GitHub_Artifacts_NL_Context.md", + "AI_and_ML/GPU Infrastructure.md", + "AI_and_ML/GraphRAG.md", + "AI_and_ML/GraphRAG_and_PKM.md", + "AI_and_ML/Grouped-Query Attention (GQA).md", + "AI_and_ML/Hexagonal Architecture Pattern.md", + "AI_and_ML/Hexagonal_Architecture.md", + "AI_and_ML/Hopfield Network.md", + "AI_and_ML/Hybrid Search.md", + "AI_and_ML/Innovative Problem Solving.md", + "AI_and_ML/Intentional_Failure_Induction.md", + "AI_and_ML/Key-Value (KV) Cache.md", + "AI_and_ML/KV Cache Compression.md", + "AI_and_ML/Large Language Model (LLM).md", + "AI_and_ML/Learning to Rank (LTR).md", + "AI_and_ML/Legacy_Modernization.md", + "AI_and_ML/LLM Inference Optimization.md", + "AI_and_ML/LLM-as-a-Judge_LaaJ.md", + "AI_and_ML/LLM-based_Code_Analysis.md", + "AI_and_ML/LLM_Context_Extraction.md", + "AI_and_ML/LLM_Fundamentals.md", + "AI_and_ML/LLM_Large_Language_Model.md", + "AI_and_ML/LLM_Ops_and_Tuning.md", + "AI_and_ML/LLM_기반_컨텍스트_추출_LLM-based_Context_Extraction.md", + "AI_and_ML/Local_AI_and_Infrastructure.md", + "AI_and_ML/Local_LLM_Infrastructure_MiniPC.md", + "AI_and_ML/Lost in the Middle & Context Rot.md", + "AI_and_ML/Machine Learning (Machine Learning).md", + "AI_and_ML/Mechanistic Interpretability & Steering.md", + "AI_and_ML/Mermaid_Diagrams_as_Code.md", + "AI_and_ML/Microservices Architecture (MSA).md", + "AI_and_ML/Microservices Architecture Pattern.md", + "AI_and_ML/Miscellaneous_AI_Topics.md", + "AI_and_ML/Mixture of Experts (MoE) & Sparse Architectures.md", + "AI_and_ML/Model_Context_Protocol.md", + "AI_and_ML/Model_Context_Protocol_Guide.md", + "AI_and_ML/Model_Context_Protocol_MCP.md", + "AI_and_ML/Modular Monolith.md", + "AI_and_ML/Morphological and Syntactic Analysis.md", + "AI_and_ML/Multi-Agent System (Multi-Agent System).md", + "AI_and_ML/Multimodal RAG.md", + "AI_and_ML/Natural Language Processing (NLP).md", + "AI_and_ML/Neuro-Symbolic AI.md", + "AI_and_ML/NotebookLM_Research_Workflow.md", + "AI_and_ML/Ollama_Local_LLM_Setup_Guide.md", + "AI_and_ML/On-Device_AI_Mobile_Gemma.md", + "AI_and_ML/PagedAttention.md", + "AI_and_ML/PEFT & LoRA.md", + "AI_and_ML/Personal Knowledge Management (PKM) & AI.md", + "AI_and_ML/Ports_and_Adapters.md", + "AI_and_ML/Pull_Request_PR.md", + "AI_and_ML/RAG Evaluation Frameworks.md", + "AI_and_ML/RAG_and_Vector_Search.md", + "AI_and_ML/Reasoning Models.md", + "AI_and_ML/Refactoring_Best_Practices.md", + "AI_and_ML/Refactoring_Principles.md", + "AI_and_ML/Reranking.md", + "AI_and_ML/Retrieval-Augmented Generation (RAG).md", + "AI_and_ML/Ring Attention.md", + "AI_and_ML/SAST.md", + "AI_and_ML/SCA_Fundamentals.md", + "AI_and_ML/Search_Intent_Keyword_Strategy.md", + "AI_and_ML/Secrets_Detection.md", + "AI_and_ML/Selective State Space Models (Mamba).md", + "AI_and_ML/Sequence_Diagram.md", + "AI_and_ML/Software Architecture Pattern.md", + "AI_and_ML/Software Maintenance.md", + "AI_and_ML/Software_Composition_Analysis.md", + "AI_and_ML/Software_Composition_Analysis_(SCA).md", + "AI_and_ML/Software_Design_Patterns.md", + "AI_and_ML/Software_Supply_Chain_Security.md", + "AI_and_ML/SonarQube.md", + "AI_and_ML/SonarQube_Quality_Gate.md", + "AI_and_ML/Sparse Attention.md", + "AI_and_ML/Static_Code_Analysis.md", + "AI_and_ML/Structurizr.md", + "AI_and_ML/Supply_Chain_Security.md", + "AI_and_ML/Team Topologies.md", + "AI_and_ML/Test-Driven_Development.md", + "AI_and_ML/Tokenization & Subword Processing.md", + "AI_and_ML/Tokenization Economics.md", + "AI_and_ML/Tool Use & Function Calling.md", + "AI_and_ML/Transformer Architecture.md", + "AI_and_ML/Ubiquitous_Language.md", + "AI_and_ML/Vector Database.md", + "AI_and_ML/Vector Databases & Search.md", + "AI_and_ML/Vector Embedding.md", + "AI_and_ML/Vector Search.md", + "AI_and_ML/vLLM.md", + "AI_and_ML/Weak Central Coherence.md", + "AI_and_ML/소프트웨어_아키텍처_다이어그램_Software_Architecture_Diagrams.md", + "AI_and_ML/손실 회피.md", + "AI_and_ML/인공지능 코드 분석 (AI-Powered Codebase Analysis).md", + "AI_and_ML/자연어 아티팩트 (Natural Language Artifacts).md", + "AI_and_ML/자연어_아티팩트_NL_Artifacts.md", + "AI_and_ML/컨텍스트 엔진 (Context Engine).md", + "AI_and_ML/컨텍스트_빌더_Context_Builder.md", + "AI_and_ML/코드 리뷰 프로세스 (Code Review Process).md", + "AI_and_ML/코드_분석_도구_Code_Analysis_Tools.md", + "AI_and_ML/코드_분석_및_자동화_도구_Automated_Code_Analysis_Tools.md", + "AI_and_ML/코드_속성_그래프_CPG.md", + "AI_and_ML/프레임워크별_실전_패턴.md", + "Architecture", + "Architecture/ACID Transactions.md", + "Architecture/ADR_(Architecture_Decision_Record).md", + "Architecture/ADR_(Architecture_Decision_Records).md", + "Architecture/AI-Assisted Refactoring (AI 기반 리팩토링).md", + "Architecture/Apache Ignite.md", + "Architecture/API Gateway.md", + "Architecture/API-First_Architecture.md", + "Architecture/API_Design_Principles.md", + "Architecture/API_Fundamentals.md", + "Architecture/Append-only log.md", + "Architecture/Approval Testing - Snapshot Testing (승인-스냅샷 테스트).md", + "Architecture/Architectural Violations.md", + "Architecture/Architecture Erosion (아키텍처 침식).md", + "Architecture/Architecture Evaluation (아키텍처 평가).md", + "Architecture/Architecture.md", + "Architecture/Architecture_Diagramming_Standards.md", + "Architecture/Aspect-Oriented Programming (AOP).md", + "Architecture/ATAM (Architecture Trade-offs Analysis Method).md", + "Architecture/ATAM (Architecture Tradeoff Analysis Method).md", + "Architecture/Automated Testing (자동화된 테스트).md", + "Architecture/Automated_Code_Analysis.md", + "Architecture/Big Design Up Front.md", + "Architecture/BLoC.md", + "Architecture/Blog_Writing_Structure_Pattern.md", + "Architecture/Bottom-Up-Approach.md", + "Architecture/BPM.md", + "Architecture/Broker Architecture Pattern.md", + "Architecture/Broker Topology.md", + "Architecture/Business Process Execution Language (BPEL).md", + "Architecture/C4_Modeling_Framework.md", + "Architecture/Call_Stack.md", + "Architecture/Call_Stack_Analysis.md", + "Architecture/Characterization Tests (특성화 테스트).md", + "Architecture/Choreography.md", + "Architecture/CI-CD_Pipeline.md", + "Architecture/CI_CD.md", + "Architecture/Circuit Breaker Pattern.md", + "Architecture/Clean Architecture Pattern.md", + "Architecture/Clean Architecture.md", + "Architecture/Clean_Architecture.md", + "Architecture/Cloud_Native_Patterns.md", + "Architecture/Code Rot (코드 부패 - 소프트웨어 부패).md", + "Architecture/Code Smell (코드 스멜).md", + "Architecture/Code_Refactoring.md", + "Architecture/Codebase_Orientation_Map.md", + "Architecture/Codebase_Reading_Framework.md", + "Architecture/Complex Event Processing (CEP).md", + "Architecture/Compound_Components.md", + "Architecture/Conceptual Integrity.md", + "Architecture/CQRS (Command Query Responsibility Segregation).md", + "Architecture/CQRS_Pattern.md", + "Architecture/DDD_Aggregates.md", + "Architecture/Dependencies (의존성).md", + "Architecture/Dependency-Injection.md", + "Architecture/Dependency-Inversion-Principle.md", + "Architecture/Dependency_Analysis.md", + "Architecture/Dependency_Inversion.md", + "Architecture/Design Pattern.md", + "Architecture/Design-System.md", + "Architecture/Design_Patterns.md", + "Architecture/Distributed Systems Fallacies.md", + "Architecture/Distributed Tracing.md", + "Architecture/Distributed_Computing.md", + "Architecture/Documentation-Strategy.md", + "Architecture/Domain-Driven Design (DDD).md", + "Architecture/DORA-Metrics.md", + "Architecture/DRY_Don't_Repeat_Yourself_원칙.md", + "Architecture/DRY_Principle.md", + "Architecture/Dynamic Systems Development Method (DSDM).md", + "Architecture/Dynamic_Behavior_Tracking.md", + "Architecture/Event Mediator.md", + "Architecture/Event-Driven Architecture Pattern.md", + "Architecture/Event-Driven_Architecture.md", + "Architecture/Event-Driven_Architecture_EDA.md", + "Architecture/Event_Storming.md", + "Architecture/Eventual Consistency.md", + "Architecture/Executable_Documentation.md", + "Architecture/Factory_Pattern.md", + "Architecture/Fault-Tolerance.md", + "Architecture/File-based_Routing.md", + "Architecture/Game_Design_Theory.md", + "Architecture/Git_History_Analysis.md", + "Architecture/gRPC_and_Protocol_Buffers.md", + "Architecture/Implementation Separation.md", + "Architecture/In-Memory Data Grid.md", + "Architecture/Infrastructure_as_Code.md", + "Architecture/Integration_Architecture_Diagrams.md", + "Architecture/ISO 25010 (Quality Model).md", + "Architecture/ISO 25010.md", + "Architecture/ISO-IEC_25010.md", + "Architecture/Istio.md", + "Architecture/Keeper of the Vision.md", + "Architecture/Kubernetes.md", + "Architecture/Kubernetes_Orchestration.md", + "Architecture/Layered Architecture Pattern.md", + "Architecture/Layered Architecture.md", + "Architecture/Layered_Architecture.md", + "Architecture/Legacy Code (레거시 코드).md", + "Architecture/Legacy_Modernization_Strategy.md", + "Architecture/Logging_Diagnostics.md", + "Architecture/Macro-architecture.md", + "Architecture/Mediator Topology.md", + "Architecture/Mermaid_Diagrams.md", + "Architecture/Message Broker.md", + "Architecture/Message Brokers.md", + "Architecture/Microservices Architecture.md", + "Architecture/Microservices_Architecture.md", + "Architecture/Mock Objects (가짜 객체).md", + "Architecture/Monolithic Architecture Pattern.md", + "Architecture/Monolithic_Architecture.md", + "Architecture/New_Architecture.md", + "Architecture/Nudge_Theory.md", + "Architecture/Object-Oriented-Programming.md", + "Architecture/Observability.md", + "Architecture/Observer Pattern.md", + "Architecture/Onion_Architecture.md", + "Architecture/Open-Closed Principle (개방-폐쇄 원칙).md", + "Architecture/PlantUML.md", + "Architecture/Polymorphism (다형성).md", + "Architecture/Predictive_Refactoring.md", + "Architecture/Project_Codebase_Organization.md", + "Architecture/Prototyping.md", + "Architecture/Publish-Subscribe Model.md", + "Architecture/Pull_Request_Review.md", + "Architecture/React_Architecture.md", + "Architecture/Reactive_Programming.md", + "Architecture/Red-Green Refactoring.md", + "Architecture/Refactoring (리팩토링).md", + "Architecture/Refactoring Techniques (리팩토링 기법).md", + "Architecture/Refactoring.md", + "Architecture/Router_Implementation.md", + "Architecture/Rule of Three (3의 법칙).md", + "Architecture/Saga Pattern (Orchestration).md", + "Architecture/Saga Pattern.md", + "Architecture/SARA (Software Architecture Review and Assessment).md", + "Architecture/Scalability.md", + "Architecture/Scratch Refactoring (스크래치 리팩토링).md", + "Architecture/Serverless_Architecture.md", + "Architecture/Service Mesh.md", + "Architecture/Service-Oriented Architecture (SOA).md", + "Architecture/Sidecar Architecture Pattern.md", + "Architecture/Simple event processing.md", + "Architecture/Single_Responsibility_Principle_(SRP).md", + "Architecture/Singleton Pattern.md", + "Architecture/Snapshots.md", + "Architecture/Software Architecture Documentation.md", + "Architecture/Software Architecture Knowledge Management (소프트웨어 아키텍처 지식 관리).md", + "Architecture/Software Development Life Cycle (SDLC).md", + "Architecture/Software_Architecture.md", + "Architecture/Software_Architecture_Erosion.md", + "Architecture/Software_Architecture_Patterns.md", + "Architecture/Software_Architecture_Recovery.md", + "Architecture/SOLID_Principles.md", + "Architecture/SOLID_원칙.md", + "Architecture/Space-Based_Architecture.md", + "Architecture/State-Strategy Pattern (상태-전략 패턴).md", + "Architecture/Static Code Analysis (정적 코드 분석기).md", + "Architecture/Static_and_Dynamic_Analysis.md", + "Architecture/Static_Code_Analysis_Tools.md", + "Architecture/Stream Processing.md", + "Architecture/System_Architecture_Documentation.md", + "Architecture/Technical_Debt.md", + "Architecture/Template Method Pattern (템플릿 메서드 패턴).md", + "Architecture/Testability_Architecture.md", + "Architecture/Testability_in_Architecture.md", + "Architecture/UML_Diagrams.md", + "Architecture/UML_Methodology.md", + "Architecture/Utility Tree (유틸리티 트리).md", + "Architecture/vFunction.md", + "Architecture/Vue_Architecture.md", + "Architecture/Wrap Method (랩 메서드).md", + "Architecture/객체_지향_프로그래밍_Object-Oriented_Programming,_OOP.md", + "Architecture/관심사의_분리_Separation_of_Concerns,_SoC.md", + "Architecture/도메인_주도_설계_DDD.md", + "Architecture/동적_애플리케이션_보안_테스트_DAST.md", + "Architecture/로그_Logs.md", + "Architecture/마이크로서비스 아키텍처의 의존성 관리.md", + "Architecture/버전_관리_이력_Version_Control_History.md", + "Architecture/분산_시스템_아키텍처_Distributed_Systems_Architecture.md", + "Architecture/비기능 요구사항 (Non-functional Requirements).md", + "Architecture/비기능적 요구사항 (Non-functional Requirements, NFRs).md", + "Architecture/생성_패턴_Creational_Patterns.md", + "Architecture/소프트웨어 아키텍처 평가 (Software Architecture Evaluation).md", + "Architecture/소프트웨어_구성_분석SCA.md", + "Architecture/스택_트레이스(Stack_trace).md", + "Architecture/시스템 아키텍처 시각화 (System Architecture Visualization).md", + "Architecture/아키텍처 스타일 및 디자인 패턴 (Architectural Styles & Design Patterns).md", + "Architecture/아키텍처 패턴 지식.md", + "Architecture/아키텍처_다이어그램_Architecture_Diagram.md", + "Architecture/애자일 소프트웨어 개발과 아키텍처 (Agile Software Development and Architecture).md", + "Architecture/의사결정_매트릭스(Decision_Matrix).md", + "Architecture/인터페이스와_포트-어댑터_Interfaces_and_Ports-Adapters.md", + "Architecture/지식 증발 (Knowledge Vaporization).md", + "Architecture/추상_구문_트리_AST.md", + "Architecture/컴포넌트 기반 아키텍처 (CBA).md", + "Architecture/클린_코드_Clean_Code.md", + "Architecture/프로토타이핑 및 개념 증명(PoC).md", + "Architecture/하향식_탐색_Top-Down_Approach.md", + "Architecture/핫스팟_탐지_Hotspot_Detection.md", + "Architecture/형상_관리_체계_Version_Control_System.md", + "Backend", + "Backend/Accordion.md", + "Backend/API_Application_Programming_Interface.md", + "Backend/Backend as a Service (BaaS).md", + "Backend/Backend.md", + "Backend/Composition_API.md", + "Backend/Dependency Injection (DI).md", + "Backend/DTO (Data Transfer Object).md", + "Backend/GraphQL_and_Data_Fetching.md", + "Backend/Middleware & Interceptors.md", + "Backend/NestJS_Microservices.md", + "Backend/Serverless_Computing.md", + "Backend/Spring Boot.md", + "Backend/Spring_Cloud.md", + "Backend/WebHooks_and_Notifications.md", + "Backend/WebSockets_and_Realtime.md", + "Backend/동적-정적 코드 분석 (Static-Dynamic Code Analysis).md", + "Backend/디버깅_전략_Debugging_Strategies.md", + "Backend/라우터_Routers.md", + "Backend/로그_Logs_및_에러_메시지_Error_Messages.md", + "Backend/상향식_및_하향식_탐색_Top-Down_&_Bottom-Up_Approach.md", + "Backend/상향식_및_하향식_탐색_Top-down_&_Bottom-up_Navigation.md", + "Backend/소프트웨어 문서화 (Software Documentation).md", + "Backend/엔드포인트_Endpoints.md", + "Backend/진입점 (Entry Points).md", + "Backend/코드베이스_투어_Codebase_Tours.md", + "Backend/하향식Top-Down_접근법.md", + "Balancing", + "Balancing/Game Design & Math", + "Balancing/Game Design & Math/Algorithmic Game Theory.md", + "Business_and_Management", + "Business_and_Management/5-Second Rule.md", + "Business_and_Management/Agile Methodology (애자일 방법론).md", + "Business_and_Management/Agile Software Development (애자일 소프트웨어 개발).md", + "Business_and_Management/Blog_Headline_and_Subtitle_Strategy.md", + "Business_and_Management/Bounce Forward.md", + "Business_and_Management/Business Intelligence (BI) & Data Discovery.md", + "Business_and_Management/Business_and_Management.md", + "Business_and_Management/Calculated Risk.md", + "Business_and_Management/Career Mobility (경력 이동성).md", + "Business_and_Management/Content_Portfolio_Strategy.md", + "Business_and_Management/Creative and Flexible Corporate Culture.md", + "Business_and_Management/Decision Tree.md", + "Business_and_Management/Extreme Programming (XP).md", + "Business_and_Management/Goal Drive and Action Power.md", + "Business_and_Management/Green Yellow Red Zones.md", + "Business_and_Management/Knowledge Management in Engineering.md", + "Business_and_Management/Leadership & Organizational Resilience.md", + "Business_and_Management/MECE Framework.md", + "Business_and_Management/Mutual Growth.md", + "Business_and_Management/Omni-channel Strategy.md", + "Business_and_Management/Operational Excellence & Knowledge Transfer (운영 우수성 및 지식 전수).md", + "Business_and_Management/PR_Issue_Tracking.md", + "Business_and_Management/Proactive Approach.md", + "Business_and_Management/Proactive Organizational Culture.md", + "Business_and_Management/Proactive Personality.md", + "Business_and_Management/Proactive Response.md", + "Business_and_Management/Progressive_Web_Apps.md", + "Business_and_Management/Reactive Behavior.md", + "Business_and_Management/Resilience.md", + "Business_and_Management/Review Performance & Flow.md", + "Business_and_Management/Risk Management & Engineering.md", + "Business_and_Management/Risk Management.md", + "Business_and_Management/SEO (Search Engine Optimization).md", + "Business_and_Management/Strategic Agility.md", + "Business_and_Management/Strategic Thinking & Proactive Action.md", + "Business_and_Management/Theory of Planned Behavior.md", + "Business_and_Management/UML_Unified_Modeling_Language.md", + "Business_and_Management/Zones of Initiative.md", + "Business_and_Management/리팩토링 및 기술 부채 관리 (Refactoring & Technical Debt Management).md", + "Business_and_Management/하이브리드 전략 (Hybrid Strategy).md", + "Business_Strategy", + "Business_Strategy/Himart_UIUX_Direction_20260428.md", + "Business_Strategy/Himart_Webstore_Meeting_20260429.md", + "Computational Theory & Math", + "Computational Theory & Math/Graph Theory.md", + "Computer_Science_and_Theory", + "Computer_Science_and_Theory/Caetextia.md", + "Computer_Science_and_Theory/Computer_Science_and_Theory.md", + "Computer_Science_and_Theory/Cross-Frequency Coupling (CFC).md", + "Computer_Science_and_Theory/Design Patterns (디자인 패턴).md", + "Computer_Science_and_Theory/Flame-Icicle_Graph_플레임-고드름_그래프.md", + "Computer_Science_and_Theory/FMEA.md", + "Computer_Science_and_Theory/Global Workspace Theory.md", + "Computer_Science_and_Theory/Information Retrieval (IR).md", + "Computer_Science_and_Theory/Information Retrieval Evaluation Metrics.md", + "Computer_Science_and_Theory/Keyword Search.md", + "Computer_Science_and_Theory/Knowledge Graph.md", + "Computer_Science_and_Theory/Neural Ignition.md", + "Computer_Science_and_Theory/Ontology.md", + "Computer_Science_and_Theory/Phase-Amplitude Coupling.md", + "Computer_Science_and_Theory/Structured Data.md", + "Computer_Science_and_Theory/Theta-Gamma Coupling.md", + "Computer_Science_and_Theory/Weak Central Coherence Theory.md", + "Computer_Science_and_Theory/Working Memory.md", + "Content_Strategy", + "Content_Strategy/Mobile-First Design.md", + "Core_Systems", + "Core_Systems/AI & Games", + "Core_Systems/AI & Games/AlphaZero Strategy.md", + "Core_Systems/Game Design", + "Core_Systems/Game Design/Agency and Player Autonomy.md", + "Core_Systems/Game Design/Post-Modernist Literature in Gaming.md", + "Core_Systems/Game Design/Quantum-Game-Theory.md", + "Core_Systems/Physics & Simulation", + "Core_Systems/Physics & Simulation/Aerospace Flight Simulation.md", + "Core_Systems/Simulation & Math", + "Core_Systems/Simulation & Math/Agent-Based Modeling (ABM).md", + "Core_Systems/System Design & Modeling", + "Core_Systems/System Design & Modeling/Event Storming.md", + "Core_Systems/Cyber-Physical Systems (CPS).md", + "Core_Systems/Systems Biology.md", + "Design_and_UX", + "Design_and_UX/Blog_Tone_and_Manner_Guide.md", + "Design_and_UX/Design_and_UX.md", + "Design_and_UX/Personalization & User Intent.md", + "Design_and_UX/Psychology.md", + "Design_and_UX/성능_병목_현상_Performance_Bottlenecks.md", + "Design_and_UX/의존성_매핑_Dependency_Mapping.md", + "Development", + "Development/Code Refactoring.md", + "DevOps_and_Security", + "DevOps_and_Security/A_B-Testing-Platforms.md", + "DevOps_and_Security/Code Review Automation & Metrics (코드 리뷰 자동화 및 지표).md", + "DevOps_and_Security/Code_Property_Graph.md", + "DevOps_and_Security/Commit_History.md", + "DevOps_and_Security/Continuous Integration & Continuous Deployment (CI-CD).md", + "DevOps_and_Security/Continuous_Integration.md", + "DevOps_and_Security/DAST_Fundamentals.md", + "DevOps_and_Security/Data Governance & Privacy.md", + "DevOps_and_Security/Debugger_Techniques.md", + "DevOps_and_Security/DevOps_and_Security.md", + "DevOps_and_Security/DevSecOps_Framework.md", + "DevOps_and_Security/Digital Twins.md", + "DevOps_and_Security/Dynamic_Application_Security_Testing.md", + "DevOps_and_Security/Flame_Graphs.md", + "DevOps_and_Security/Git (Version Control System).md", + "DevOps_and_Security/Governance Agent.md", + "DevOps_and_Security/Logging_and_Error_Handling.md", + "DevOps_and_Security/Production Observability.md", + "DevOps_and_Security/SAST_Fundamentals.md", + "DevOps_and_Security/Secret_Management.md", + "DevOps_and_Security/Security_Posture_Management.md", + "DevOps_and_Security/Static_Application_Security_Testing.md", + "DevOps_and_Security/Test_Automation.md", + "DevOps_and_Security/Test_Automation_Mastery.md", + "DevOps_and_Security/Version_Control_Systems.md", + "DevOps_and_Security/Zero-Trust Architecture.md", + "DevOps_and_Security/객체 수명 주기 (Object Life Cycle).md", + "DevOps_and_Security/동적 런타임 분석 (Dynamic Runtime Analysis).md", + "DevOps_and_Security/런타임 프로파일링 (Runtime Profiling).md", + "DevOps_and_Security/리뷰_맵_Review_Maps.md", + "DevOps_and_Security/버전 관리 이력 분석 (Version Control History Analysis).md", + "DevOps_and_Security/버전 관리 추적 분석 (Version Control Tracking).md", + "DevOps_and_Security/버전_관리_시스템_VCS.md", + "DevOps_and_Security/버전_관리_이력Git_History-Commits.md", + "DevOps_and_Security/애플리케이션_보안_태세_관리ASPM.md", + "DevOps_and_Security/중단점 (Breakpoints).md", + "DevOps_and_Security/지속적 보안(DevSecOps)과 CI-CD 통합.md", + "DevOps_and_Security/코드베이스 맵 (Codebase Map).md", + "Economics & Algorithms", + "Economics & Algorithms/AI 기반 보상 및 난이도 스케일링.md", + "Economics & Algorithms/Chef Universe.md", + "Economics & Algorithms/Dynamic Pricing.md", + "Economics & Algorithms/EVE 온라인(EVE Online).md", + "Economics & Algorithms/Fortnite.md", + "Economics & Algorithms/Game of War- Fire Age BM 및 게임 구조 분석.md", + "Economics & Algorithms/Game of War- Fire Age BM.md", + "Economics & Algorithms/Machinations 라이브옵스 데이터 연동.md", + "Economics & Algorithms/Machinations(토크노믹스 시뮬레이션).md", + "Economics & Algorithms/Monetization Strategy.md", + "Economics & Algorithms/Play-and-Earn.md", + "Economics & Algorithms/가상 경제 인플레이션(Game Economy Inflation).md", + "Economics & Algorithms/가차(Gacha) 시스템.md", + "Economics & Algorithms/가챠(Gacha) 시스템.md", + "Economics & Algorithms/게임 경제 설계(Game Economy Design).md", + "Economics & Algorithms/게임 경제 인플레이션(Game Economy Inflation).md", + "Economics & Algorithms/게임 내 광고(IAA).md", + "Economics & Algorithms/게임 데이터 분석(Game Analytics).md", + "Economics & Algorithms/게임 수익화 전략(Monetization Strategy).md", + "Economics & Algorithms/고객 유지율(Retention).md", + "Economics & Algorithms/과금 의향 (Willingness to Pay).md", + "Economics & Algorithms/동적 가격 책정(Dynamic Pricing).md", + "Economics & Algorithms/디아블로 2(Diablo II).md", + "Economics & Algorithms/라이브옵스(Live-ops).md", + "Economics & Algorithms/마키네이션(Machinations.io) 시뮬레이션.md", + "Economics & Algorithms/무료 플레이(Free-to-Play) 모델.md", + "Economics & Algorithms/물리 기반 렌더링(PBR).md", + "Economics & Algorithms/부분 유료화(Free-to-Play).md", + "Economics & Algorithms/사용자 생성 콘텐츠(UGC).md", + "Economics & Algorithms/소액 결제 (Microtransactions).md", + "Economics & Algorithms/수도꼭지와 배수구(Taps and Sinks).md", + "Economics & Algorithms/알비온 온라인(Albion Online)의 경제 시스템.md", + "Economics & Algorithms/원신(Genshin Impact)의 레진 시스템.md", + "Economics & Algorithms/원신(Genshin Impact)의 진행 제한과 가차 시스템.md", + "Economics & Algorithms/이브 온라인(EVE Online).md", + "Economics & Algorithms/인앱 결제(IAP).md", + "Economics & Algorithms/인앱 광고 (IAA).md", + "Economics & Algorithms/인앱 광고(IAA).md", + "Economics & Algorithms/인앱 구매 (IAP).md", + "Economics & Algorithms/인앱 구매(IAP).md", + "Economics & Algorithms/자원 소모처(Sinks).md", + "Economics & Algorithms/잔존율(Retention).md", + "Economics & Algorithms/지불 용의 (Willingness to Pay).md", + "Economics & Algorithms/클래시 로얄(Clash Royale)의 엘릭서.md", + "Economics & Algorithms/탭과 싱크(Taps and Sinks).md", + "Economics & Algorithms/페이 투 윈(Pay to Win).md", + "Economics & Algorithms/포켓랜드(Pocket Land).md", + "Economics & Algorithms/플랫폼 컨버전스(Platform Convergence).md", + "Economics & Algorithms/하이브리드 수익화 (Hybrid Monetization).md", + "Economics & Algorithms/하이브리드 수익화(Hybrid Monetization).md", + "Economics & Algorithms/하이브리드 캐주얼(Hybrid-Casual).md", + "Economics & Algorithms/하이브리드 캐주얼(Hybrid-casual)의 하이브리드 수익화 모델.md", + "Economics & Algorithms/행동 경제학(Behavioral Economics).md", + "Economics & Algorithms/행동 유도성(Affordances).md", + "Economy", + "Economy/4X 전략 게임 수익화 모델.md", + "Economy/계단식 수익화 모델 (Staircase Monetization).md", + "Education", + "Education/Management Consulting (경영 컨설팅).md", + "Education/Management Consulting.md", + "Frontend", + "Frontend/Client Components.md", + "Frontend/Codegen.md", + "Frontend/Composables.md", + "Frontend/Design_Systems_and_Web_Components.md", + "Frontend/Fabric.md", + "Frontend/Frontend.md", + "Frontend/Frontend_Performance.md", + "Frontend/Hermes.md", + "Frontend/Hydration & Progressive Rendering.md", + "Frontend/Impeller_Engine.md", + "Frontend/JSI (JavaScript Interface).md", + "Frontend/Micro-frontends.md", + "Frontend/Next.js App Router.md", + "Frontend/Nextjs_Framework.md", + "Frontend/One-way_Data_Flow.md", + "Frontend/Options API.md", + "Frontend/Pinia.md", + "Frontend/React Hooks.md", + "Frontend/React Suspense.md", + "Frontend/React_Native_Web_-_Desktop.md", + "Frontend/Reactivity System (ref, reactive).md", + "Frontend/Server Side Rendering (SSR).md", + "Frontend/State Management Libraries.md", + "Frontend/TanStack_Query_React_Query.md", + "Frontend/TurboModules.md", + "Frontend_Mastery", + "Frontend_Mastery/Component-Based Architecture.md", + "Frontend_Mastery/Compound Components.md", + "Frontend_Mastery/Concurrent Rendering.md", + "Frontend_Mastery/Container Queries.md", + "Frontend_Mastery/Core Web Vitals.md", + "Frontend_Mastery/Critical Rendering Path.md", + "Frontend_Mastery/CSS Performance Optimization.md", + "Frontend_Mastery/CSS 구조 설계 방식.md", + "Frontend_Mastery/CSS 성능 최적화(CSS Performance Optimization).md", + "Frontend_Mastery/Design System Architecture.md", + "Frontend_Mastery/Design Systems.md", + "Frontend_Mastery/Design Tokens.md", + "Frontend_Mastery/DOM (Document Object Model).md", + "Frontend_Mastery/DOM(Document Object Model).md", + "Frontend_Mastery/E-commerce Platforms.md", + "Frontend_Mastery/Feature-Driven Architecture.md", + "Frontend_Mastery/Feature-Sliced Design (FSD).md", + "Frontend_Mastery/Feature-Sliced Design.md", + "Frontend_Mastery/Fiber Architecture.md", + "Frontend_Mastery/Fiber 아키텍처 (Fiber Architecture).md", + "Frontend_Mastery/Fluid Typography.md", + "Frontend_Mastery/GPU 가속 및 컴포지팅.md", + "Frontend_Mastery/Hydration 성능 최적화.md", + "Frontend_Mastery/Large Frontend Projects.md", + "Frontend_Mastery/Layout Thrashing.md", + "Frontend_Mastery/Monorepo Architecture.md", + "Frontend_Mastery/Next.js App Router 프로젝트.md", + "Frontend_Mastery/Next.js App Router 환경의 컴포넌트 스타일링.md", + "Frontend_Mastery/Next.js 기반 대규모 웹 애플리케이션.md", + "Frontend_Mastery/Next.js 렌더링 최적화.md", + "Frontend_Mastery/Next.js를 활용한 SEO 및 성능 최적화 하이브리드 렌더링 아키텍처 설계.md", + "Frontend_Mastery/Next.js를 활용한 하이브리드 렌더링 및 SEO 최적화.md", + "Frontend_Mastery/React Compiler.md", + "Frontend_Mastery/React Context API.md", + "Frontend_Mastery/React Fiber 및 동시성 렌더링.md", + "Frontend_Mastery/React Fiber 아키텍처.md", + "Frontend_Mastery/React Fiber.md", + "Frontend_Mastery/React Server Components (RSC).md", + "Frontend_Mastery/React Server Components(RSC) 환경의 스타일링 최적화.md", + "Frontend_Mastery/React 기반 대규모 웹 애플리케이션 최적화.md", + "Frontend_Mastery/React 기반 프론트엔드 성능 최적화.md", + "Frontend_Mastery/React 렌더링 최적화.md", + "Frontend_Mastery/React 성능 최적화 (React Performance Optimization).md", + "Frontend_Mastery/React 성능 최적화.md", + "Frontend_Mastery/React 컴파일러 (React Compiler).md", + "Frontend_Mastery/React 컴포넌트 기반 아키텍처.md", + "Frontend_Mastery/React-Vue-Angular 프레임워크.md", + "Frontend_Mastery/React가 빠른 이유.md", + "Frontend_Mastery/Reflow & Repaint.md", + "Frontend_Mastery/Reflow - Repaint 최소화 방법.md", + "Frontend_Mastery/Reflow - Repaint.md", + "Frontend_Mastery/Reflow and Repaint.md", + "Frontend_Mastery/Reflow 및 Repaint 최적화.md", + "Frontend_Mastery/Reflow 및 Repaint.md", + "Frontend_Mastery/Reflow와 Repaint(리플로우와 리페인트).md", + "Frontend_Mastery/Reflow와 Repaint.md", + "Frontend_Mastery/Render Props.md", + "Frontend_Mastery/Responsive Web Design.md", + "Frontend_Mastery/SaaS 대시보드 및 이커머스 레이아웃 구축.md", + "Frontend_Mastery/SaaS 플랫폼 및 인터랙티브 대시보드 개발.md", + "Frontend_Mastery/SEO 중심의 마케팅 및 블로그 사이트 구축.md", + "Frontend_Mastery/Server-Side Rendering (SSR).md", + "Frontend_Mastery/Static Site Generation (SSG).md", + "Frontend_Mastery/Styled Components.md", + "Frontend_Mastery/styled-components.md", + "Frontend_Mastery/Time Slicing.md", + "Frontend_Mastery/Time-Slicing.md", + "Frontend_Mastery/Uber Base Web Design System.md", + "Frontend_Mastery/Virtual DOM.md", + "Frontend_Mastery/Virtual DOM과 Reconciliation.md", + "Frontend_Mastery/“React가 빠른 이유” 및 렌더링 최적화 개념.md", + "Frontend_Mastery/“React가 빠른 이유”.md", + "Frontend_Mastery/가변 타이포그래피 (Fluid Typography).md", + "Frontend_Mastery/가상 DOM (Virtual DOM) 및 재조정(Reconciliation).md", + "Frontend_Mastery/검색 엔진 최적화 (SEO).md", + "Frontend_Mastery/검색 엔진 최적화(SEO) 대응 렌더링 전략 수립.md", + "Frontend_Mastery/기능 중심 아키텍처(Feature-Driven Architecture).md", + "Frontend_Mastery/단일 진실 공급원(Single Source of Truth) 구축.md", + "Frontend_Mastery/단일 진실 공급원(Single Source of Truth).md", + "Frontend_Mastery/단일 페이지 애플리케이션 (SPA).md", + "Frontend_Mastery/단일 페이지 애플리케이션(SPA) 렌더링 설계.md", + "Frontend_Mastery/단일 페이지 애플리케이션(SPA) 아키텍처 설계.md", + "Frontend_Mastery/대규모 프론트엔드 아키텍처(Scalable Frontend Architecture).md", + "Frontend_Mastery/대규모 프론트엔드 프로젝트(Large Frontend Projects).md", + "Frontend_Mastery/동시성 렌더링 (Concurrent Rendering).md", + "Frontend_Mastery/디자인 시스템 (Design System).md", + "Frontend_Mastery/디자인 시스템 (Design Systems).md", + "Frontend_Mastery/디자인 시스템(Design System).md", + "Frontend_Mastery/디자인 시스템(Design Systems).md", + "Frontend_Mastery/디자인 토큰 (Design Tokens).md", + "Frontend_Mastery/디자인 토큰(Design Tokens).md", + "Frontend_Mastery/레이아웃 스래싱(Layout Thrashing).md", + "Frontend_Mastery/렌더링 블로킹 방지를 위한 CSS 분할 및 로딩 최적화.md", + "Frontend_Mastery/리플로우 및 리페인트 (Reflow & Repaint).md", + "Frontend_Mastery/리플로우 및 리페인트(Reflow & Repaint).md", + "Frontend_Mastery/리플로우 및 리페인트(Reflow and Repaint).md", + "Frontend_Mastery/마이크로 인터랙션(Micro-interactions).md", + "Frontend_Mastery/메인 스레드 (Main Thread).md", + "Frontend_Mastery/모던 웹 성능 최적화(Core Web Vitals).md", + "Frontend_Mastery/모바일 우선 설계(Mobile-First Design).md", + "Frontend_Mastery/모바일 우선주의 (Mobile-First) 디자인.md", + "Frontend_Mastery/모바일 퍼스트(Mobile-First).md", + "Frontend_Mastery/미디어 쿼리 (Media Queries).md", + "Frontend_Mastery/미디어 쿼리(Media Queries).md", + "Frontend_Mastery/반응형 웹 UI 구현.md", + "Frontend_Mastery/반응형 웹 디자인 (Responsive Web Design).md", + "Frontend_Mastery/브라우저 렌더링 과정 (Critical Rendering Path).md", + "Frontend_Mastery/브라우저 렌더링 과정 최적화 및 UI 반응성 개선.md", + "Frontend_Mastery/브라우저 렌더링 파이프라인(Critical Rendering Path).md", + "Frontend_Mastery/성능 및 SEO 최적화 프로젝트.md", + "Frontend_Mastery/성능 최적화(Performance Optimization).md", + "Frontend_Mastery/성능 최적화(Reflow & Repaint).md", + "Frontend_Mastery/실무에서 CSS 관리하는 방법.md", + "Frontend_Mastery/애니메이션 (transition - keyframes) 성능 최적화.md", + "Frontend_Mastery/웹 성능 최적화(Web Performance Optimization).md", + "Frontend_Mastery/유동적 타이포그래피 (Fluid Typography).md", + "Frontend_Mastery/유동적 타이포그래피(Fluid Typography).md", + "Frontend_Mastery/유지보수 가능하고 확장 가능한 CSS 아키텍처 설계.md", + "Frontend_Mastery/유지보수 가능한 대규모 프론트엔드 CSS 설계.md", + "Frontend_Mastery/전자상거래 플랫폼 (E-commerce Platforms).md", + "Frontend_Mastery/중요 렌더링 경로 (Critical Rendering Path).md", + "Frontend_Mastery/컨테이너 쿼리 (Container Queries).md", + "Frontend_Mastery/컨테이너 쿼리(Container Queries).md", + "Frontend_Mastery/컴포넌트 기반 아키텍처(Component-Based Architecture).md", + "Frontend_Mastery/크리티컬 렌더링 패스 (Critical Rendering Path).md", + "Frontend_Mastery/프론트엔드 성능 최적화 및 SEO 개선 프로젝트.md", + "Frontend_Mastery/프론트엔드 프레임워크 (React, Angular, Vue).md", + "Frontend_Mastery/피처 슬라이스 디자인 (Feature-Sliced Design).md", + "Frontend_Mastery/하이드레이션 (Hydration).md", + "Frontend_Mastery/확장 가능한 프론트엔드 아키텍처(Scalable Frontend Architecture).md", + "Game Design", + "Game Design/Monetization", + "Game Design/Monetization/Power Creep.md", + "Game Design/Monetization/Staircase Monetization.md", + "Game Design/Monetization/VIP System.md", + "Game Design/Social & Psychology", + "Game Design/Social & Psychology/Social Engineering.md", + "Game Design/Baiting Tactics.md", + "Game Design/Base Layouts.md", + "Game Design/Base-Layouts.md", + "Game Design/Combat Controls.md", + "Game Design/Eugen Systems.md", + "Game Design/Game of War BM과 구조 조사.md", + "Game Design/Game of War BM과 구조 조사.md", + "Game Design/Game of War- Fire Age BM 및 구조 설계.md", + "Game Design/Staircase Monetization Model.md", + "Game Design/VIP 시스템 (VIP System).md", + "Game Design/VIP 시스템.md", + "Game Design/War Commander 전투 생태계의 전술적 진화(Tactical Evolution of the Combat Ecosystem).md", + "Game Design/거점(Control Points) 점령전.md", + "Game Design/계단식 수익화 (Staircase Monetization).md", + "Game Design/과금 모델 (Monetization).md", + "Game Design/기지 방어 레이아웃(Base Layouts).md", + "Game Design/기지 방어 설계(Defensive Architecture).md", + "Game Design/동맹(Alliances).md", + "Game Design/동적 가격 책정 (Dynamic Pricing).md", + "Game Design/매몰 비용의 오류 (Sunk Cost Fallacy).md", + "Game Design/모바일 미드코어 게임의 진화 및 Game of War BM 구조 분석 프로젝트.md", + "Game Design/미끼 전술(Baiting).md", + "Game Design/방어 구조(Defensive Architecture).md", + "Game Design/방어 기하학 및 구조 설계(Defensive Architecture).md", + "Game Design/방어 아키텍처(Defensive Architecture).md", + "Game Design/스태어케이스 수익화 모델 (Staircase Monetization Model).md", + "Game Design/실시간 번역 엔진 (Real-Time Engine).md", + "Game Design/실시간 번역 엔진 (RTE).md", + "Game Design/실시간 엔진 (Real-Time Engine).md", + "Game Design/실시간 엔진 (RTE).md", + "Game Design/영구 손실 (Permanent loss).md", + "Game Design/영구적 손실 (Permanent Loss).md", + "Game Design/유닛 미끼 전술(Baiting).md", + "Game Design/유인 전술(Baiting Tactics).md", + "Game Design/유인 전술(Baiting).md", + "Game Design/전투 제어(Combat Controls).md", + "Game Design/전투 컨트롤(Combat Controls).md", + "Game Design/전투 통제(Combat Controls).md", + "Game Design/피해 유형(Damage Types).md", + "Game Design/혼합 소대(Mixed Platoons).md", + "Game_Design", + "Game_Design/소유 효과.md", + "General Knowledge", + "General Knowledge/2026-04-15.md", + "General Knowledge/Brand-Identity-Management.md", + "General Knowledge/Code Splitting Lazy Loading.md", + "General Knowledge/Description-Logics.md", + "General Knowledge/Dopamine Signaling.md", + "General Knowledge/Iriszoom 엔진.md", + "General Knowledge/Iriszoom 엔진의 물리적 가시화.md", + "General Knowledge/Machinations.io의 몬테카를로 시뮬레이션 및 데이터 예측.md", + "General Knowledge/Markov-Random-Fields.md", + "General Knowledge/Mobile Game Development Financial Model.md", + "General Knowledge/Model-Free RL vs Model-Based RL.md", + "General Knowledge/Mycological Horror.md", + "General Knowledge/OffscreenCanvas (멀티스레딩).md", + "General Knowledge/Pocket Land.md", + "General Knowledge/README.md", + "General Knowledge/Reb's FRAGO 모드.md", + "General Knowledge/RebsFRAGO 모드.md", + "General Knowledge/Resource Deposits(자원 매장지).md", + "General Knowledge/SharedArrayBuffer 보안 이슈와 Cross-Origin Isolation 설정법.md", + "General Knowledge/Variance-Rules.md", + "General Knowledge/데이터 기반 밸런싱 (Data-Driven Balancing).md", + "General Knowledge/데이터 기반 밸런싱(Data-Driven Balancing).md", + "General Knowledge/데이터 기반 밸런싱.md", + "General Knowledge/데이터 기반 설계 (Data-Driven Design).md", + "General Knowledge/데이터 기반 설계(Data-Driven Design).md", + "General Knowledge/디아블로 2(Diablo II) 조던링 사태.md", + "General Knowledge/디지털 트윈(Digital Twin).md", + "General Knowledge/라이브옵스(LiveOps).md", + "General Knowledge/마크-스위프-컴팩트(Mark-Sweep-Compact).md", + "General Knowledge/마키네이션(Machinations).md", + "General Knowledge/모바일 게임 개발 재무 모델 (Mobile Game Development Financial Model).md", + "General Knowledge/무제.md", + "General Knowledge/부분 유료화(Free-to-Play) 게임.md", + "General Knowledge/비디오 게임 산업의 플랫폼 융합(Platform Convergence).md", + "General Knowledge/사용자 제작 콘텐츠(UGC).md", + "General Knowledge/알비온 온라인(Albion Online) 암시장 시스템.md", + "General Knowledge/알비온 온라인(Albion Online).md", + "General Knowledge/원신(Genshin Impact).md", + "General Knowledge/이벤트 포워딩(Event Forwarding).md", + "General Knowledge/자원 관리(Resource Management).md", + "General Knowledge/클래시 로얄(Clash Royale).md", + "General Knowledge/클래시 로얄(Clash Royale)의 대칭성과 밸런싱.md", + "General Knowledge/클래시 로얄(Clash Royale)의 비용-엘릭서 밸런싱.md", + "General Knowledge/하이브리드 캐주얼 (Hybrid Casual).md", + "General Knowledge/환영합니다.md", + "Level_Design", + "Level_Design/세계 지도(World Map).md", + "Level_Design/월드 맵(World Map).md", + "Logic & Reasoning", + "Logic & Reasoning/Deductive and Inductive Reasoning.md", + "Logic & Reasoning/Deductive vs. Inductive Reasoning.md", + "Logic & Reasoning/Inductive and Deductive Reasoning.md", + "Logic & Reasoning/Inductive vs. Deductive Reasoning.md", + "Logic & Reasoning/Mental Models.md", + "Logic & Reasoning/Problem Solving.md", + "Logic & Reasoning/Strategic Thinking.md", + "Market_Research", + "Market_Research/Sociology & Tech", + "Market_Research/Sociology & Tech/Algorithmic Governance.md", + "Market_Research/Sociology & Tech/Algorithmic-Governance.md", + "Marketing", + "Marketing/MrBeast_Algorithm.md", + "Modeling", + "Modeling/Metaverse", + "Modeling/Metaverse/Spatial_Computing.md", + "Modeling/Metaverse & Devices", + "Modeling/Metaverse & Devices/Apple Vision Pro Ecosystem.md", + "Operations", + "Operations/Automation & Industry", + "Operations/Automation & Industry/3D Web-based HMI.md", + "Operations/Governance & Reliability", + "Operations/Governance & Reliability/Autonomous Logging.md", + "Other", + "Other/Advanced Search Operators.md", + "Other/Codebase_Onboarding.md", + "Other/Effective Code Review Feedback.md", + "Other/Improvisation.md", + "Other/Other.md", + "Other/Program Comprehension Strategies.md", + "Other/Progressive_Web_Apps_PWAs.md", + "Other/Server-Side_Rendering_SSR.md", + "Other/TypeScript.md", + "Other/UML_상태_다이어그램_Statechart_Diagram.md", + "Other/동적_분석_Dynamic_Analysis.md", + "Other/동적_코드_분석_Dynamic_Code_Analysis.md", + "Other/디버거_Debugger.md", + "Other/반복적_리뷰Iterative_Review.md", + "Other/아키텍처_드리프트_Architectural_Drift.md", + "Other/유니버스 LTV(Universe LTV).md", + "Other/의도_및_목적_지향적_설명_Purpose-driven_Explanation.md", + "Other/코드_스멜_및_리팩토링_Code_Smells_and_Refactoring.md", + "Other/코드베이스_맵과_대화형_투어_Codebase_Maps_&_Interactive_Tours.md", + "Other/테스트_자동화_및_테스트_주도_개발_Test_Automation_&_TDD.md", + "Other/풀_리퀘스트_및_이슈_트래커_PR_&_Issue_Tracker.md", + "Other/풀_리퀘스트_및_이슈_트래킹_Pull_Requests_&_Issue_Tracking.md", + "Other/행동 경제학.md", + "Programming & Language", + "Programming & Language/bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처.md", + "Programming & Language/Cosmos 플랫폼 (Netflix).md", + "Programming & Language/Excess Property Checking.md", + "Programming & Language/InstancedMesh 동적 버퍼 확장.md", + "Programming & Language/SharedArrayBuffer 동시성 문제 해결법.md", + "Programming & Language/SharedArrayBuffer로 스레드 간 메모리 공유 효율 높이기.md", + "Programming & Language/Structural Typing.md", + "Programming & Language/Turborepo 기반 모노레포 워크플로우.md", + "Programming & Language/Turborepo 환경 구성.md", + "Programming & Language/Turborepo를 활용한 다중 애플리케이션 및 라이브러리 통합 관리.md", + "Programming & Language/Type Casting.md", + "Programming & Language/Union Types.md", + "Programming & Language/객체 지향 프로그래밍 (Object-Oriented Programming).md", + "Programming & Language/객체 지향 프로그래밍 (OOP).md", + "Programming & Language/객체 지향 프로그래밍(OOP).md", + "Programming & Language/관심사의 분리(SoC).md", + "Programming & Language/넷플릭스 코스모스 플랫폼 (Netflix Cosmos).md", + "Programming & Language/넷플릭스(Netflix)의 마이크로서비스 및 코스모스 플랫폼 전환.md", + "Programming & Language/느슨한 결합 (Loose Coupling).md", + "Programming & Language/대규모 모노레포(Turborepo) 환경에서의 린트 오케스트레이션.md", + "Programming & Language/도메인 기반 설계 (DDD).md", + "Programming & Language/모노레포(Monorepo) 기반 구성 중앙화.md", + "Programming & Language/모노레포(Monorepo) 설정 중앙화.md", + "Programming & Language/모노레포(Monorepo) 아키텍처 설정.md", + "Programming & Language/스파게티 코드 (Spaghetti Code).md", + "Programming & Language/안구 운동 기능(Oculomotor functions).md", + "Programming & Language/의존성 역전 (Dependency Inversion).md", + "Programming & Language/의존성 역전 원칙 (Dependency Inversion Principle DIP).md", + "Programming & Language/의존성 역전 원칙 (Dependency Inversion Principle).md", + "Programming & Language/의존성 주입 (Dependency Injection).md", + "Programming & Language/집합론 (Set Theory).md", + "Programming & Language/집합론(Set Theory).md", + "Programming & Language/프론트엔드 및 모노레포(Monorepo) 개발 환경 설정.md", + "Programming & Tools", + "Programming & Tools/ndf-parse 패키지.md", + "Programming & Tools/War-Yes.md", + "Programming & Tools/가변적 LOD(Level of Detail) 시스템.md", + "Programming & Tools/데이터 파싱 (Data Parsing).md", + "Programming & Tools/데이터 파싱(Data Parsing).md", + "Programming & Tools/텔레메트리 (Telemetry) 밸런싱.md", + "Programming & Tools/텔레메트리 (Telemetry).md", + "Programming & Tools/텔레메트리 밸런싱 (Telemetry Balancing).md", + "Programming & Tools/텔레메트리 밸런싱(Telemetry Balancing).md", + "Programming & Tools/텔레메트리(Telemetry) 데이터 분석.md", + "Psychology", + "Psychology/Behavioral_Economics.md", + "Psychology/Operant_Conditioning.md", + "Psychology/Psychological Resilience & Productivity (심리적 회복탄력성 및 생산성).md", + "Psychology & Behavior", + "Psychology & Behavior/소셜 엔지니어링 (Social Engineering).md", + "Security & Reliability", + "Security & Reliability/SAST (Static Application Security Testing).md", + "Security & Reliability/Software Composition Analysis (SCA).md", + "Skybound", + "Skybound/01_Core_Engine", + "Skybound/01_Core_Engine/Combat_System_Reference_Error_Resolution.md", + "Skybound/04_Mechanics_Progression", + "Skybound/04_Mechanics_Progression/Campaign_and_Dual_Loop_System.md", + "Skybound/04_Mechanics_Progression/Equipment_Crafting_and_Synthesis_Full.md", + "Skybound/04_Mechanics_Progression/UX_Gameplay_Protocol_V10_0.md", + "Skybound/05_Project_Issues", + "Skybound/05_Project_Issues/2026-04-22_Engine_Logic_Optimization_Report.md", + "Skybound/2026년 3월 연구 드롭(March 2026 Research Drop).md", + "Skybound/2026년 3월 연구 업데이트(March 2026 Research Drop).md", + "Skybound/March 2026 연구 업데이트(March 2026 Research Drop).md", + "Skybound/Skybound-Knowledge-Hub.md", + "Skybound/Skybound_Enemy_Orientation_Fix.md", + "Skybound/War Commander → 전투 시스템.md", + "Skybound/War Commander 전투 전술 및 방어 메타.md", + "Storytelling", + "Storytelling/AI & Narrative", + "Storytelling/AI & Narrative/AI-Driven Narrative Systems.md", + "Storytelling/AI & Psychology", + "Storytelling/AI & Psychology/Affective Computing.md", + "Storytelling/Psychology & Behavior", + "Storytelling/Psychology & Behavior/ABA(Applied Behavior Analysis).md", + "Storytelling/Psychology & Behavior/Addiction Neuroscience.md", + "Storytelling/Psychology & Behavior/Agent-Based-Modeling.md", + "UI_UX_Assets", + "UI_UX_Assets/Design & Experience", + "UI_UX_Assets/Design & Experience/Accessibility-Compliance-WCAG.md", + "UI_UX_Assets/Design & Experience/Affective User Interfaces (AUI).md", + "UI_UX_Assets/Design & Experience/Agile-UX-Integration.md", + "UI_UX_Assets/Design & Experience/Americans-with-Disabilities-Act-ADA.md", + "UI_UX_Assets/Design & Experience/AODA-Accessibility-for-Ontarians-with-Disabilities-Act.md", + "UI_UX_Assets/Design & Experience/Apple Human Interface Guidelines.md", + "UI_UX_Assets/Design & Experience/Arkane-Studios.md", + "UI_UX_Assets/Design & Experience/Assignability-Rules.md", + "UI_UX_Assets/Design & Experience/Assistive-Technology-Interoperability.md", + "UI_UX_Assets/Design & Experience/AST-Manipulation-Techniques.md", + "UI_UX_Assets/Design & Experience/Atomic Design Pattern.md", + "UI_UX_Assets/Design & Experience/Auction-Theory.md", + "UI_UX_Assets/Design & Experience/Augmented Reality (AR) Interfaces.md", + "UI_UX_Assets/Design & Experience/Automated-Client-Generation.md", + "UI_UX_Assets/Design & Experience/Bay 12 Games.md", + "UI_UX_Assets/Design & Experience/Bazel.md", + "UI_UX_Assets/Design & Experience/Behavior-Driven-Development (BDD).md", + "UI_UX_Assets/Design & Experience/BioShock (Rapture)] [Dark Souls (Environmental Lore)] [Gone Home (Domestic Narrative Architecture).md", + "UI_UX_Assets/Design & Experience/Borderlands-Art-Direction.md", + "UI_UX_Assets/Design & Experience/Boundary-Layer-Validation.md", + "UI_UX_Assets/Design & Experience/Branded Types in TypeScript.md", + "UI_UX_Assets/Design & Experience/Buck2.md", + "UI_UX_Assets/Design & Experience/Causal Loop Diagramming.md", + "UI_UX_Assets/Design & Experience/Choice Architecture in Digital UX.md", + "UI_UX_Assets/Design & Experience/Chrome User Experience Report (CrUX).md", + "UI_UX_Assets/Design & Experience/Code Formatting.md", + "UI_UX_Assets/Design & Experience/Cognitive Aging Research.md", + "UI_UX_Assets/Design & Experience/Cognitive Dissonance.md", + "UI_UX_Assets/Design & Experience/Cognitive-Flexibility.md", + "UI_UX_Assets/Design & Experience/Cognitive-Psychology.md", + "UI_UX_Assets/Design & Experience/Complexity Science in Economics.md", + "UI_UX_Assets/Design & Experience/Computation-Caching-Strategies.md", + "UI_UX_Assets/Design & Experience/Computational Thinking.md", + "UI_UX_Assets/Design & Experience/Computational-Fluid-Dynamics.md", + "UI_UX_Assets/Design & Experience/Conditional-Types.md", + "UI_UX_Assets/Design & Experience/Content-Strategy.md", + "UI_UX_Assets/Design & Experience/Contract-Driven-Development.md", + "UI_UX_Assets/Design & Experience/Contract-First-Development.md", + "UI_UX_Assets/Design & Experience/Contract-Testing.md", + "UI_UX_Assets/Design & Experience/Contravariance-and-Covariance.md", + "UI_UX_Assets/Design & Experience/Creativity-and-Cognitive-Complexity.md", + "UI_UX_Assets/Design & Experience/Critical Design.md", + "UI_UX_Assets/Design & Experience/Cryptoeconomics.md", + "UI_UX_Assets/Design & Experience/Dark Souls (Environmental Storytelling).md", + "UI_UX_Assets/Design & Experience/Data-Sanitization.md", + "UI_UX_Assets/Design & Experience/Declaration Merging.md", + "UI_UX_Assets/Design & Experience/Declaration-Merging.md", + "UI_UX_Assets/Design & Experience/Depth-Subtyping.md", + "UI_UX_Assets/Design & Experience/Design-Thinking.md", + "UI_UX_Assets/Design & Experience/Design-Tokens.md", + "UI_UX_Assets/Design & Experience/Diegetic UI.md", + "UI_UX_Assets/Design & Experience/Diegetic-Interface.md", + "UI_UX_Assets/Design & Experience/Digital Humanities.md", + "UI_UX_Assets/Design & Experience/Digital Twin Interfaces.md", + "UI_UX_Assets/Design & Experience/Digital-Heritage-Preservation.md", + "UI_UX_Assets/Design & Experience/Digital-Humanities.md", + "UI_UX_Assets/Design & Experience/Digital-Transformation-Strategy.md", + "UI_UX_Assets/Design & Experience/Divergent-Thinking.md", + "UI_UX_Assets/Design & Experience/Duck-Typing.md", + "UI_UX_Assets/Design & Experience/Dwarf Fortress.md", + "UI_UX_Assets/Design & Experience/E-commerce-Conversion-Optimization.md", + "UI_UX_Assets/Design & Experience/Edge-Detection-Algorithms.md", + "UI_UX_Assets/Design & Experience/Educational Pedagogy (Zone of Proximal Development).md", + "UI_UX_Assets/Design & Experience/Educational-Psychology.md", + "UI_UX_Assets/Design & Experience/Electromyography.md", + "UI_UX_Assets/Design & Experience/Environmental Storyability.md", + "UI_UX_Assets/Design & Experience/Environmental Storytelling.md", + "UI_UX_Assets/Design & Experience/Environmental-Storytelling.md", + "UI_UX_Assets/Design & Experience/Ergodic Literature.md", + "UI_UX_Assets/Design & Experience/Ergodic-Literature.md", + "UI_UX_Assets/Design & Experience/ESL Pro Tour.md", + "UI_UX_Assets/Design & Experience/ESLint-Plugin-TypeScript.md", + "UI_UX_Assets/Design & Experience/eSports Performance Psychology.md", + "UI_UX_Assets/Design & Experience/Executive Function.md", + "UI_UX_Assets/Design & Experience/Exhaustiveness-Checking-with-Never.md", + "UI_UX_Assets/Design & Experience/Fallout (Pip-Boy Mechanic).md", + "UI_UX_Assets/Design & Experience/Flow-Sensitive-Typing.md", + "UI_UX_Assets/Design & Experience/Formalism vs Structuralism.md", + "UI_UX_Assets/Design & Experience/Formalist Criticism.md", + "UI_UX_Assets/Design & Experience/FSD (Feature-Sliced Design).md", + "UI_UX_Assets/Design & Experience/Game Studies (Game Studies Journal).md", + "UI_UX_Assets/Design & Experience/Game Systems Design.md", + "UI_UX_Assets/Design & Experience/Game-Level-Design.md", + "UI_UX_Assets/Design & Experience/Game-Studies-Academic-Discourse.md", + "UI_UX_Assets/Design & Experience/Game-Studies-Journal.md", + "UI_UX_Assets/Design & Experience/Gamification in Pedagogy.md", + "UI_UX_Assets/Design & Experience/Gamification-Mechanics.md", + "UI_UX_Assets/Design & Experience/GitHub Actions.md", + "UI_UX_Assets/Design & Experience/Global Augmentation.md", + "UI_UX_Assets/Design & Experience/Grammar-based-Synthesis.md", + "UI_UX_Assets/Design & Experience/Haptic Feedback Technology.md", + "UI_UX_Assets/Design & Experience/Hierarchical Reinforcement Learning (HRL).md", + "UI_UX_Assets/Design & Experience/High-Performance-Human-Factors.md", + "UI_UX_Assets/Design & Experience/HUD-less Design Paradigms.md", + "UI_UX_Assets/Design & Experience/Human-Computer Interaction (HCI).md", + "UI_UX_Assets/Design & Experience/Human-Computer-Interaction (HCI).md", + "UI_UX_Assets/Design & Experience/Human-Machine Interface (HMI) Design.md", + "UI_UX_Assets/Design & Experience/Human-Robot Interaction (HRI).md", + "UI_UX_Assets/Design & Experience/Human-Robot-Interaction.md", + "UI_UX_Assets/Design & Experience/Hypertextuality.md", + "UI_UX_Assets/Design & Experience/Immersive Analytics.md", + "UI_UX_Assets/Design & Experience/Incremental-Compilation.md", + "UI_UX_Assets/Design & Experience/Information-Architecture.md", + "UI_UX_Assets/Design & Experience/Interface Segregation Principle (ISP).md", + "UI_UX_Assets/Design & Experience/Interface-Extension-vs-Augmentation.md", + "UI_UX_Assets/Design & Experience/Interface-Extension.md", + "UI_UX_Assets/Design & Experience/Interface-Merging.md", + "UI_UX_Assets/Design & Experience/Interface-Segregation-Principle-in-TypeScript.md", + "UI_UX_Assets/Design & Experience/Interoperability Standards.md", + "UI_UX_Assets/Design & Experience/Intersection-Types-vs-Interface-Extension.md", + "UI_UX_Assets/Design & Experience/ISO 9241 표준.md", + "UI_UX_Assets/Design & Experience/JSON-Schema-Validation.md", + "UI_UX_Assets/Design & Experience/K-12-EdTech.md", + "UI_UX_Assets/Design & Experience/Kinetics.md", + "UI_UX_Assets/Design & Experience/Knowledge-Graph-Construction.md", + "UI_UX_Assets/Design & Experience/LCS (League of Legends Championship Series).md", + "UI_UX_Assets/Design & Experience/Lean-UX.md", + "UI_UX_Assets/Design & Experience/Level Design Theory.md", + "UI_UX_Assets/Design & Experience/Level-Design-Theory.md", + "UI_UX_Assets/Design & Experience/Linguistics.md", + "UI_UX_Assets/Design & Experience/Linked-Data-Principles.md", + "UI_UX_Assets/Design & Experience/Ludo-narrative Dissonance.md", + "UI_UX_Assets/Design & Experience/Ludo-Narrative-Dissonance.md", + "UI_UX_Assets/Design & Experience/Ludonarrative-Dissonance.md", + "UI_UX_Assets/Design & Experience/Mapped-Types.md", + "UI_UX_Assets/Design & Experience/Material Design System.md", + "UI_UX_Assets/Design & Experience/Material Design.md", + "UI_UX_Assets/Design & Experience/Material-Design.md", + "UI_UX_Assets/Design & Experience/Mechanism Design in Auctions.md", + "UI_UX_Assets/Design & Experience/Mechanism Design.md", + "UI_UX_Assets/Design & Experience/Mechanism-Design.md", + "UI_UX_Assets/Design & Experience/Micro-Frontend-Architecture.md", + "UI_UX_Assets/Design & Experience/Mobile-App-Onboarding.md", + "UI_UX_Assets/Design & Experience/Module Resolution Algorithm.md", + "UI_UX_Assets/Design & Experience/Module-Augmentation-Patterns.md", + "UI_UX_Assets/Design & Experience/Module-Resolution-Strategy.md", + "UI_UX_Assets/Design & Experience/Monorepo-Architecture-Design.md", + "UI_UX_Assets/Design & Experience/Monorepo-Architecture.md", + "UI_UX_Assets/Design & Experience/Monorepo-Dependency-Graph-Analysis.md", + "UI_UX_Assets/Design & Experience/Monte Carlo Tree Search (MCTS).md", + "UI_UX_Assets/Design & Experience/Motor-Learning-Theory.md", + "UI_UX_Assets/Design & Experience/Motor-Learning.md", + "UI_UX_Assets/Design & Experience/Narrative Design.md", + "UI_UX_Assets/Design & Experience/Narrative Intelligence.md", + "UI_UX_Assets/Design & Experience/Nash Equilibrium.md", + "UI_UX_Assets/Design & Experience/Nash-Equilibrium.md", + "UI_UX_Assets/Design & Experience/Ninja-Build-System.md", + "UI_UX_Assets/Design & Experience/Nodejs-Backend-Architecture.md", + "UI_UX_Assets/Design & Experience/Nominal Typing.md", + "UI_UX_Assets/Design & Experience/Nominal-Typing-via-Branded-Types.md", + "UI_UX_Assets/Design & Experience/Nominal-Typing-vs-Structural-Typing.md", + "UI_UX_Assets/Design & Experience/Nominal-vs-Structural-Typing.md", + "UI_UX_Assets/Design & Experience/Non-Diegetic UI.md", + "UI_UX_Assets/Design & Experience/Nx-Build-System.md", + "UI_UX_Assets/Design & Experience/Object-Literal-Assignment.md", + "UI_UX_Assets/Design & Experience/Object-Oriented-Interface-Design.md", + "UI_UX_Assets/Design & Experience/Occupational-Ergonomics.md", + "UI_UX_Assets/Design & Experience/OpenAPI-Specification.md", + "UI_UX_Assets/Design & Experience/Optimal-Experience-Research.md", + "UI_UX_Assets/Design & Experience/Organizational Learning Culture.md", + "UI_UX_Assets/Design & Experience/Organizational-Innovation-Management.md", + "UI_UX_Assets/Design & Experience/Orthopedic-Implant-Validation.md", + "UI_UX_Assets/Design & Experience/Player Agency.md", + "UI_UX_Assets/Design & Experience/Player-Autonomy.md", + "UI_UX_Assets/Design & Experience/Political-Philosophy-in-Games.md", + "UI_UX_Assets/Design & Experience/Product-Analytics-Infrastructure.md", + "UI_UX_Assets/Design & Experience/Protocol-Buffers-TypeScript.md", + "UI_UX_Assets/Design & Experience/Public Policy Design.md", + "UI_UX_Assets/Design & Experience/Quantum-Computing-Simulations.md", + "UI_UX_Assets/Design & Experience/Rapier 물리 엔진 스냅샷(Snapshot) 기반 상태 복원.md", + "UI_UX_Assets/Design & Experience/React Native 게임 최적화 (JSI Hermes).md", + "UI_UX_Assets/Design & Experience/React Performance Optimization.md", + "UI_UX_Assets/Design & Experience/React 컴포넌트 Props 검증.md", + "UI_UX_Assets/Design & Experience/Redstone Engineering.md", + "UI_UX_Assets/Design & Experience/Redux 등 상태 관리 (State Management).md", + "UI_UX_Assets/Design & Experience/Redux 스타일 리듀서 및 액션 관리.md", + "UI_UX_Assets/Design & Experience/Redux-Reducers.md", + "UI_UX_Assets/Design & Experience/Redux-Toolkit-Architecture.md", + "UI_UX_Assets/Design & Experience/Reinforcement Learning Reward Shaping.md", + "UI_UX_Assets/Design & Experience/Roguelike Subgenre.md", + "UI_UX_Assets/Design & Experience/SeL4-Microkernel.md", + "UI_UX_Assets/Design & Experience/Self-Determination Theory.md", + "UI_UX_Assets/Design & Experience/Self-Determination-Theory.md", + "UI_UX_Assets/Design & Experience/Service-Design.md", + "UI_UX_Assets/Design & Experience/SimCity-Series.md", + "UI_UX_Assets/Design & Experience/Single-Responsibility-Principle.md", + "UI_UX_Assets/Design & Experience/Single-Source-of-Truth-Principle.md", + "UI_UX_Assets/Design & Experience/Smithsonian-Digital-Repository.md", + "UI_UX_Assets/Design & Experience/Snyk Open Source.md", + "UI_UX_Assets/Design & Experience/Social Learning Theory.md", + "UI_UX_Assets/Design & Experience/Socially Assistive Robotics (SAR).md", + "UI_UX_Assets/Design & Experience/Software Architecture API Contract Design.md", + "UI_UX_Assets/Design & Experience/Software-Contract-Enforcement.md", + "UI_UX_Assets/Design & Experience/Software-Product-Management.md", + "UI_UX_Assets/Design & Experience/Spatial Cognition.md", + "UI_UX_Assets/Design & Experience/Spatial Computing.md", + "UI_UX_Assets/Design & Experience/State-Machine-Implementation.md", + "UI_UX_Assets/Design & Experience/Static Type Checking Systems.md", + "UI_UX_Assets/Design & Experience/Static-Program-Analysis.md", + "UI_UX_Assets/Design & Experience/Structural Type System.md", + "UI_UX_Assets/Design & Experience/Structural-Subtyping.md", + "UI_UX_Assets/Design & Experience/Structural-Type-System.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-Analysis.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-and-Compatibility.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-Compatibility.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-Mechanics.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-Mechanisms.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-System.md", + "UI_UX_Assets/Design & Experience/Structural-Typing-vs-Nominal-Typing.md", + "UI_UX_Assets/Design & Experience/Structural-Typing.md", + "UI_UX_Assets/Design & Experience/Structural-vs-Nominal-Typing-in-TS.md", + "UI_UX_Assets/Design & Experience/Structural-vs-Nominal-Typing.md", + "UI_UX_Assets/Design & Experience/Subtyping-and-Variance.md", + "UI_UX_Assets/Design & Experience/Subtyping-Relations.md", + "UI_UX_Assets/Design & Experience/Subtyping-Rules.md", + "UI_UX_Assets/Design & Experience/Systemic Design.md", + "UI_UX_Assets/Design & Experience/Systemic Game Design.md", + "UI_UX_Assets/Design & Experience/Systemic-Design.md", + "UI_UX_Assets/Design & Experience/Template-Literal-Types.md", + "UI_UX_Assets/Design & Experience/The Emergence Theory in Game Design.md", + "UI_UX_Assets/Design & Experience/The Last of Us (Resource Scarcity and Character Bond).md", + "UI_UX_Assets/Design & Experience/Topological-Sorting.md", + "UI_UX_Assets/Design & Experience/Touchpoint-Analysis.md", + "UI_UX_Assets/Design & Experience/Turborepo-Orchestration.md", + "UI_UX_Assets/Design & Experience/Type Alias.md", + "UI_UX_Assets/Design & Experience/Type Branding.md", + "UI_UX_Assets/Design & Experience/Type Declaration.md", + "UI_UX_Assets/Design & Experience/Type-Aware-Linting.md", + "UI_UX_Assets/Design & Experience/Type-Compatibility-and-Subtyping.md", + "UI_UX_Assets/Design & Experience/Type-Compatibility-Rules.md", + "UI_UX_Assets/Design & Experience/Type-Compatibility.md", + "UI_UX_Assets/Design & Experience/Type-Composition-via-Intersections.md", + "UI_UX_Assets/Design & Experience/Type-Driven-Development.md", + "UI_UX_Assets/Design & Experience/Type-Erasure-and-Runtime-Behavior.md", + "UI_UX_Assets/Design & Experience/Type-Guards-and-Narrowing.md", + "UI_UX_Assets/Design & Experience/Type-Narrowing.md", + "UI_UX_Assets/Design & Experience/Type-Safe-API-Design.md", + "UI_UX_Assets/Design & Experience/Type-Safety-and-Exhaustiveness-Checking.md", + "UI_UX_Assets/Design & Experience/Type-Safety.md", + "UI_UX_Assets/Design & Experience/Type-Variance-in-TypeScript.md", + "UI_UX_Assets/Design & Experience/TypeScript Compiler API.md", + "UI_UX_Assets/Design & Experience/TypeScript Type System (Interface Design).md", + "UI_UX_Assets/Design & Experience/TypeScript 라이브러리 타입 확장.md", + "UI_UX_Assets/Design & Experience/TypeScript 인터페이스 및 시스템 보호 아키텍처 설계.md", + "UI_UX_Assets/Design & Experience/TypeScript 컴파일러 캐싱 최적화.md", + "UI_UX_Assets/Design & Experience/TypeScript-Compiler-API-Design.md", + "UI_UX_Assets/Design & Experience/TypeScript-Compiler-API.md", + "UI_UX_Assets/Design & Experience/TypeScript-Compiler-Architecture.md", + "UI_UX_Assets/Design & Experience/TypeScript-Language-Service-API.md", + "UI_UX_Assets/Design & Experience/TypeScript-Project-References.md", + "UI_UX_Assets/Design & Experience/TypeScript의 안전한 인터페이스 설계.md", + "UI_UX_Assets/Design & Experience/TypeScript의 인터페이스 및 객체 타입 설계.md", + "UI_UX_Assets/Design & Experience/Unified-User-Experience.md", + "UI_UX_Assets/Design & Experience/Union-Types.md", + "UI_UX_Assets/Design & Experience/Urban-Morphology.md", + "UI_UX_Assets/Design & Experience/Urban-Planning-Simulations.md", + "UI_UX_Assets/Design & Experience/User Experience (UX) Design.md", + "UI_UX_Assets/Design & Experience/User Experience (UX) in Game Design.md", + "UI_UX_Assets/Design & Experience/User-Experience-Design.md", + "UI_UX_Assets/Design & Experience/UX-Gamification.md", + "UI_UX_Assets/Design & Experience/UX_UI in Interactive Media.md", + "UI_UX_Assets/Design & Experience/Variance (Covariance Contravariance Invariance).md", + "UI_UX_Assets/Design & Experience/Variance-(Covariance-Contravariance-Invariance).md", + "UI_UX_Assets/Design & Experience/Variance-Covariance-Contravariance.md", + "UI_UX_Assets/Design & Experience/Video Game Design.md", + "UI_UX_Assets/Design & Experience/Visual-Hierarchy-in-Game-Design.md", + "UI_UX_Assets/Design & Experience/Von Neumann-Morgenstern Axioms.md", + "UI_UX_Assets/Design & Experience/W3C-Semantic-Web-Standards.md", + "UI_UX_Assets/Design & Experience/Wayfinding-Design.md", + "UI_UX_Assets/Design & Experience/Width-and-Depth-Subtyping.md", + "UI_UX_Assets/Design & Experience/Zod-Runtime-Validation.md", + "UI_UX_Assets/Design & Experience/Zod-Schema-Validation.md", + "UI_UX_Assets/Design & Experience/가상 DOM (Virtual DOM).md", + "UI_UX_Assets/Design & Experience/계층형 아키텍처 (Layered Architecture).md", + "UI_UX_Assets/Design & Experience/고성능 실시간 상호작용 시스템을 위한 React 기반 게임 엔진 아키텍처.md", + "UI_UX_Assets/Design & Experience/교육 심리학에서의 보상 설계.md", + "UI_UX_Assets/Design & Experience/교육학의 모델링 전략.md", + "UI_UX_Assets/Design & Experience/뇌과학 기반 중독 재활 프로그램.md", + "UI_UX_Assets/Design & Experience/데이터 지향 설계 (Data-Oriented Design).md", + "UI_UX_Assets/Design & Experience/도메인 주도 설계 (DDD).md", + "UI_UX_Assets/Design & Experience/도메인 주도 설계(DDD).md", + "UI_UX_Assets/Design & Experience/도파민 보상 체계.md", + "UI_UX_Assets/Design & Experience/라이브러리 타입 선언 (dts) 확장.md", + "UI_UX_Assets/Design & Experience/마이크로 프론트엔드 (Micro Frontends).md", + "UI_UX_Assets/Design & Experience/맞춤형 개별화 학습 설계.md", + "UI_UX_Assets/Design & Experience/모바일 앱 및 웹 인터페이스 설계.md", + "UI_UX_Assets/Design & Experience/몰입감 (Presence).md", + "UI_UX_Assets/Design & Experience/바운디드 컨텍스트 (Bounded Context).md", + "UI_UX_Assets/Design & Experience/비동기 데이터 패칭 (Async Operations Pattern).md", + "UI_UX_Assets/Design & Experience/사용성 공학 (Usability Engineering).md", + "UI_UX_Assets/Design & Experience/사용자 경험 (UX) 디자인.md", + "UI_UX_Assets/Design & Experience/사용자 경험 (UX).md", + "UI_UX_Assets/Design & Experience/사용자 경험 디자인 (UX Design).md", + "UI_UX_Assets/Design & Experience/사회 인지 이론(Social Cognitive Theory).md", + "UI_UX_Assets/Design & Experience/상태 관리 최적화 (Zustand Valtio).md", + "UI_UX_Assets/Design & Experience/상태 관리(State Management).md", + "UI_UX_Assets/Design & Experience/상태 모델링 (State Modeling).md", + "UI_UX_Assets/Design & Experience/선언 병합(Declaration Merging).md", + "UI_UX_Assets/Design & Experience/아보(Bobo) 인형 실험.md", + "UI_UX_Assets/Design & Experience/응용 행동 분석(ABA)] [행동 경제학] [교육 심리학의 행동주의 모델.md", + "UI_UX_Assets/Design & Experience/인간 요인 공학 (Human Factors Engineering).md", + "UI_UX_Assets/Design & Experience/인지 부조화 이론.md", + "UI_UX_Assets/Design & Experience/인지 부하 이론(Cognitive Load Theory).md", + "UI_UX_Assets/Design & Experience/인지 심리학 (Cognitive Psychology).md", + "UI_UX_Assets/Design & Experience/인지 평가 이론 (Cognitive Evaluation Theory).md", + "UI_UX_Assets/Design & Experience/인터페이스 (Interface).md", + "UI_UX_Assets/Design & Experience/인터페이스 분리 원칙 (Interface Segregation Principle).md", + "UI_UX_Assets/Design & Experience/자기 효능감 (Self-Efficacy).md", + "UI_UX_Assets/Design & Experience/자기 효능감(Self-Efficacy).md", + "UI_UX_Assets/Design & Experience/자기조절학습(Self-Regulated Learning).md", + "UI_UX_Assets/Design & Experience/재조정 (Reconciliation).md", + "UI_UX_Assets/Design & Experience/조직 시민 행동 (OCB).md", + "UI_UX_Assets/Design & Experience/조직 행동론의 성과급 체계 분석.md", + "UI_UX_Assets/Design & Experience/중독 의학 및 정신 병리학.md", + "UI_UX_Assets/Design & Experience/중독 재활 프로그램.md", + "UI_UX_Assets/Design & Experience/철벽 수비대_ - TypeScript 타입 시스템 (인터페이스 설계).md", + "UI_UX_Assets/Design & Experience/치타 사람 이미지 프롬프트.md", + "UI_UX_Assets/Design & Experience/클린 아키텍처 (Clean Architecture).md", + "UI_UX_Assets/Design & Experience/클린 아키텍처(Clean Architecture).md", + "UI_UX_Assets/Design & Experience/타입 가드 (Type Guards).md", + "UI_UX_Assets/Design & Experience/타입 별칭 (Type Alias).md", + "UI_UX_Assets/Design & Experience/플레이어 경험 디자인 (Player Experience Design).md", + "UI_UX_Assets/Design & Experience/행동 치료 및 인지 행동 치료 (CBT).md", + "UI_UX_Assets/React Frontend Development.md", + "UX_Scenarios", + "UX_Scenarios/Skybound", + "UX_Scenarios/Skybound/04_Mechanics_Progression", + "UX_Scenarios/Skybound/04_Mechanics_Progression/Meta_Economy_Growth_Loop.md", + "UX_Scenarios/Systemic Modeling & Fun", + "UX_Scenarios/Systemic Modeling & Fun/Game Design Theory.md", + "Visual_Effects", + "Visual_Effects/Graphics", + "Visual_Effects/Graphics/3D_Gaussian_Splatting.md", + "Visual_Effects/Graphics/3D_Web_HMI.md", + "Visual_Effects/Graphics & Performance", + "Visual_Effects/Graphics & Performance/Agency-Narrative Integration.md", + "Visual_Effects/Graphics & Performance/Alpha Blending.md", + "Visual_Effects/Graphics & Performance/ANGLE (Almost Native Graphics Layer Engine).md", + "Visual_Effects/Graphics & Performance/ANGLE.md", + "Visual_Effects/Graphics & Performance/Apple-Human-Interface-Guidelines.md", + "Visual_Effects/Graphics & Performance/Augmented Reality (AR).md", + "Visual_Effects/Graphics & Performance/Augmented Reality Navigation Systems.md", + "Visual_Effects/Graphics & Performance/Autonomous Vehicle Perception.md", + "Visual_Effects/Graphics & Performance/Babylonjs.md", + "Visual_Effects/Graphics & Performance/BatchedMesh.md", + "Visual_Effects/Graphics & Performance/Behavioral Economics in Digital Ecosystems.md", + "Visual_Effects/Graphics & Performance/Behavioral Economics.md", + "Visual_Effects/Graphics & Performance/BIM 모델 렌더링.md", + "Visual_Effects/Graphics & Performance/BIM 모델 시뮬레이션.md", + "Visual_Effects/Graphics & Performance/Bio-mechanical-Modeling.md", + "Visual_Effects/Graphics & Performance/Bioregionalism.md", + "Visual_Effects/Graphics & Performance/Bounding Volume Hierarchy (BVH).md", + "Visual_Effects/Graphics & Performance/BufferAttribute.md", + "Visual_Effects/Graphics & Performance/Cel-Shading-Techniques.md", + "Visual_Effects/Graphics & Performance/Cellular Automata.md", + "Visual_Effects/Graphics & Performance/Cesium.md", + "Visual_Effects/Graphics & Performance/Chrome (Blink_Dawn).md", + "Visual_Effects/Graphics & Performance/Chromium WebGPU Implementation.md", + "Visual_Effects/Graphics & Performance/Cognitive Load Theory.md", + "Visual_Effects/Graphics & Performance/Cognitive-Load-Theory.md", + "Visual_Effects/Graphics & Performance/Collaborative Learning Environments.md", + "Visual_Effects/Graphics & Performance/Competitive Esports Ecosystems.md", + "Visual_Effects/Graphics & Performance/Computational Ecology.md", + "Visual_Effects/Graphics & Performance/Compute Shaders.md", + "Visual_Effects/Graphics & Performance/Computer-Vision-Synthesis.md", + "Visual_Effects/Graphics & Performance/Creative Process.md", + "Visual_Effects/Graphics & Performance/Critical-Play.md", + "Visual_Effects/Graphics & Performance/Cultural-Heritage-Informatics.md", + "Visual_Effects/Graphics & Performance/CyArk.md", + "Visual_Effects/Graphics & Performance/Cybertext Theory.md", + "Visual_Effects/Graphics & Performance/DBpedia.md", + "Visual_Effects/Graphics & Performance/Digital Sandbox Theory.md", + "Visual_Effects/Graphics & Performance/Digital Twin Visualization.md", + "Visual_Effects/Graphics & Performance/Direct3D.md", + "Visual_Effects/Graphics & Performance/Drama-Management-Systems.md", + "Visual_Effects/Graphics & Performance/Dual-Track-Agile.md", + "Visual_Effects/Graphics & Performance/Duolingo (Language Learning)] [Fitness Tracking Apps (Strava_Fitbit)] [EdTech Gamification] [FinTech Engagement Strategies.md", + "Visual_Effects/Graphics & Performance/Dynamic Assessment.md", + "Visual_Effects/Graphics & Performance/Dynamical Systems Theory.md", + "Visual_Effects/Graphics & Performance/Ecosystem-Modeling.md", + "Visual_Effects/Graphics & Performance/EdTech (Gamified Learning).md", + "Visual_Effects/Graphics & Performance/Educational-Gamification.md", + "Visual_Effects/Graphics & Performance/Embodied Cognition in Virtual Reality.md", + "Visual_Effects/Graphics & Performance/Employee Engagement Systems.md", + "Visual_Effects/Graphics & Performance/Epidemiological Forecasting.md", + "Visual_Effects/Graphics & Performance/Epidemiological Modeling.md", + "Visual_Effects/Graphics & Performance/Expressjs-Type-Extensions.md", + "Visual_Effects/Graphics & Performance/EXT_disjoint_timer_query.md", + "Visual_Effects/Graphics & Performance/Fill Rate.md", + "Visual_Effects/Graphics & Performance/Flow State Theory.md", + "Visual_Effects/Graphics & Performance/Formal-Grammar.md", + "Visual_Effects/Graphics & Performance/Formalism-vs-Structuralism.md", + "Visual_Effects/Graphics & Performance/Formalist Game Design.md", + "Visual_Effects/Graphics & Performance/Fragment Shading.md", + "Visual_Effects/Graphics & Performance/FXAA.md", + "Visual_Effects/Graphics & Performance/Game Studies (Academic Discipline).md", + "Visual_Effects/Graphics & Performance/Game Theory (Economics).md", + "Visual_Effects/Graphics & Performance/Game Theory and Market Equilibrium.md", + "Visual_Effects/Graphics & Performance/Game Theory.md", + "Visual_Effects/Graphics & Performance/Gamification-Design.md", + "Visual_Effects/Graphics & Performance/Garbage Collection.md", + "Visual_Effects/Graphics & Performance/GPU-driven Rendering.md", + "Visual_Effects/Graphics & Performance/GPURenderBundles.md", + "Visual_Effects/Graphics & Performance/Graph Theory in Level Design.md", + "Visual_Effects/Graphics & Performance/HTML5 Canvas.md", + "Visual_Effects/Graphics & Performance/Human-Centered Design.md", + "Visual_Effects/Graphics & Performance/Immersive Educational Simulations.md", + "Visual_Effects/Graphics & Performance/instancedArray.md", + "Visual_Effects/Graphics & Performance/InstancedMesh (드로우 콜 최적화).md", + "Visual_Effects/Graphics & Performance/Instructional Systems Design (ISD).md", + "Visual_Effects/Graphics & Performance/Instructional-Design.md", + "Visual_Effects/Graphics & Performance/Interactive Storytelling.md", + "Visual_Effects/Graphics & Performance/Interactive-Storytelling.md", + "Visual_Effects/Graphics & Performance/Internet of Things (IoT) Telemetry.md", + "Visual_Effects/Graphics & Performance/Intrinsic Motivation.md", + "Visual_Effects/Graphics & Performance/ISO 9241 Standards.md", + "Visual_Effects/Graphics & Performance/JavaScript.md", + "Visual_Effects/Graphics & Performance/Knowledge-Graphs.md", + "Visual_Effects/Graphics & Performance/Looking-Glass-Studios.md", + "Visual_Effects/Graphics & Performance/Loot Box Regulation (EU_China Compliance).md", + "Visual_Effects/Graphics & Performance/Ludology.md", + "Visual_Effects/Graphics & Performance/Markov Decision Process (MDP).md", + "Visual_Effects/Graphics & Performance/Markov Decision Processes.md", + "Visual_Effects/Graphics & Performance/Mathematical Game Theory.md", + "Visual_Effects/Graphics & Performance/MDA Framework.md", + "Visual_Effects/Graphics & Performance/MDA-Framework.md", + "Visual_Effects/Graphics & Performance/Measure Theory.md", + "Visual_Effects/Graphics & Performance/Memory Leaks.md", + "Visual_Effects/Graphics & Performance/MeshStandardMaterial 조명 연산.md", + "Visual_Effects/Graphics & Performance/Meta Quest_Horizon OS.md", + "Visual_Effects/Graphics & Performance/Metal.md", + "Visual_Effects/Graphics & Performance/Metaverse Architecture.md", + "Visual_Effects/Graphics & Performance/Micro-latency.md", + "Visual_Effects/Graphics & Performance/Minecraft.md", + "Visual_Effects/Graphics & Performance/Minecraft_ Education Edition.md", + "Visual_Effects/Graphics & Performance/Mobile Gaming Monetization Strategies.md", + "Visual_Effects/Graphics & Performance/Narrative-Branching-Models.md", + "Visual_Effects/Graphics & Performance/Narratology.md", + "Visual_Effects/Graphics & Performance/NASA-Jet-Propulsion-Laboratory-Software-Standards.md", + "Visual_Effects/Graphics & Performance/Needle Engine.md", + "Visual_Effects/Graphics & Performance/NVIDIA Omniverse.md", + "Visual_Effects/Graphics & Performance/Object Pooling.md", + "Visual_Effects/Graphics & Performance/OffscreenCanvas 기반 멀티스레드 렌더링 구현.md", + "Visual_Effects/Graphics & Performance/OffscreenCanvas.md", + "Visual_Effects/Graphics & Performance/Open Metaverse Framework.md", + "Visual_Effects/Graphics & Performance/Open-World Design Paradigms.md", + "Visual_Effects/Graphics & Performance/OpenGL ES 20.md", + "Visual_Effects/Graphics & Performance/Operant Conditioning.md", + "Visual_Effects/Graphics & Performance/Perlin Noise.md", + "Visual_Effects/Graphics & Performance/Physics Engine Integration.md", + "Visual_Effects/Graphics & Performance/Positive Psychology.md", + "Visual_Effects/Graphics & Performance/Positive-Psychology.md", + "Visual_Effects/Graphics & Performance/Post-Acute-Care-Models.md", + "Visual_Effects/Graphics & Performance/Post-humanism.md", + "Visual_Effects/Graphics & Performance/Problem-Solving-Theory.md", + "Visual_Effects/Graphics & Performance/Procedural-Animation.md", + "Visual_Effects/Graphics & Performance/R3F 3D 게임 환경의 메모리 관리.md", + "Visual_Effects/Graphics & Performance/Radix Sort.md", + "Visual_Effects/Graphics & Performance/RDF와 OWL.md", + "Visual_Effects/Graphics & Performance/React Three Fiber (R3F).md", + "Visual_Effects/Graphics & Performance/React 기반 게임 엔진 아키텍처.md", + "Visual_Effects/Graphics & Performance/React 동시성 기능 (Concurrent Features).md", + "Visual_Effects/Graphics & Performance/Redux-Reducer-Pattern.md", + "Visual_Effects/Graphics & Performance/Revit glTF Export.md", + "Visual_Effects/Graphics & Performance/Revit 모델 렌더링.md", + "Visual_Effects/Graphics & Performance/Robotics-Control-Systems.md", + "Visual_Effects/Graphics & Performance/Role-Playing-Games (RPGs).md", + "Visual_Effects/Graphics & Performance/Rowhammer attack.md", + "Visual_Effects/Graphics & Performance/Rowhammer.md", + "Visual_Effects/Graphics & Performance/SaaS-Retention-Strategies.md", + "Visual_Effects/Graphics & Performance/Sandbox-Simulation.md", + "Visual_Effects/Graphics & Performance/Search-Based Procedural Content Generation (SBPCG).md", + "Visual_Effects/Graphics & Performance/Semantic Versioning (SemVer) in Type Safety.md", + "Visual_Effects/Graphics & Performance/Semantic-Web-Technologies.md", + "Visual_Effects/Graphics & Performance/Semantic-Web.md", + "Visual_Effects/Graphics & Performance/Semiotics in Media.md", + "Visual_Effects/Graphics & Performance/Sensor Fusion.md", + "Visual_Effects/Graphics & Performance/Service-Dominant-Logic.md", + "Visual_Effects/Graphics & Performance/SharedArrayBuffer.md", + "Visual_Effects/Graphics & Performance/Simulations of Social Systems.md", + "Visual_Effects/Graphics & Performance/Simultaneous Localization and Mapping (SLAM).md", + "Visual_Effects/Graphics & Performance/Skybound Protocol 기술 메뉴얼 및 개발자 가이드.md", + "Visual_Effects/Graphics & Performance/SLA-Definition.md", + "Visual_Effects/Graphics & Performance/Smart City Digital Twins.md", + "Visual_Effects/Graphics & Performance/Smart-City-Frameworks.md", + "Visual_Effects/Graphics & Performance/Sorting.md", + "Visual_Effects/Graphics & Performance/Special Education Interventions.md", + "Visual_Effects/Graphics & Performance/Speculative Biology.md", + "Visual_Effects/Graphics & Performance/Surgical-Robotics.md", + "Visual_Effects/Graphics & Performance/Systemic-Design-Frameworks.md", + "Visual_Effects/Graphics & Performance/Systems Theory.md", + "Visual_Effects/Graphics & Performance/Temporal-Logic.md", + "Visual_Effects/Graphics & Performance/Texture Compression.md", + "Visual_Effects/Graphics & Performance/The Rapture Setting.md", + "Visual_Effects/Graphics & Performance/The-Space-Syntax-Laboratory.md", + "Visual_Effects/Graphics & Performance/Three Shader Language (TSL).md", + "Visual_Effects/Graphics & Performance/Three.js 렌더링 최적화.md", + "Visual_Effects/Graphics & Performance/threejs Issue _30352.md", + "Visual_Effects/Graphics & Performance/Threejs 대규모 렌더링 최적화 파이프라인.md", + "Visual_Effects/Graphics & Performance/Threejs 렌더링 성능 최적화.md", + "Visual_Effects/Graphics & Performance/Threejs 렌더링 최적화.md", + "Visual_Effects/Graphics & Performance/Threejs 모바일 렌더링 최적화.md", + "Visual_Effects/Graphics & Performance/Threejs 자원 해제 (Dispose).md", + "Visual_Effects/Graphics & Performance/Timestamp Quantization.md", + "Visual_Effects/Graphics & Performance/Timestamp Queries Quantization.md", + "Visual_Effects/Graphics & Performance/TLB design.md", + "Visual_Effects/Graphics & Performance/TSL (Three Shader Language).md", + "Visual_Effects/Graphics & Performance/Turtle-Graphics.md", + "Visual_Effects/Graphics & Performance/TypedArray.md", + "Visual_Effects/Graphics & Performance/Urban-Resilience-Planning.md", + "Visual_Effects/Graphics & Performance/USD - Universal Scene Description.md", + "Visual_Effects/Graphics & Performance/User-Story-Mapping.md", + "Visual_Effects/Graphics & Performance/Utsubo.md", + "Visual_Effects/Graphics & Performance/UV Offset.md", + "Visual_Effects/Graphics & Performance/UX Design Gamification.md", + "Visual_Effects/Graphics & Performance/UX-Design-Architecture.md", + "Visual_Effects/Graphics & Performance/Varying Variables.md", + "Visual_Effects/Graphics & Performance/Vertex Shader.md", + "Visual_Effects/Graphics & Performance/VIA-Classification.md", + "Visual_Effects/Graphics & Performance/Virtual Reality (VR) Storytelling.md", + "Visual_Effects/Graphics & Performance/Voxel-based Rendering.md", + "Visual_Effects/Graphics & Performance/Vulkan.md", + "Visual_Effects/Graphics & Performance/Waves of Connection.md", + "Visual_Effects/Graphics & Performance/WebGLRenderingContext.md", + "Visual_Effects/Graphics & Performance/WebGPU Timestamp Queries.md", + "Visual_Effects/Graphics & Performance/WebGPU 대규모 건설 뷰어.md", + "Visual_Effects/Graphics & Performance/Winning Ways for your Mathematical Plays.md", + "Visual_Effects/Graphics & Performance/XState-Library.md", + "Visual_Effects/Graphics & Performance/고성능 3D WebGL 게임 렌더링 엔진.md", + "Visual_Effects/Graphics & Performance/고성능 멀티스레드 React 앱 아키텍처.md", + "Visual_Effects/Graphics & Performance/교육 심리학 및 교수법 설계.md", + "Visual_Effects/Graphics & Performance/기업 문화 진단 및 개선.md", + "Visual_Effects/Graphics & Performance/대규모 건설 뷰어(Construction Viewers).md", + "Visual_Effects/Graphics & Performance/대규모 건축물 및 지형 뷰어(BIM).md", + "Visual_Effects/Graphics & Performance/마이크로 프론트엔드.md", + "Visual_Effects/Graphics & Performance/만성 질환 행동 수정 개입.md", + "Visual_Effects/Graphics & Performance/명령형 직접 조작 (Imperative Manipulation).md", + "Visual_Effects/Graphics & Performance/모바일 기반 WebGL 애플리케이션 개발.md", + "Visual_Effects/Graphics & Performance/브라우저 그래픽 렌더링 백엔드.md", + "Visual_Effects/Graphics & Performance/서비스 디자인 (Service Design).md", + "Visual_Effects/Graphics & Performance/셰이더 정밀도 (Mediump_Highp).md", + "Visual_Effects/Graphics & Performance/스토리지 텍스처(Storage Textures).md", + "Visual_Effects/Graphics & Performance/실시간 렌더링 파이프라인.md", + "Visual_Effects/Graphics & Performance/실시간 물리 시뮬레이션 동기화.md", + "Visual_Effects/Graphics & Performance/웹 브라우저 그래픽 API 호환성.md", + "Visual_Effects/Graphics & Performance/조직 행동론의 직무 몰입 연구.md", + "Visual_Effects/Graphics & Performance/컴퓨트 셰이더(Compute Shaders).md", + "Visual_Effects/Graphics & Performance/프래그먼트 바운드(Fragment-bound).md", + "Visual_Effects/Graphics & Performance/프래그먼트 셰이딩(Fragment Shading).md", + "Visual_Effects/Graphics & Performance/헤드 마운트 디스플레이(HMD).md", + "Visual_Effects/Graphics & Performance/헤드마운트 디스플레이 (HMD).md", + "Visual_Effects/애니메이션 (transition - keyframes).md", + "4X 전략.md", + "Actionable Health Intelligence.md", + "Agent Harness.md", + "Agent Loop (에이전트 루프).md", + "Agent-Based Modeling.md", + "Agent_State_Store.md", + "AGI (Artificial General Intelligence).md", + "Agile_and_Team_Collaboration.md", + "AI 안전 (AI Safety).md", + "AI 에이전트 (AI Agents).md", + "AI 이미지 생성 워크플로우 (AI Image Generation Workflow).md", + "AI 이미지 생성 파이프라인.md", + "Albion Online (Full LootPlayer-Driven Production).md", + "Algorithmic Mechanism Design.md", + "Algorithmic Rhetoric.md", + "Alliance (동맹).md", + "Amygdala Hyperactivity.md", + "ARG-Alternate-Reality-Games.md", + "Arkane Studios.md", + "Auction Theory.md", + "Blog_Content_Rules.md", + "Blog_Title_Rules.md", + "CFG Scale.md", + "Character Reference.md", + "Chrome DevTools 및 메모리 프로파일링.md", + "CI-CD 파이프라인 (CI-CD Pipeline).md", + "CIPOMDPs.md", + "Clinical-grade Wearables (임상 등급 웨어러블).md", + "CNN.md", + "Cocktail-Party-Effect.md", + "Cognitive-Bias.md", + "Context API.md", + "Context Engineering.md", + "Context-Integration.md", + "Contextual AI Chatbot.md", + "Continuous Glucose Monitoring (CGM).md", + "Continuous Glucose Monitors (CGM).md", + "Conversational-Maxims.md", + "DALL-E 3의 자연어 기반 최적화.md", + "Data Twins in Healthcare.md", + "E2LLM.md", + "Edge Computing.md", + "Elite-Athletic-Development.md", + "Engineering_Principles.md", + "Executive-Dysfunction.md", + "Fact_Based_Meeting_Minutes_Prompt.md", + "FemTech (여성 건강 기술).md", + "FemTech Wearables.md", + "Flak Tank.md", + "FlashAttention.md", + "Game of War- Fire Age BM 구조.md", + "Global-Neuronal-Workspace.md", + "GPU-Memory-Hierarchy.md", + "Hearables (Health Earbuds).md", + "Hybrid-AI-Architectures.md", + "Inductive Reasoning.md", + "Inpainting & Outpainting.md", + "Jamba-and-Bamba.md", + "Legacy_React_Migration.md", + "Lifetime Value (LTV).md", + "LTV (Lifetime Value).md", + "Mamba.md", + "March 2026 Research Drop.md", + "MCP (Model Context Protocol).md", + "Metaverse Aesthetics.md", + "Midjourney V6 및 V7 기반의 이미지 생성 워크플로우.md", + "Midjourney V7 Draft Mode.md", + "Midjourney V7 및 V6 워크플로우.md", + "Midjourney V7의 Draft Mode 워크플로우.md", + "Midjourney 브랜드 캠페인 및 무드보드 제작.md", + "Motion-Capture-Retargeting.md", + "Nextjs_and_Modern_React_Patterns.md", + "Omni Reference (--oref).md", + "Omni Reference.md", + "On-Device AI - Wearable AI.md", + "Pay-to-win.md", + "Performance_and_Memory_Management.md", + "Permanent Loss.md", + "PEV_Loop.md", + "Positive Prompt.md", + "Pragmatics.md", + "Predictive AI Algorithms.md", + "Prefrontal-Cortex.md", + "Prompt Engineering.md", + "Prompt Structure.md", + "Prompt Weighting.md", + "React 18 Concurrent Features.md", + "Real User Monitoring (RUM).md", + "Roguelike Procedural Generation.md", + "S2-Attn.md", + "Selective-SSM.md", + "Skybound_Asset_Purity_Sync.md", + "Smart Glasses & Spatial Computing.md", + "Smart Rings.md", + "Soft-Prompt-Compression.md", + "SSM.md", + "Stable Diffusion Image Optimization.md", + "Stable Diffusion 오픈소스 제어.md", + "Stable Diffusion의 가중치 제어 문법.md", + "Street Duel Fighter.md", + "Theta-Gamma-Coupling.md", + "Token-Embedding.md", + "Triton-and-CuTe.md", + "Unified Health Data APIs.md", + "Wearables API - IoT Devices.md", + "가중치 부여(Prompt Weighting).md", + "긍정 프롬프트 (Positive Prompt).md", + "네거티브 프롬프트 (Negative Prompts).md", + "네거티브 프롬프트(Negative Prompt).md", + "디지털 치료제 (Digital Therapeutics, DTx).md", + "디퓨전 모델 (Diffusion Models).md", + "매몰 비용 오류 (Sunk Cost Fallacy).md", + "미드저니 V7 드래프트 모드 및 옴니 참조 워크플로우.md", + "미드저니 V7 및 드래프트 모드 워크플로우.md", + "미드저니 V7 업데이트 및 시각적 워크플로우.md", + "미드저니(Midjourney) 에디터 기능.md", + "베이지안 추론 (Bayesian Inference).md", + "보상의 역효과 (Overjustification Effect).md", + "부정 프롬프트(Negative Prompt).md", + "스타일 참조(Style Reference, --sref).md", + "스테이블 디퓨전 CFG Scale 및 가중치 제어.md", + "스테이블 디퓨전(Stable Diffusion) 이미지 생성 최적화.md", + "신경망 기초 (Neural Networks).md", + "안정적 디퓨전 이미지 최적화 (Stable Diffusion Image Optimization).md", + "얼라이언스 (Alliance).md", + "오픈소스 기반 맞춤형 AI 이미지 생성 및 하드웨어 수준의 정밀 통제 워크플로우.md", + "온디바이스 AI (On-device AI - Edge Computing).md", + "인문학적 게임 비평 및 서사학.md", + "인지 행동 치료 (CBT).md", + "자연어 프롬프트 (Natural Language Prompt).md", + "자연어 프롬프트(Natural Language Prompt).md", + "지도 학습 (Supervised Learning).md", + "캐릭터 참조 (Character Reference).md", + "캐릭터 참조(Character Reference).md", + "컨트롤넷 (ControlNet).md", + "컨트롤넷(ControlNet).md", + "파워 크립 (Power Creep).md", + "펨테크 예측 분석 (Predictive Analytics in FemTech).md", + "풀 리퀘스트 (Pull Request).md", + "프롬프트 가중치 (Prompt Weighting).md", + "프롬프트 가중치(Prompt Weighting).md", + "프롬프트 엔지니어링(Prompt Engineering).md", + "플랫폼 저항성(Platform Resistance).md", + "확산 모델 (Diffusion Models).md" + ], + "expandedFileItems": [], + "expandedLinkItems": [], + "folderSort": 0, + "fileSort": 3, + "linkSort": 3, + "linkFilter": { + "filterString": "", + "matchCase": false + }, + "ignoredFolders": [], + "consolidateLinks": false +} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/broken-links/main.js b/10_Wiki/Topics/.obsidian/plugins/broken-links/main.js new file mode 100644 index 00000000..f115dc7c --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/broken-links/main.js @@ -0,0 +1,8782 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ROLLUP +if you want to view the source visit the plugins github repository +*/ + +'use strict'; + +var obsidian = require('obsidian'); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +/** @returns {void} */ +function noop() {} + +function run(fn) { + return fn(); +} + +function blank_object() { + return Object.create(null); +} + +/** + * @param {Function[]} fns + * @returns {void} + */ +function run_all(fns) { + fns.forEach(run); +} + +/** + * @param {any} thing + * @returns {thing is Function} + */ +function is_function(thing) { + return typeof thing === 'function'; +} + +/** @returns {boolean} */ +function safe_not_equal(a, b) { + return a != a ? b == b : a !== b || (a && typeof a === 'object') || typeof a === 'function'; +} + +/** @returns {boolean} */ +function is_empty(obj) { + return Object.keys(obj).length === 0; +} + +/** + * @param {Node} target + * @param {Node} node + * @returns {void} + */ +function append(target, node) { + target.appendChild(node); +} + +/** + * @param {Node} target + * @param {Node} node + * @param {Node} [anchor] + * @returns {void} + */ +function insert$1(target, node, anchor) { + target.insertBefore(node, anchor || null); +} + +/** + * @param {Node} node + * @returns {void} + */ +function detach(node) { + if (node.parentNode) { + node.parentNode.removeChild(node); + } +} + +/** + * @returns {void} */ +function destroy_each(iterations, detaching) { + for (let i = 0; i < iterations.length; i += 1) { + if (iterations[i]) iterations[i].d(detaching); + } +} + +/** + * @template {keyof HTMLElementTagNameMap} K + * @param {K} name + * @returns {HTMLElementTagNameMap[K]} + */ +function element(name) { + return document.createElement(name); +} + +/** + * @param {string} data + * @returns {Text} + */ +function text(data) { + return document.createTextNode(data); +} + +/** + * @returns {Text} */ +function space() { + return text(' '); +} + +/** + * @returns {Text} */ +function empty() { + return text(''); +} + +/** + * @param {EventTarget} node + * @param {string} event + * @param {EventListenerOrEventListenerObject} handler + * @param {boolean | AddEventListenerOptions | EventListenerOptions} [options] + * @returns {() => void} + */ +function listen(node, event, handler, options) { + node.addEventListener(event, handler, options); + return () => node.removeEventListener(event, handler, options); +} + +/** + * @param {Element} node + * @param {string} attribute + * @param {string} [value] + * @returns {void} + */ +function attr(node, attribute, value) { + if (value == null) node.removeAttribute(attribute); + else if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value); +} + +/** + * @param {Element} element + * @returns {ChildNode[]} + */ +function children(element) { + return Array.from(element.childNodes); +} + +/** + * @param {Text} text + * @param {unknown} data + * @returns {void} + */ +function set_data(text, data) { + data = '' + data; + if (text.data === data) return; + text.data = /** @type {string} */ (data); +} + +/** + * @returns {void} */ +function set_input_value(input, value) { + input.value = value == null ? '' : value; +} + +/** + * @returns {void} */ +function toggle_class(element, name, toggle) { + // The `!!` is required because an `undefined` flag means flipping the current state. + element.classList.toggle(name, !!toggle); +} + +/** + * @typedef {Node & { + * claim_order?: number; + * hydrate_init?: true; + * actual_end_child?: NodeEx; + * childNodes: NodeListOf; + * }} NodeEx + */ + +/** @typedef {ChildNode & NodeEx} ChildNodeEx */ + +/** @typedef {NodeEx & { claim_order: number }} NodeEx2 */ + +/** + * @typedef {ChildNodeEx[] & { + * claim_info?: { + * last_index: number; + * total_claimed: number; + * }; + * }} ChildNodeArray + */ + +let current_component; + +/** @returns {void} */ +function set_current_component(component) { + current_component = component; +} + +function get_current_component() { + if (!current_component) throw new Error('Function called outside component initialization'); + return current_component; +} + +/** + * Schedules a callback to run immediately before the component is updated after any state change. + * + * The first time the callback runs will be before the initial `onMount` + * + * https://svelte.dev/docs/svelte#beforeupdate + * @param {() => any} fn + * @returns {void} + */ +function beforeUpdate(fn) { + get_current_component().$$.before_update.push(fn); +} + +/** + * Schedules a callback to run immediately after the component has been updated. + * + * The first time the callback runs will be after the initial `onMount` + * + * https://svelte.dev/docs/svelte#afterupdate + * @param {() => any} fn + * @returns {void} + */ +function afterUpdate(fn) { + get_current_component().$$.after_update.push(fn); +} + +const dirty_components = []; +const binding_callbacks = []; + +let render_callbacks = []; + +const flush_callbacks = []; + +const resolved_promise = /* @__PURE__ */ Promise.resolve(); + +let update_scheduled = false; + +/** @returns {void} */ +function schedule_update() { + if (!update_scheduled) { + update_scheduled = true; + resolved_promise.then(flush); + } +} + +/** @returns {void} */ +function add_render_callback(fn) { + render_callbacks.push(fn); +} + +// flush() calls callbacks in this order: +// 1. All beforeUpdate callbacks, in order: parents before children +// 2. All bind:this callbacks, in reverse order: children before parents. +// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT +// for afterUpdates called during the initial onMount, which are called in +// reverse order: children before parents. +// Since callbacks might update component values, which could trigger another +// call to flush(), the following steps guard against this: +// 1. During beforeUpdate, any updated components will be added to the +// dirty_components array and will cause a reentrant call to flush(). Because +// the flush index is kept outside the function, the reentrant call will pick +// up where the earlier call left off and go through all dirty components. The +// current_component value is saved and restored so that the reentrant call will +// not interfere with the "parent" flush() call. +// 2. bind:this callbacks cannot trigger new flush() calls. +// 3. During afterUpdate, any updated components will NOT have their afterUpdate +// callback called a second time; the seen_callbacks set, outside the flush() +// function, guarantees this behavior. +const seen_callbacks = new Set(); + +let flushidx = 0; // Do *not* move this inside the flush() function + +/** @returns {void} */ +function flush() { + // Do not reenter flush while dirty components are updated, as this can + // result in an infinite loop. Instead, let the inner flush handle it. + // Reentrancy is ok afterwards for bindings etc. + if (flushidx !== 0) { + return; + } + const saved_component = current_component; + do { + // first, call beforeUpdate functions + // and update components + try { + while (flushidx < dirty_components.length) { + const component = dirty_components[flushidx]; + flushidx++; + set_current_component(component); + update(component.$$); + } + } catch (e) { + // reset dirty state to not end up in a deadlocked state and then rethrow + dirty_components.length = 0; + flushidx = 0; + throw e; + } + set_current_component(null); + dirty_components.length = 0; + flushidx = 0; + while (binding_callbacks.length) binding_callbacks.pop()(); + // then, once components are updated, call + // afterUpdate functions. This may cause + // subsequent updates... + for (let i = 0; i < render_callbacks.length; i += 1) { + const callback = render_callbacks[i]; + if (!seen_callbacks.has(callback)) { + // ...so guard against infinite loops + seen_callbacks.add(callback); + callback(); + } + } + render_callbacks.length = 0; + } while (dirty_components.length); + while (flush_callbacks.length) { + flush_callbacks.pop()(); + } + update_scheduled = false; + seen_callbacks.clear(); + set_current_component(saved_component); +} + +/** @returns {void} */ +function update($$) { + if ($$.fragment !== null) { + $$.update(); + run_all($$.before_update); + const dirty = $$.dirty; + $$.dirty = [-1]; + $$.fragment && $$.fragment.p($$.ctx, dirty); + $$.after_update.forEach(add_render_callback); + } +} + +/** + * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`. + * @param {Function[]} fns + * @returns {void} + */ +function flush_render_callbacks(fns) { + const filtered = []; + const targets = []; + render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c))); + targets.forEach((c) => c()); + render_callbacks = filtered; +} + +const outroing = new Set(); + +/** + * @type {Outro} + */ +let outros; + +/** + * @returns {void} */ +function group_outros() { + outros = { + r: 0, + c: [], + p: outros // parent group + }; +} + +/** + * @returns {void} */ +function check_outros() { + if (!outros.r) { + run_all(outros.c); + } + outros = outros.p; +} + +/** + * @param {import('./private.js').Fragment} block + * @param {0 | 1} [local] + * @returns {void} + */ +function transition_in(block, local) { + if (block && block.i) { + outroing.delete(block); + block.i(local); + } +} + +/** + * @param {import('./private.js').Fragment} block + * @param {0 | 1} local + * @param {0 | 1} [detach] + * @param {() => void} [callback] + * @returns {void} + */ +function transition_out(block, local, detach, callback) { + if (block && block.o) { + if (outroing.has(block)) return; + outroing.add(block); + outros.c.push(() => { + outroing.delete(block); + if (callback) { + if (detach) block.d(1); + callback(); + } + }); + block.o(local); + } else if (callback) { + callback(); + } +} + +/** @typedef {1} INTRO */ +/** @typedef {0} OUTRO */ +/** @typedef {{ direction: 'in' | 'out' | 'both' }} TransitionOptions */ +/** @typedef {(node: Element, params: any, options: TransitionOptions) => import('../transition/public.js').TransitionConfig} TransitionFn */ + +/** + * @typedef {Object} Outro + * @property {number} r + * @property {Function[]} c + * @property {Object} p + */ + +/** + * @typedef {Object} PendingProgram + * @property {number} start + * @property {INTRO|OUTRO} b + * @property {Outro} [group] + */ + +/** + * @typedef {Object} Program + * @property {number} a + * @property {INTRO|OUTRO} b + * @property {1|-1} d + * @property {number} duration + * @property {number} start + * @property {number} end + * @property {Outro} [group] + */ + +// general each functions: + +function ensure_array_like(array_like_or_iterator) { + return array_like_or_iterator?.length !== undefined + ? array_like_or_iterator + : Array.from(array_like_or_iterator); +} + +/** @returns {void} */ +function create_component(block) { + block && block.c(); +} + +/** @returns {void} */ +function mount_component(component, target, anchor) { + const { fragment, after_update } = component.$$; + fragment && fragment.m(target, anchor); + // onMount happens before the initial afterUpdate + add_render_callback(() => { + const new_on_destroy = component.$$.on_mount.map(run).filter(is_function); + // if the component was destroyed immediately + // it will update the `$$.on_destroy` reference to `null`. + // the destructured on_destroy may still reference to the old array + if (component.$$.on_destroy) { + component.$$.on_destroy.push(...new_on_destroy); + } else { + // Edge case - component was destroyed immediately, + // most likely as a result of a binding initialising + run_all(new_on_destroy); + } + component.$$.on_mount = []; + }); + after_update.forEach(add_render_callback); +} + +/** @returns {void} */ +function destroy_component(component, detaching) { + const $$ = component.$$; + if ($$.fragment !== null) { + flush_render_callbacks($$.after_update); + run_all($$.on_destroy); + $$.fragment && $$.fragment.d(detaching); + // TODO null out other refs, including component.$$ (but need to + // preserve final state?) + $$.on_destroy = $$.fragment = null; + $$.ctx = []; + } +} + +/** @returns {void} */ +function make_dirty(component, i) { + if (component.$$.dirty[0] === -1) { + dirty_components.push(component); + schedule_update(); + component.$$.dirty.fill(0); + } + component.$$.dirty[(i / 31) | 0] |= 1 << i % 31; +} + +// TODO: Document the other params +/** + * @param {SvelteComponent} component + * @param {import('./public.js').ComponentConstructorOptions} options + * + * @param {import('./utils.js')['not_equal']} not_equal Used to compare props and state values. + * @param {(target: Element | ShadowRoot) => void} [append_styles] Function that appends styles to the DOM when the component is first initialised. + * This will be the `add_css` function from the compiled component. + * + * @returns {void} + */ +function init( + component, + options, + instance, + create_fragment, + not_equal, + props, + append_styles = null, + dirty = [-1] +) { + const parent_component = current_component; + set_current_component(component); + /** @type {import('./private.js').T$$} */ + const $$ = (component.$$ = { + fragment: null, + ctx: [], + // state + props, + update: noop, + not_equal, + bound: blank_object(), + // lifecycle + on_mount: [], + on_destroy: [], + on_disconnect: [], + before_update: [], + after_update: [], + context: new Map(options.context || (parent_component ? parent_component.$$.context : [])), + // everything else + callbacks: blank_object(), + dirty, + skip_bound: false, + root: options.target || parent_component.$$.root + }); + append_styles && append_styles($$.root); + let ready = false; + $$.ctx = instance + ? instance(component, options.props || {}, (i, ret, ...rest) => { + const value = rest.length ? rest[0] : ret; + if ($$.ctx && not_equal($$.ctx[i], ($$.ctx[i] = value))) { + if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value); + if (ready) make_dirty(component, i); + } + return ret; + }) + : []; + $$.update(); + ready = true; + run_all($$.before_update); + // `false` as a special case of no DOM component + $$.fragment = create_fragment ? create_fragment($$.ctx) : false; + if (options.target) { + if (options.hydrate) { + // TODO: what is the correct type here? + // @ts-expect-error + const nodes = children(options.target); + $$.fragment && $$.fragment.l(nodes); + nodes.forEach(detach); + } else { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + $$.fragment && $$.fragment.c(); + } + if (options.intro) transition_in(component.$$.fragment); + mount_component(component, options.target, options.anchor); + flush(); + } + set_current_component(parent_component); +} + +/** + * Base class for Svelte components. Used when dev=false. + * + * @template {Record} [Props=any] + * @template {Record} [Events=any] + */ +class SvelteComponent { + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * @type {any} + */ + $$ = undefined; + /** + * ### PRIVATE API + * + * Do not use, may change at any time + * + * @type {any} + */ + $$set = undefined; + + /** @returns {void} */ + $destroy() { + destroy_component(this, 1); + this.$destroy = noop; + } + + /** + * @template {Extract} K + * @param {K} type + * @param {((e: Events[K]) => void) | null | undefined} callback + * @returns {() => void} + */ + $on(type, callback) { + if (!is_function(callback)) { + return noop; + } + const callbacks = this.$$.callbacks[type] || (this.$$.callbacks[type] = []); + callbacks.push(callback); + return () => { + const index = callbacks.indexOf(callback); + if (index !== -1) callbacks.splice(index, 1); + }; + } + + /** + * @param {Partial} props + * @returns {void} + */ + $set(props) { + if (this.$$set && !is_empty(props)) { + this.$$.skip_bound = true; + this.$$set(props); + this.$$.skip_bound = false; + } + } +} + +/** + * @typedef {Object} CustomElementPropDefinition + * @property {string} [attribute] + * @property {boolean} [reflect] + * @property {'String'|'Boolean'|'Number'|'Array'|'Object'} [type] + */ + +// generated during release, do not modify +const PUBLIC_VERSION = '4'; + +if (typeof window !== 'undefined') + // @ts-ignore + (window.__svelte || (window.__svelte = { v: new Set() })).v.add(PUBLIC_VERSION); + +var LinkGrouping; +(function (LinkGrouping) { + LinkGrouping[LinkGrouping["ByFolder"] = 0] = "ByFolder"; + LinkGrouping[LinkGrouping["ByFile"] = 1] = "ByFile"; + LinkGrouping[LinkGrouping["ByLink"] = 2] = "ByLink"; +})(LinkGrouping || (LinkGrouping = {})); +var FolderSort; +(function (FolderSort) { + FolderSort[FolderSort["NameAsc"] = 0] = "NameAsc"; + FolderSort[FolderSort["NameDesc"] = 1] = "NameDesc"; +})(FolderSort || (FolderSort = {})); +var FileSort; +(function (FileSort) { + FileSort[FileSort["NameAsc"] = 0] = "NameAsc"; + FileSort[FileSort["NameDesc"] = 1] = "NameDesc"; + FileSort[FileSort["CountAsc"] = 2] = "CountAsc"; + FileSort[FileSort["CountDesc"] = 3] = "CountDesc"; +})(FileSort || (FileSort = {})); +var LinkSort; +(function (LinkSort) { + LinkSort[LinkSort["NameAsc"] = 0] = "NameAsc"; + LinkSort[LinkSort["NameDesc"] = 1] = "NameDesc"; + LinkSort[LinkSort["CountAsc"] = 2] = "CountAsc"; + LinkSort[LinkSort["CountDesc"] = 3] = "CountDesc"; +})(LinkSort || (LinkSort = {})); + +/* src/views/tree-item-file.svelte generated by Svelte v4.2.9 */ + +function get_each_context$4(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[10] = list[i]; + return child_ctx; +} + +// (29:8) {#each file.links as link} +function create_each_block$4(ctx) { + let div2; + let div1; + let div0; + let t0_value = /*link*/ ctx[10].id + ""; + let t0; + let t1; + let mounted; + let dispose; + + function click_handler_1(...args) { + return /*click_handler_1*/ ctx[7](/*link*/ ctx[10], ...args); + } + + function auxclick_handler(...args) { + return /*auxclick_handler*/ ctx[8](/*link*/ ctx[10], ...args); + } + + return { + c() { + div2 = element("div"); + div1 = element("div"); + div0 = element("div"); + t0 = text(t0_value); + t1 = space(); + attr(div0, "class", "tree-item-inner nav-link-title-content"); + attr(div1, "class", "tree-item-self is-clickable nav-link-title"); + attr(div2, "class", "tree-item nav-link"); + }, + m(target, anchor) { + insert$1(target, div2, anchor); + append(div2, div1); + append(div1, div0); + append(div0, t0); + append(div2, t1); + + if (!mounted) { + dispose = [ + listen(div1, "click", click_handler_1), + listen(div1, "auxclick", auxclick_handler) + ]; + + mounted = true; + } + }, + p(new_ctx, dirty) { + ctx = new_ctx; + if (dirty & /*file*/ 1 && t0_value !== (t0_value = /*link*/ ctx[10].id + "")) set_data(t0, t0_value); + }, + d(detaching) { + if (detaching) { + detach(div2); + } + + mounted = false; + run_all(dispose); + } + }; +} + +function create_fragment$4(ctx) { + let div6; + let div4; + let div0; + let t0; + let div1; + let t1; + let div2; + let t2_value = /*file*/ ctx[0].name + ""; + let t2; + let t3; + let div3; + let span; + let t4_value = /*file*/ ctx[0].links.length + ""; + let t4; + let t5; + let div5; + let div6_id_value; + let mounted; + let dispose; + let each_value = ensure_array_like(/*file*/ ctx[0].links); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block$4(get_each_context$4(ctx, each_value, i)); + } + + return { + c() { + div6 = element("div"); + div4 = element("div"); + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = text(t2_value); + t3 = space(); + div3 = element("div"); + span = element("span"); + t4 = text(t4_value); + t5 = space(); + div5 = element("div"); + + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + attr(div0, "class", "tree-item-icon collapse-icon nav-folder-collapse-indicator"); + attr(div0, "data-icon", "right-triangle"); + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[4]); + attr(div1, "class", "tree-item-icon"); + attr(div1, "data-icon", "file"); + attr(div2, "class", "tree-item-inner nav-file-title-content"); + attr(span, "class", "tree-item-flair"); + attr(div3, "class", "tree-item-flair-outer nav-file-link-count"); + attr(div4, "class", "tree-item-self is-clickable nav-file-title"); + attr(div5, "class", "tree-item-children nav-file-children"); + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[4]); + attr(div6, "id", div6_id_value = /*file*/ ctx[0].path); + attr(div6, "class", "tree-item nav-file"); + toggle_class(div6, "is-collapsed", /*isCollapsed*/ ctx[4]); + }, + m(target, anchor) { + insert$1(target, div6, anchor); + append(div6, div4); + append(div4, div0); + append(div4, t0); + append(div4, div1); + append(div4, t1); + append(div4, div2); + append(div2, t2); + append(div4, t3); + append(div4, div3); + append(div3, span); + append(span, t4); + append(div6, t5); + append(div6, div5); + + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div5, null); + } + } + + /*div6_binding*/ ctx[9](div6); + + if (!mounted) { + dispose = listen(div4, "click", /*click_handler*/ ctx[6]); + mounted = true; + } + }, + p(ctx, [dirty]) { + if (dirty & /*isCollapsed*/ 16) { + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[4]); + } + + if (dirty & /*file*/ 1 && t2_value !== (t2_value = /*file*/ ctx[0].name + "")) set_data(t2, t2_value); + if (dirty & /*file*/ 1 && t4_value !== (t4_value = /*file*/ ctx[0].links.length + "")) set_data(t4, t4_value); + + if (dirty & /*linkClicked, file*/ 5) { + each_value = ensure_array_like(/*file*/ ctx[0].links); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context$4(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + } else { + each_blocks[i] = create_each_block$4(child_ctx); + each_blocks[i].c(); + each_blocks[i].m(div5, null); + } + } + + for (; i < each_blocks.length; i += 1) { + each_blocks[i].d(1); + } + + each_blocks.length = each_value.length; + } + + if (dirty & /*isCollapsed*/ 16) { + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[4]); + } + + if (dirty & /*file*/ 1 && div6_id_value !== (div6_id_value = /*file*/ ctx[0].path)) { + attr(div6, "id", div6_id_value); + } + + if (dirty & /*isCollapsed*/ 16) { + toggle_class(div6, "is-collapsed", /*isCollapsed*/ ctx[4]); + } + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) { + detach(div6); + } + + destroy_each(each_blocks, detaching); + /*div6_binding*/ ctx[9](null); + mounted = false; + dispose(); + } + }; +} + +function instance$4($$self, $$props, $$invalidate) { + let { plugin } = $$props; + let { file } = $$props; + let { expandableItemClicked } = $$props; + let { linkClicked } = $$props; + let el; + + let isCollapsed = plugin.settings.groupBy == LinkGrouping.ByFolder + ? !plugin.settings.expandedFolderItems.contains(file.path) + : !plugin.settings.expandedFileItems.contains(file.path); + + afterUpdate(() => { + $$invalidate(4, isCollapsed = plugin.settings.groupBy == LinkGrouping.ByFolder + ? !plugin.settings.expandedFolderItems.contains(file.path) + : !plugin.settings.expandedFileItems.contains(file.path)); + }); + + const click_handler = e => expandableItemClicked(e, el); + + const click_handler_1 = (link, e) => { + linkClicked(e, link); + }; + + const auxclick_handler = (link, e) => { + linkClicked(e, link); + }; + + function div6_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + el = $$value; + $$invalidate(3, el); + }); + } + + $$self.$$set = $$props => { + if ('plugin' in $$props) $$invalidate(5, plugin = $$props.plugin); + if ('file' in $$props) $$invalidate(0, file = $$props.file); + if ('expandableItemClicked' in $$props) $$invalidate(1, expandableItemClicked = $$props.expandableItemClicked); + if ('linkClicked' in $$props) $$invalidate(2, linkClicked = $$props.linkClicked); + }; + + return [ + file, + expandableItemClicked, + linkClicked, + el, + isCollapsed, + plugin, + click_handler, + click_handler_1, + auxclick_handler, + div6_binding + ]; +} + +class Tree_item_file extends SvelteComponent { + constructor(options) { + super(); + + init(this, options, instance$4, create_fragment$4, safe_not_equal, { + plugin: 5, + file: 0, + expandableItemClicked: 1, + linkClicked: 2 + }); + } +} + +/* src/views/tree-item-folder.svelte generated by Svelte v4.2.9 */ + +function get_each_context$3(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[10] = list[i]; + return child_ctx; +} + +function get_each_context_1$1(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[13] = list[i]; + return child_ctx; +} + +// (30:8) {#each folder.folders as subfolder} +function create_each_block_1$1(ctx) { + let folder_1; + let current; + + folder_1 = new Tree_item_folder({ + props: { + plugin: /*plugin*/ ctx[0], + folder: /*subfolder*/ ctx[13], + linkClicked: /*linkClicked*/ ctx[4], + expandableItemClicked: /*expandableItemClicked*/ ctx[2], + folderContextClicked: /*folderContextClicked*/ ctx[3] + } + }); + + return { + c() { + create_component(folder_1.$$.fragment); + }, + m(target, anchor) { + mount_component(folder_1, target, anchor); + current = true; + }, + p(ctx, dirty) { + const folder_1_changes = {}; + if (dirty & /*plugin*/ 1) folder_1_changes.plugin = /*plugin*/ ctx[0]; + if (dirty & /*folder*/ 2) folder_1_changes.folder = /*subfolder*/ ctx[13]; + if (dirty & /*linkClicked*/ 16) folder_1_changes.linkClicked = /*linkClicked*/ ctx[4]; + if (dirty & /*expandableItemClicked*/ 4) folder_1_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[2]; + if (dirty & /*folderContextClicked*/ 8) folder_1_changes.folderContextClicked = /*folderContextClicked*/ ctx[3]; + folder_1.$set(folder_1_changes); + }, + i(local) { + if (current) return; + transition_in(folder_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(folder_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(folder_1, detaching); + } + }; +} + +// (33:8) {#each folder.files as file} +function create_each_block$3(ctx) { + let file_1; + let current; + + file_1 = new Tree_item_file({ + props: { + plugin: /*plugin*/ ctx[0], + file: /*file*/ ctx[10], + expandableItemClicked: /*expandableItemClicked*/ ctx[2], + linkClicked: /*linkClicked*/ ctx[4] + } + }); + + return { + c() { + create_component(file_1.$$.fragment); + }, + m(target, anchor) { + mount_component(file_1, target, anchor); + current = true; + }, + p(ctx, dirty) { + const file_1_changes = {}; + if (dirty & /*plugin*/ 1) file_1_changes.plugin = /*plugin*/ ctx[0]; + if (dirty & /*folder*/ 2) file_1_changes.file = /*file*/ ctx[10]; + if (dirty & /*expandableItemClicked*/ 4) file_1_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[2]; + if (dirty & /*linkClicked*/ 16) file_1_changes.linkClicked = /*linkClicked*/ ctx[4]; + file_1.$set(file_1_changes); + }, + i(local) { + if (current) return; + transition_in(file_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(file_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(file_1, detaching); + } + }; +} + +function create_fragment$3(ctx) { + let div6; + let div4; + let div0; + let t0; + let div1; + let t1; + let div2; + let t2_value = /*folder*/ ctx[1].name + ""; + let t2; + let t3; + let div3; + let span; + let t4_value = /*folder*/ ctx[1].linkCount + ""; + let t4; + let t5; + let div5; + let t6; + let div6_id_value; + let current; + let mounted; + let dispose; + let each_value_1 = ensure_array_like(/*folder*/ ctx[1].folders); + let each_blocks_1 = []; + + for (let i = 0; i < each_value_1.length; i += 1) { + each_blocks_1[i] = create_each_block_1$1(get_each_context_1$1(ctx, each_value_1, i)); + } + + const out = i => transition_out(each_blocks_1[i], 1, 1, () => { + each_blocks_1[i] = null; + }); + + let each_value = ensure_array_like(/*folder*/ ctx[1].files); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block$3(get_each_context$3(ctx, each_value, i)); + } + + const out_1 = i => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + + return { + c() { + div6 = element("div"); + div4 = element("div"); + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = text(t2_value); + t3 = space(); + div3 = element("div"); + span = element("span"); + t4 = text(t4_value); + t5 = space(); + div5 = element("div"); + + for (let i = 0; i < each_blocks_1.length; i += 1) { + each_blocks_1[i].c(); + } + + t6 = space(); + + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + attr(div0, "class", "tree-item-icon collapse-icon nav-folder-collapse-indicator"); + attr(div0, "data-icon", "right-triangle"); + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[6]); + attr(div1, "class", "tree-item-icon"); + attr(div1, "data-icon", "lucide-folder"); + attr(div2, "class", "tree-item-inner nav-folder-title-content"); + attr(span, "class", "tree-item-flair"); + attr(div3, "class", "tree-item-flair-outer nav-folder-link-count"); + attr(div4, "class", "tree-item-self is-clickable nav-folder-title"); + attr(div5, "class", "tree-item-children nav-folder-children"); + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[6]); + attr(div6, "id", div6_id_value = /*folder*/ ctx[1].path); + attr(div6, "class", "tree-item nav-folder"); + toggle_class(div6, "is-collapsed", /*isCollapsed*/ ctx[6]); + }, + m(target, anchor) { + insert$1(target, div6, anchor); + append(div6, div4); + append(div4, div0); + append(div4, t0); + append(div4, div1); + append(div4, t1); + append(div4, div2); + append(div2, t2); + append(div4, t3); + append(div4, div3); + append(div3, span); + append(span, t4); + append(div6, t5); + append(div6, div5); + + for (let i = 0; i < each_blocks_1.length; i += 1) { + if (each_blocks_1[i]) { + each_blocks_1[i].m(div5, null); + } + } + + append(div5, t6); + + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div5, null); + } + } + + /*div6_binding*/ ctx[9](div6); + current = true; + + if (!mounted) { + dispose = [ + listen(div4, "click", /*click_handler*/ ctx[7]), + listen(div4, "contextmenu", /*contextmenu_handler*/ ctx[8]) + ]; + + mounted = true; + } + }, + p(ctx, [dirty]) { + if (!current || dirty & /*isCollapsed*/ 64) { + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[6]); + } + + if ((!current || dirty & /*folder*/ 2) && t2_value !== (t2_value = /*folder*/ ctx[1].name + "")) set_data(t2, t2_value); + if ((!current || dirty & /*folder*/ 2) && t4_value !== (t4_value = /*folder*/ ctx[1].linkCount + "")) set_data(t4, t4_value); + + if (dirty & /*plugin, folder, linkClicked, expandableItemClicked, folderContextClicked*/ 31) { + each_value_1 = ensure_array_like(/*folder*/ ctx[1].folders); + let i; + + for (i = 0; i < each_value_1.length; i += 1) { + const child_ctx = get_each_context_1$1(ctx, each_value_1, i); + + if (each_blocks_1[i]) { + each_blocks_1[i].p(child_ctx, dirty); + transition_in(each_blocks_1[i], 1); + } else { + each_blocks_1[i] = create_each_block_1$1(child_ctx); + each_blocks_1[i].c(); + transition_in(each_blocks_1[i], 1); + each_blocks_1[i].m(div5, t6); + } + } + + group_outros(); + + for (i = each_value_1.length; i < each_blocks_1.length; i += 1) { + out(i); + } + + check_outros(); + } + + if (dirty & /*plugin, folder, expandableItemClicked, linkClicked*/ 23) { + each_value = ensure_array_like(/*folder*/ ctx[1].files); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context$3(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block$3(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(div5, null); + } + } + + group_outros(); + + for (i = each_value.length; i < each_blocks.length; i += 1) { + out_1(i); + } + + check_outros(); + } + + if (!current || dirty & /*isCollapsed*/ 64) { + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[6]); + } + + if (!current || dirty & /*folder*/ 2 && div6_id_value !== (div6_id_value = /*folder*/ ctx[1].path)) { + attr(div6, "id", div6_id_value); + } + + if (!current || dirty & /*isCollapsed*/ 64) { + toggle_class(div6, "is-collapsed", /*isCollapsed*/ ctx[6]); + } + }, + i(local) { + if (current) return; + + for (let i = 0; i < each_value_1.length; i += 1) { + transition_in(each_blocks_1[i]); + } + + for (let i = 0; i < each_value.length; i += 1) { + transition_in(each_blocks[i]); + } + + current = true; + }, + o(local) { + each_blocks_1 = each_blocks_1.filter(Boolean); + + for (let i = 0; i < each_blocks_1.length; i += 1) { + transition_out(each_blocks_1[i]); + } + + each_blocks = each_blocks.filter(Boolean); + + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + + current = false; + }, + d(detaching) { + if (detaching) { + detach(div6); + } + + destroy_each(each_blocks_1, detaching); + destroy_each(each_blocks, detaching); + /*div6_binding*/ ctx[9](null); + mounted = false; + run_all(dispose); + } + }; +} + +function instance$3($$self, $$props, $$invalidate) { + let { plugin } = $$props; + let { folder } = $$props; + let { expandableItemClicked } = $$props; + let { folderContextClicked } = $$props; + let { linkClicked } = $$props; + let el; + let isCollapsed = !plugin.settings.expandedFolderItems.contains(folder.path); + + afterUpdate(() => { + $$invalidate(6, isCollapsed = !plugin.settings.expandedFolderItems.contains(folder.path)); + }); + + const click_handler = e => expandableItemClicked(e, el); + const contextmenu_handler = e => folderContextClicked(e, el); + + function div6_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + el = $$value; + $$invalidate(5, el); + }); + } + + $$self.$$set = $$props => { + if ('plugin' in $$props) $$invalidate(0, plugin = $$props.plugin); + if ('folder' in $$props) $$invalidate(1, folder = $$props.folder); + if ('expandableItemClicked' in $$props) $$invalidate(2, expandableItemClicked = $$props.expandableItemClicked); + if ('folderContextClicked' in $$props) $$invalidate(3, folderContextClicked = $$props.folderContextClicked); + if ('linkClicked' in $$props) $$invalidate(4, linkClicked = $$props.linkClicked); + }; + + return [ + plugin, + folder, + expandableItemClicked, + folderContextClicked, + linkClicked, + el, + isCollapsed, + click_handler, + contextmenu_handler, + div6_binding + ]; +} + +class Tree_item_folder extends SvelteComponent { + constructor(options) { + super(); + + init(this, options, instance$3, create_fragment$3, safe_not_equal, { + plugin: 0, + folder: 1, + expandableItemClicked: 2, + folderContextClicked: 3, + linkClicked: 4 + }); + } +} + +/* src/views/tree-item-link-group.svelte generated by Svelte v4.2.9 */ + +function get_each_context$2(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[10] = list[i]; + return child_ctx; +} + +// (27:8) {#each linkGroup.links as link} +function create_each_block$2(ctx) { + let div2; + let div1; + let div0; + let t0_value = /*link*/ ctx[10].parent.name + ""; + let t0; + let t1; + let t2_value = /*link*/ ctx[10].position.start.line + 1 + ""; + let t2; + let t3; + let t4; + let mounted; + let dispose; + + function click_handler_1(...args) { + return /*click_handler_1*/ ctx[7](/*link*/ ctx[10], ...args); + } + + function auxclick_handler(...args) { + return /*auxclick_handler*/ ctx[8](/*link*/ ctx[10], ...args); + } + + return { + c() { + div2 = element("div"); + div1 = element("div"); + div0 = element("div"); + t0 = text(t0_value); + t1 = text(" (line: "); + t2 = text(t2_value); + t3 = text(")"); + t4 = space(); + attr(div0, "class", "tree-item-inner nav-link-title-content"); + attr(div1, "class", "tree-item-self is-clickable nav-link-title"); + attr(div2, "class", "tree-item nav-link"); + }, + m(target, anchor) { + insert$1(target, div2, anchor); + append(div2, div1); + append(div1, div0); + append(div0, t0); + append(div0, t1); + append(div0, t2); + append(div0, t3); + append(div2, t4); + + if (!mounted) { + dispose = [ + listen(div1, "click", click_handler_1), + listen(div1, "auxclick", auxclick_handler) + ]; + + mounted = true; + } + }, + p(new_ctx, dirty) { + ctx = new_ctx; + if (dirty & /*linkGroup*/ 1 && t0_value !== (t0_value = /*link*/ ctx[10].parent.name + "")) set_data(t0, t0_value); + if (dirty & /*linkGroup*/ 1 && t2_value !== (t2_value = /*link*/ ctx[10].position.start.line + 1 + "")) set_data(t2, t2_value); + }, + d(detaching) { + if (detaching) { + detach(div2); + } + + mounted = false; + run_all(dispose); + } + }; +} + +function create_fragment$2(ctx) { + let div6; + let div4; + let div0; + let t0; + let div1; + let t1; + let div2; + let t2_value = /*linkGroup*/ ctx[0].id + ""; + let t2; + let t3; + let div3; + let span; + let t4_value = /*linkGroup*/ ctx[0].links.length + ""; + let t4; + let t5; + let div5; + let div6_id_value; + let mounted; + let dispose; + let each_value = ensure_array_like(/*linkGroup*/ ctx[0].links); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block$2(get_each_context$2(ctx, each_value, i)); + } + + return { + c() { + div6 = element("div"); + div4 = element("div"); + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = text(t2_value); + t3 = space(); + div3 = element("div"); + span = element("span"); + t4 = text(t4_value); + t5 = space(); + div5 = element("div"); + + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + attr(div0, "class", "tree-item-icon collapse-icon nav-folder-collapse-indicator"); + attr(div0, "data-icon", "right-triangle"); + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[4]); + attr(div1, "class", "tree-item-icon"); + attr(div1, "data-icon", "lucide-link"); + attr(div2, "class", "tree-item-inner nav-file-title-content"); + attr(span, "class", "tree-item-flair"); + attr(div3, "class", "tree-item-flair-outer nav-file-link-count"); + attr(div4, "class", "tree-item-self is-clickable nav-file-title"); + attr(div5, "class", "tree-item-children nav-link-children"); + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[4]); + attr(div6, "id", div6_id_value = /*linkGroup*/ ctx[0].id); + attr(div6, "class", "tree-item nav-link-group"); + toggle_class(div6, "hidden", !/*linkGroup*/ ctx[0].show); + }, + m(target, anchor) { + insert$1(target, div6, anchor); + append(div6, div4); + append(div4, div0); + append(div4, t0); + append(div4, div1); + append(div4, t1); + append(div4, div2); + append(div2, t2); + append(div4, t3); + append(div4, div3); + append(div3, span); + append(span, t4); + append(div6, t5); + append(div6, div5); + + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div5, null); + } + } + + /*div6_binding*/ ctx[9](div6); + + if (!mounted) { + dispose = listen(div4, "click", /*click_handler*/ ctx[6]); + mounted = true; + } + }, + p(ctx, [dirty]) { + if (dirty & /*isCollapsed*/ 16) { + toggle_class(div0, "is-collapsed", /*isCollapsed*/ ctx[4]); + } + + if (dirty & /*linkGroup*/ 1 && t2_value !== (t2_value = /*linkGroup*/ ctx[0].id + "")) set_data(t2, t2_value); + if (dirty & /*linkGroup*/ 1 && t4_value !== (t4_value = /*linkGroup*/ ctx[0].links.length + "")) set_data(t4, t4_value); + + if (dirty & /*linkClicked, linkGroup*/ 5) { + each_value = ensure_array_like(/*linkGroup*/ ctx[0].links); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context$2(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + } else { + each_blocks[i] = create_each_block$2(child_ctx); + each_blocks[i].c(); + each_blocks[i].m(div5, null); + } + } + + for (; i < each_blocks.length; i += 1) { + each_blocks[i].d(1); + } + + each_blocks.length = each_value.length; + } + + if (dirty & /*isCollapsed*/ 16) { + toggle_class(div5, "hidden", /*isCollapsed*/ ctx[4]); + } + + if (dirty & /*linkGroup*/ 1 && div6_id_value !== (div6_id_value = /*linkGroup*/ ctx[0].id)) { + attr(div6, "id", div6_id_value); + } + + if (dirty & /*linkGroup*/ 1) { + toggle_class(div6, "hidden", !/*linkGroup*/ ctx[0].show); + } + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) { + detach(div6); + } + + destroy_each(each_blocks, detaching); + /*div6_binding*/ ctx[9](null); + mounted = false; + dispose(); + } + }; +} + +function instance$2($$self, $$props, $$invalidate) { + let { plugin } = $$props; + let { linkGroup } = $$props; + let { expandableItemClicked } = $$props; + let { linkClicked } = $$props; + let el; + let isCollapsed = !plugin.settings.expandedLinkItems.contains(linkGroup.id); + + afterUpdate(() => { + $$invalidate(4, isCollapsed = !plugin.settings.expandedLinkItems.contains(linkGroup.id)); + }); + + const click_handler = e => expandableItemClicked(e, el); + + const click_handler_1 = (link, e) => { + linkClicked(e, link); + }; + + const auxclick_handler = (link, e) => { + linkClicked(e, link); + }; + + function div6_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + el = $$value; + $$invalidate(3, el); + }); + } + + $$self.$$set = $$props => { + if ('plugin' in $$props) $$invalidate(5, plugin = $$props.plugin); + if ('linkGroup' in $$props) $$invalidate(0, linkGroup = $$props.linkGroup); + if ('expandableItemClicked' in $$props) $$invalidate(1, expandableItemClicked = $$props.expandableItemClicked); + if ('linkClicked' in $$props) $$invalidate(2, linkClicked = $$props.linkClicked); + }; + + return [ + linkGroup, + expandableItemClicked, + linkClicked, + el, + isCollapsed, + plugin, + click_handler, + click_handler_1, + auxclick_handler, + div6_binding + ]; +} + +class Tree_item_link_group extends SvelteComponent { + constructor(options) { + super(); + + init(this, options, instance$2, create_fragment$2, safe_not_equal, { + plugin: 5, + linkGroup: 0, + expandableItemClicked: 1, + linkClicked: 2 + }); + } +} + +/* src/views/broken-links-tree.svelte generated by Svelte v4.2.9 */ + +function get_each_context$1(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[25] = list[i]; + return child_ctx; +} + +function get_each_context_1(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[28] = list[i]; + return child_ctx; +} + +function get_each_context_2(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[28] = list[i]; + return child_ctx; +} + +function get_each_context_3(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[33] = list[i]; + return child_ctx; +} + +// (64:4) {#if groupBy == LinkGrouping.ByLink} +function create_if_block_3(ctx) { + let div3; + let div2; + let input; + let t0; + let div0; + let t1; + let div1; + let mounted; + let dispose; + + return { + c() { + div3 = element("div"); + div2 = element("div"); + input = element("input"); + t0 = space(); + div0 = element("div"); + t1 = space(); + div1 = element("div"); + attr(input, "type", "search"); + attr(input, "spellcheck", "false"); + attr(input, "placeholder", "Filter..."); + attr(div0, "class", "filter-input-clear-button"); + attr(div0, "aria-label", "Clear filter"); + attr(div1, "class", "input-right-decorator clickable-icon"); + attr(div1, "aria-label", "Match case"); + attr(div1, "data-icon", "uppercase-lowercase-a"); + toggle_class(div1, "is-active", /*linkFilter*/ ctx[0].matchCase); + attr(div2, "class", "filter-input-container"); + attr(div3, "class", "filter-row"); + }, + m(target, anchor) { + insert$1(target, div3, anchor); + append(div3, div2); + append(div2, input); + set_input_value(input, /*linkFilter*/ ctx[0].filterString); + append(div2, t0); + append(div2, div0); + append(div2, t1); + append(div2, div1); + + if (!mounted) { + dispose = [ + listen(input, "input", /*input_input_handler*/ ctx[17]), + listen(input, "input", /*input_handler*/ ctx[18]), + listen(div0, "click", /*click_handler_1*/ ctx[19]), + listen(div1, "click", /*click_handler_2*/ ctx[20]) + ]; + + mounted = true; + } + }, + p(ctx, dirty) { + if (dirty[0] & /*linkFilter*/ 1 && input.value !== /*linkFilter*/ ctx[0].filterString) { + set_input_value(input, /*linkFilter*/ ctx[0].filterString); + } + + if (dirty[0] & /*linkFilter*/ 1) { + toggle_class(div1, "is-active", /*linkFilter*/ ctx[0].matchCase); + } + }, + d(detaching) { + if (detaching) { + detach(div3); + } + + mounted = false; + run_all(dispose); + } + }; +} + +// (103:12) {#if groupBy == LinkGrouping.ByFolder} +function create_if_block_2(ctx) { + let t; + let each1_anchor; + let current; + let each_value_3 = ensure_array_like(/*brokenLinks*/ ctx[2].byFolder.folders); + let each_blocks_1 = []; + + for (let i = 0; i < each_value_3.length; i += 1) { + each_blocks_1[i] = create_each_block_3(get_each_context_3(ctx, each_value_3, i)); + } + + const out = i => transition_out(each_blocks_1[i], 1, 1, () => { + each_blocks_1[i] = null; + }); + + let each_value_2 = ensure_array_like(/*brokenLinks*/ ctx[2].byFolder.files); + let each_blocks = []; + + for (let i = 0; i < each_value_2.length; i += 1) { + each_blocks[i] = create_each_block_2(get_each_context_2(ctx, each_value_2, i)); + } + + const out_1 = i => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + + return { + c() { + for (let i = 0; i < each_blocks_1.length; i += 1) { + each_blocks_1[i].c(); + } + + t = space(); + + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + each1_anchor = empty(); + }, + m(target, anchor) { + for (let i = 0; i < each_blocks_1.length; i += 1) { + if (each_blocks_1[i]) { + each_blocks_1[i].m(target, anchor); + } + } + + insert$1(target, t, anchor); + + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(target, anchor); + } + } + + insert$1(target, each1_anchor, anchor); + current = true; + }, + p(ctx, dirty) { + if (dirty[0] & /*plugin, brokenLinks, linkClicked, expandableItemClicked, folderContextClicked*/ 1414) { + each_value_3 = ensure_array_like(/*brokenLinks*/ ctx[2].byFolder.folders); + let i; + + for (i = 0; i < each_value_3.length; i += 1) { + const child_ctx = get_each_context_3(ctx, each_value_3, i); + + if (each_blocks_1[i]) { + each_blocks_1[i].p(child_ctx, dirty); + transition_in(each_blocks_1[i], 1); + } else { + each_blocks_1[i] = create_each_block_3(child_ctx); + each_blocks_1[i].c(); + transition_in(each_blocks_1[i], 1); + each_blocks_1[i].m(t.parentNode, t); + } + } + + group_outros(); + + for (i = each_value_3.length; i < each_blocks_1.length; i += 1) { + out(i); + } + + check_outros(); + } + + if (dirty[0] & /*plugin, brokenLinks, expandableItemClicked, linkClicked*/ 1158) { + each_value_2 = ensure_array_like(/*brokenLinks*/ ctx[2].byFolder.files); + let i; + + for (i = 0; i < each_value_2.length; i += 1) { + const child_ctx = get_each_context_2(ctx, each_value_2, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block_2(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(each1_anchor.parentNode, each1_anchor); + } + } + + group_outros(); + + for (i = each_value_2.length; i < each_blocks.length; i += 1) { + out_1(i); + } + + check_outros(); + } + }, + i(local) { + if (current) return; + + for (let i = 0; i < each_value_3.length; i += 1) { + transition_in(each_blocks_1[i]); + } + + for (let i = 0; i < each_value_2.length; i += 1) { + transition_in(each_blocks[i]); + } + + current = true; + }, + o(local) { + each_blocks_1 = each_blocks_1.filter(Boolean); + + for (let i = 0; i < each_blocks_1.length; i += 1) { + transition_out(each_blocks_1[i]); + } + + each_blocks = each_blocks.filter(Boolean); + + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + + current = false; + }, + d(detaching) { + if (detaching) { + detach(t); + detach(each1_anchor); + } + + destroy_each(each_blocks_1, detaching); + destroy_each(each_blocks, detaching); + } + }; +} + +// (104:16) {#each brokenLinks.byFolder.folders as folder} +function create_each_block_3(ctx) { + let folder_1; + let current; + + folder_1 = new Tree_item_folder({ + props: { + plugin: /*plugin*/ ctx[1], + folder: /*folder*/ ctx[33], + linkClicked: /*linkClicked*/ ctx[10], + expandableItemClicked: /*expandableItemClicked*/ ctx[7], + folderContextClicked: /*folderContextClicked*/ ctx[8] + } + }); + + return { + c() { + create_component(folder_1.$$.fragment); + }, + m(target, anchor) { + mount_component(folder_1, target, anchor); + current = true; + }, + p(ctx, dirty) { + const folder_1_changes = {}; + if (dirty[0] & /*plugin*/ 2) folder_1_changes.plugin = /*plugin*/ ctx[1]; + if (dirty[0] & /*brokenLinks*/ 4) folder_1_changes.folder = /*folder*/ ctx[33]; + if (dirty[0] & /*linkClicked*/ 1024) folder_1_changes.linkClicked = /*linkClicked*/ ctx[10]; + if (dirty[0] & /*expandableItemClicked*/ 128) folder_1_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[7]; + if (dirty[0] & /*folderContextClicked*/ 256) folder_1_changes.folderContextClicked = /*folderContextClicked*/ ctx[8]; + folder_1.$set(folder_1_changes); + }, + i(local) { + if (current) return; + transition_in(folder_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(folder_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(folder_1, detaching); + } + }; +} + +// (107:16) {#each brokenLinks.byFolder.files as file} +function create_each_block_2(ctx) { + let file_1; + let current; + + file_1 = new Tree_item_file({ + props: { + plugin: /*plugin*/ ctx[1], + file: /*file*/ ctx[28], + expandableItemClicked: /*expandableItemClicked*/ ctx[7], + linkClicked: /*linkClicked*/ ctx[10] + } + }); + + return { + c() { + create_component(file_1.$$.fragment); + }, + m(target, anchor) { + mount_component(file_1, target, anchor); + current = true; + }, + p(ctx, dirty) { + const file_1_changes = {}; + if (dirty[0] & /*plugin*/ 2) file_1_changes.plugin = /*plugin*/ ctx[1]; + if (dirty[0] & /*brokenLinks*/ 4) file_1_changes.file = /*file*/ ctx[28]; + if (dirty[0] & /*expandableItemClicked*/ 128) file_1_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[7]; + if (dirty[0] & /*linkClicked*/ 1024) file_1_changes.linkClicked = /*linkClicked*/ ctx[10]; + file_1.$set(file_1_changes); + }, + i(local) { + if (current) return; + transition_in(file_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(file_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(file_1, detaching); + } + }; +} + +// (111:12) {#if groupBy == LinkGrouping.ByFile} +function create_if_block_1(ctx) { + let each_1_anchor; + let current; + let each_value_1 = ensure_array_like(/*brokenLinks*/ ctx[2].byFile); + let each_blocks = []; + + for (let i = 0; i < each_value_1.length; i += 1) { + each_blocks[i] = create_each_block_1(get_each_context_1(ctx, each_value_1, i)); + } + + const out = i => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + + return { + c() { + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + each_1_anchor = empty(); + }, + m(target, anchor) { + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(target, anchor); + } + } + + insert$1(target, each_1_anchor, anchor); + current = true; + }, + p(ctx, dirty) { + if (dirty[0] & /*plugin, brokenLinks, expandableItemClicked, linkClicked*/ 1158) { + each_value_1 = ensure_array_like(/*brokenLinks*/ ctx[2].byFile); + let i; + + for (i = 0; i < each_value_1.length; i += 1) { + const child_ctx = get_each_context_1(ctx, each_value_1, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block_1(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor); + } + } + + group_outros(); + + for (i = each_value_1.length; i < each_blocks.length; i += 1) { + out(i); + } + + check_outros(); + } + }, + i(local) { + if (current) return; + + for (let i = 0; i < each_value_1.length; i += 1) { + transition_in(each_blocks[i]); + } + + current = true; + }, + o(local) { + each_blocks = each_blocks.filter(Boolean); + + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + + current = false; + }, + d(detaching) { + if (detaching) { + detach(each_1_anchor); + } + + destroy_each(each_blocks, detaching); + } + }; +} + +// (112:16) {#each brokenLinks.byFile as file} +function create_each_block_1(ctx) { + let file_1; + let current; + + file_1 = new Tree_item_file({ + props: { + plugin: /*plugin*/ ctx[1], + file: /*file*/ ctx[28], + expandableItemClicked: /*expandableItemClicked*/ ctx[7], + linkClicked: /*linkClicked*/ ctx[10] + } + }); + + return { + c() { + create_component(file_1.$$.fragment); + }, + m(target, anchor) { + mount_component(file_1, target, anchor); + current = true; + }, + p(ctx, dirty) { + const file_1_changes = {}; + if (dirty[0] & /*plugin*/ 2) file_1_changes.plugin = /*plugin*/ ctx[1]; + if (dirty[0] & /*brokenLinks*/ 4) file_1_changes.file = /*file*/ ctx[28]; + if (dirty[0] & /*expandableItemClicked*/ 128) file_1_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[7]; + if (dirty[0] & /*linkClicked*/ 1024) file_1_changes.linkClicked = /*linkClicked*/ ctx[10]; + file_1.$set(file_1_changes); + }, + i(local) { + if (current) return; + transition_in(file_1.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(file_1.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(file_1, detaching); + } + }; +} + +// (116:12) {#if groupBy == LinkGrouping.ByLink} +function create_if_block(ctx) { + let each_1_anchor; + let current; + let each_value = ensure_array_like(/*brokenLinks*/ ctx[2].byLink); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block$1(get_each_context$1(ctx, each_value, i)); + } + + const out = i => transition_out(each_blocks[i], 1, 1, () => { + each_blocks[i] = null; + }); + + return { + c() { + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + each_1_anchor = empty(); + }, + m(target, anchor) { + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(target, anchor); + } + } + + insert$1(target, each_1_anchor, anchor); + current = true; + }, + p(ctx, dirty) { + if (dirty[0] & /*plugin, brokenLinks, expandableItemClicked, linkClicked*/ 1158) { + each_value = ensure_array_like(/*brokenLinks*/ ctx[2].byLink); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context$1(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + transition_in(each_blocks[i], 1); + } else { + each_blocks[i] = create_each_block$1(child_ctx); + each_blocks[i].c(); + transition_in(each_blocks[i], 1); + each_blocks[i].m(each_1_anchor.parentNode, each_1_anchor); + } + } + + group_outros(); + + for (i = each_value.length; i < each_blocks.length; i += 1) { + out(i); + } + + check_outros(); + } + }, + i(local) { + if (current) return; + + for (let i = 0; i < each_value.length; i += 1) { + transition_in(each_blocks[i]); + } + + current = true; + }, + o(local) { + each_blocks = each_blocks.filter(Boolean); + + for (let i = 0; i < each_blocks.length; i += 1) { + transition_out(each_blocks[i]); + } + + current = false; + }, + d(detaching) { + if (detaching) { + detach(each_1_anchor); + } + + destroy_each(each_blocks, detaching); + } + }; +} + +// (117:16) {#each brokenLinks.byLink as linkGroup} +function create_each_block$1(ctx) { + let linkgroup; + let current; + + linkgroup = new Tree_item_link_group({ + props: { + plugin: /*plugin*/ ctx[1], + linkGroup: /*linkGroup*/ ctx[25], + expandableItemClicked: /*expandableItemClicked*/ ctx[7], + linkClicked: /*linkClicked*/ ctx[10] + } + }); + + return { + c() { + create_component(linkgroup.$$.fragment); + }, + m(target, anchor) { + mount_component(linkgroup, target, anchor); + current = true; + }, + p(ctx, dirty) { + const linkgroup_changes = {}; + if (dirty[0] & /*plugin*/ 2) linkgroup_changes.plugin = /*plugin*/ ctx[1]; + if (dirty[0] & /*brokenLinks*/ 4) linkgroup_changes.linkGroup = /*linkGroup*/ ctx[25]; + if (dirty[0] & /*expandableItemClicked*/ 128) linkgroup_changes.expandableItemClicked = /*expandableItemClicked*/ ctx[7]; + if (dirty[0] & /*linkClicked*/ 1024) linkgroup_changes.linkClicked = /*linkClicked*/ ctx[10]; + linkgroup.$set(linkgroup_changes); + }, + i(local) { + if (current) return; + transition_in(linkgroup.$$.fragment, local); + current = true; + }, + o(local) { + transition_out(linkgroup.$$.fragment, local); + current = false; + }, + d(detaching) { + destroy_component(linkgroup, detaching); + } + }; +} + +function create_fragment$1(ctx) { + let div4; + let div3; + let div0; + let t0; + let div1; + let t1; + let div2; + let t2; + let t3; + let div7; + let div6; + let div5; + let t4; + let t5; + let current; + let mounted; + let dispose; + let if_block0 = /*groupBy*/ ctx[3] == LinkGrouping.ByLink && create_if_block_3(ctx); + let if_block1 = /*groupBy*/ ctx[3] == LinkGrouping.ByFolder && create_if_block_2(ctx); + let if_block2 = /*groupBy*/ ctx[3] == LinkGrouping.ByFile && create_if_block_1(ctx); + let if_block3 = /*groupBy*/ ctx[3] == LinkGrouping.ByLink && create_if_block(ctx); + + return { + c() { + div4 = element("div"); + div3 = element("div"); + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = space(); + if (if_block0) if_block0.c(); + t3 = space(); + div7 = element("div"); + div6 = element("div"); + div5 = element("div"); + if (if_block1) if_block1.c(); + t4 = space(); + if (if_block2) if_block2.c(); + t5 = space(); + if (if_block3) if_block3.c(); + attr(div0, "class", "clickable-icon nav-action-button"); + attr(div0, "aria-label", "Group by"); + attr(div0, "data-icon", "list"); + attr(div1, "class", "clickable-icon nav-action-button"); + attr(div1, "aria-label", "Change sort order"); + attr(div1, "data-icon", "lucide-sort-asc"); + attr(div2, "class", "clickable-icon nav-action-button"); + attr(div2, "aria-label", /*expandLabel*/ ctx[14]); + attr(div2, "data-icon", /*expandIcon*/ ctx[15]); + attr(div3, "class", "nav-buttons-container"); + attr(div4, "class", "nav-header"); + attr(div5, "class", "tree-item-children nav-folder-children"); + attr(div6, "class", "tree-item nav-folder mod-root"); + attr(div7, "class", "nav-files-container"); + }, + m(target, anchor) { + insert$1(target, div4, anchor); + append(div4, div3); + append(div3, div0); + append(div3, t0); + append(div3, div1); + append(div3, t1); + append(div3, div2); + append(div4, t2); + if (if_block0) if_block0.m(div4, null); + /*div4_binding*/ ctx[21](div4); + insert$1(target, t3, anchor); + insert$1(target, div7, anchor); + append(div7, div6); + append(div6, div5); + if (if_block1) if_block1.m(div5, null); + append(div5, t4); + if (if_block2) if_block2.m(div5, null); + append(div5, t5); + if (if_block3) if_block3.m(div5, null); + /*div5_binding*/ ctx[22](div5); + /*div7_binding*/ ctx[23](div7); + current = true; + + if (!mounted) { + dispose = [ + listen(div0, "click", function () { + if (is_function(/*groupByButtonClicked*/ ctx[4])) /*groupByButtonClicked*/ ctx[4].apply(this, arguments); + }), + listen(div1, "click", function () { + if (is_function(/*sortButtonClicked*/ ctx[5])) /*sortButtonClicked*/ ctx[5].apply(this, arguments); + }), + listen(div2, "click", /*click_handler*/ ctx[16]) + ]; + + mounted = true; + } + }, + p(new_ctx, dirty) { + ctx = new_ctx; + + if (!current || dirty[0] & /*expandLabel*/ 16384) { + attr(div2, "aria-label", /*expandLabel*/ ctx[14]); + } + + if (!current || dirty[0] & /*expandIcon*/ 32768) { + attr(div2, "data-icon", /*expandIcon*/ ctx[15]); + } + + if (/*groupBy*/ ctx[3] == LinkGrouping.ByLink) { + if (if_block0) { + if_block0.p(ctx, dirty); + } else { + if_block0 = create_if_block_3(ctx); + if_block0.c(); + if_block0.m(div4, null); + } + } else if (if_block0) { + if_block0.d(1); + if_block0 = null; + } + + if (/*groupBy*/ ctx[3] == LinkGrouping.ByFolder) { + if (if_block1) { + if_block1.p(ctx, dirty); + + if (dirty[0] & /*groupBy*/ 8) { + transition_in(if_block1, 1); + } + } else { + if_block1 = create_if_block_2(ctx); + if_block1.c(); + transition_in(if_block1, 1); + if_block1.m(div5, t4); + } + } else if (if_block1) { + group_outros(); + + transition_out(if_block1, 1, 1, () => { + if_block1 = null; + }); + + check_outros(); + } + + if (/*groupBy*/ ctx[3] == LinkGrouping.ByFile) { + if (if_block2) { + if_block2.p(ctx, dirty); + + if (dirty[0] & /*groupBy*/ 8) { + transition_in(if_block2, 1); + } + } else { + if_block2 = create_if_block_1(ctx); + if_block2.c(); + transition_in(if_block2, 1); + if_block2.m(div5, t5); + } + } else if (if_block2) { + group_outros(); + + transition_out(if_block2, 1, 1, () => { + if_block2 = null; + }); + + check_outros(); + } + + if (/*groupBy*/ ctx[3] == LinkGrouping.ByLink) { + if (if_block3) { + if_block3.p(ctx, dirty); + + if (dirty[0] & /*groupBy*/ 8) { + transition_in(if_block3, 1); + } + } else { + if_block3 = create_if_block(ctx); + if_block3.c(); + transition_in(if_block3, 1); + if_block3.m(div5, null); + } + } else if (if_block3) { + group_outros(); + + transition_out(if_block3, 1, 1, () => { + if_block3 = null; + }); + + check_outros(); + } + }, + i(local) { + if (current) return; + transition_in(if_block1); + transition_in(if_block2); + transition_in(if_block3); + current = true; + }, + o(local) { + transition_out(if_block1); + transition_out(if_block2); + transition_out(if_block3); + current = false; + }, + d(detaching) { + if (detaching) { + detach(div4); + detach(t3); + detach(div7); + } + + if (if_block0) if_block0.d(); + /*div4_binding*/ ctx[21](null); + if (if_block1) if_block1.d(); + if (if_block2) if_block2.d(); + if (if_block3) if_block3.d(); + /*div5_binding*/ ctx[22](null); + /*div7_binding*/ ctx[23](null); + mounted = false; + run_all(dispose); + } + }; +} + +function instance$1($$self, $$props, $$invalidate) { + let { plugin } = $$props; + let { brokenLinks } = $$props; + let { groupBy } = $$props; + let { linkFilter = { filterString: "", matchCase: false } } = $$props; + let { groupByButtonClicked } = $$props; + let { sortButtonClicked } = $$props; + let { expandButtonClicked } = $$props; + let { expandableItemClicked } = $$props; + let { folderContextClicked } = $$props; + let { updateLinkFilter } = $$props; + let { linkClicked } = $$props; + let header; + let container; + let children; + let expandLabel = "Expand all"; + let expandIcon = "chevrons-up-down"; + + beforeUpdate(() => { + let showExpand = true; + + if (plugin.settings.groupBy == LinkGrouping.ByFolder) { + showExpand = plugin.settings.expandedFolderItems.length == 0; + } else if (plugin.settings.groupBy == LinkGrouping.ByFile) { + showExpand = plugin.settings.expandedFileItems.length == 0; + } else if (plugin.settings.groupBy == LinkGrouping.ByLink) { + showExpand = plugin.settings.expandedLinkItems.length == 0; + } + + $$invalidate(14, expandLabel = showExpand ? "Expand all" : "Collapse all"); + $$invalidate(15, expandIcon = showExpand ? "chevrons-up-down" : "chevrons-down-up"); + }); + + afterUpdate(() => { + // Set icons after DOM has been updated + setIcons(); + }); + + function setIcons() { + header.querySelectorAll(".clickable-icon").forEach(el => { + var _a; + + return obsidian.setIcon(el, (_a = el.getAttr("data-icon")) !== null && _a !== void 0 + ? _a + : ""); + }); + + container.querySelectorAll(".tree-item-icon").forEach(el => { + var _a; + + return obsidian.setIcon(el, (_a = el.getAttr("data-icon")) !== null && _a !== void 0 + ? _a + : ""); + }); + } + + const click_handler = e => expandButtonClicked(e, children); + + function input_input_handler() { + linkFilter.filterString = this.value; + $$invalidate(0, linkFilter); + } + + const input_handler = () => updateLinkFilter(linkFilter.filterString, linkFilter.matchCase); + + const click_handler_1 = () => { + $$invalidate(0, linkFilter.filterString = "", linkFilter); + updateLinkFilter(linkFilter.filterString, linkFilter.matchCase); + }; + + const click_handler_2 = () => { + $$invalidate(0, linkFilter.matchCase = !linkFilter.matchCase, linkFilter); + updateLinkFilter(linkFilter.filterString, linkFilter.matchCase); + }; + + function div4_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + header = $$value; + $$invalidate(11, header); + }); + } + + function div5_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + children = $$value; + $$invalidate(13, children); + }); + } + + function div7_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + container = $$value; + $$invalidate(12, container); + }); + } + + $$self.$$set = $$props => { + if ('plugin' in $$props) $$invalidate(1, plugin = $$props.plugin); + if ('brokenLinks' in $$props) $$invalidate(2, brokenLinks = $$props.brokenLinks); + if ('groupBy' in $$props) $$invalidate(3, groupBy = $$props.groupBy); + if ('linkFilter' in $$props) $$invalidate(0, linkFilter = $$props.linkFilter); + if ('groupByButtonClicked' in $$props) $$invalidate(4, groupByButtonClicked = $$props.groupByButtonClicked); + if ('sortButtonClicked' in $$props) $$invalidate(5, sortButtonClicked = $$props.sortButtonClicked); + if ('expandButtonClicked' in $$props) $$invalidate(6, expandButtonClicked = $$props.expandButtonClicked); + if ('expandableItemClicked' in $$props) $$invalidate(7, expandableItemClicked = $$props.expandableItemClicked); + if ('folderContextClicked' in $$props) $$invalidate(8, folderContextClicked = $$props.folderContextClicked); + if ('updateLinkFilter' in $$props) $$invalidate(9, updateLinkFilter = $$props.updateLinkFilter); + if ('linkClicked' in $$props) $$invalidate(10, linkClicked = $$props.linkClicked); + }; + + return [ + linkFilter, + plugin, + brokenLinks, + groupBy, + groupByButtonClicked, + sortButtonClicked, + expandButtonClicked, + expandableItemClicked, + folderContextClicked, + updateLinkFilter, + linkClicked, + header, + container, + children, + expandLabel, + expandIcon, + click_handler, + input_input_handler, + input_handler, + click_handler_1, + click_handler_2, + div4_binding, + div5_binding, + div7_binding + ]; +} + +class Broken_links_tree extends SvelteComponent { + constructor(options) { + super(); + + init( + this, + options, + instance$1, + create_fragment$1, + safe_not_equal, + { + plugin: 1, + brokenLinks: 2, + groupBy: 3, + linkFilter: 0, + groupByButtonClicked: 4, + sortButtonClicked: 5, + expandButtonClicked: 6, + expandableItemClicked: 7, + folderContextClicked: 8, + updateLinkFilter: 9, + linkClicked: 10 + }, + null, + [-1, -1] + ); + } +} + +function getBrokenLinks(plugin) { + var _a, _b; + return __awaiter(this, void 0, void 0, function* () { + const links = { + byFolder: { + name: "root", + path: "/", + folders: [], + files: [], + linkCount: 0, + }, + byFile: [], + byLink: [], + }; + // Iterate all the files in the vault + for (const file of plugin.app.vault.getMarkdownFiles()) { + // Check ignored folder list + if (plugin.settings.ignoredFolders.find((folder) => { + return (file.parent && file.parent.path == "/" && folder == "/") || file.path.startsWith(folder + "/"); + })) { + continue; + } + // Use the cache to get determine if there are links in the file + const fileCache = plugin.app.metadataCache.getFileCache(file); + // Set up the FileModel now to be added to any broken links + const fileModel = { + name: file.name, + path: file.path, + created: file.stat.ctime, + modified: file.stat.mtime, + links: [], + }; + // Standard links + if (fileCache === null || fileCache === void 0 ? void 0 : fileCache.links) { + processLinks(fileCache.links, plugin, fileModel, links.byLink); + } + // Embedded links + if (fileCache === null || fileCache === void 0 ? void 0 : fileCache.embeds) { + // check embedded links + processLinks(fileCache.embeds, plugin, fileModel, links.byLink); + } + // Frontmatter links + if (fileCache === null || fileCache === void 0 ? void 0 : fileCache.frontmatterLinks) { + // check frontmatter links + processLinks(fileCache.frontmatterLinks, plugin, fileModel, links.byLink); + } + if (fileModel.links.length > 0) { + links.byFile.push(fileModel); + // Parse the path and build into the folder model + const pathParts = file.path.split("/"); + if (pathParts.length > 0) { + // Nest in folders collection + let parentFolder = null; + let folderPath = ""; + for (let i = 0; i < pathParts.length - 1; i++) { + const folderName = pathParts[i]; + folderPath = folderPath.length == 0 ? folderName : `${folderPath}/${folderName}`; + // If parentFolder is null, add it to the root, + // otherwise nest it into the parentFolder + if (parentFolder == null) { + // Look for existing folder or create + // a new one and set it as the parent + parentFolder = + (_a = links.byFolder.folders.find((f) => { + if (f.path == folderPath) + return f; + })) !== null && _a !== void 0 ? _a : null; + if (parentFolder != null) { + // Increment link count + parentFolder.linkCount++; + } + else { + // Add to root + parentFolder = { + name: folderName, + path: folderPath, + folders: [], + files: [], + linkCount: 1, // default to 1 + }; + links.byFolder.folders.push(parentFolder); + } + } + else { + // Look for existing child folder or create + // a new one and add it to the parent + let childFolder = (_b = parentFolder.folders.find((f) => { + if (f.path == folderPath) + return f; + })) !== null && _b !== void 0 ? _b : null; + if (childFolder != null) { + // Increment link count + childFolder.linkCount++; + } + else { + childFolder = { + name: folderName, + path: folderPath, + folders: [], + files: [], + linkCount: 1, // default to 1 + }; + parentFolder.folders.push(childFolder); + } + // Set the child folder as the parent and recurse + parentFolder = childFolder; + } + } + // If there is a parent folder, put the file in there + if (parentFolder != null) { + parentFolder.files.push(fileModel); + } + else { + // Otherwise, file is in the root + links.byFolder.files.push(fileModel); + } + } + } + } + // Sort folder tree + sortFolderTree(links.byFolder, plugin.settings.folderSort); + // Sort file tree + sortFileTree(links.byFile, plugin.settings.fileSort); + // Sort link tree & filter + sortLinkTree(links.byLink, plugin.settings.linkSort); + filterLinkTree(links.byLink, plugin.settings.linkFilter); + return links; + }); +} +function processLinks(links, plugin, fileModel, linkModels) { + for (const link of links) { + // Get link path + const linkPath = obsidian.getLinkpath(link.link); + // Check if the link goes anywhere + const dest = plugin.app.metadataCache.getFirstLinkpathDest(linkPath, fileModel.path); + // Default behavior is to mark link as broken if no destination is found + let destIsMissing = dest == null; + // If there is a destination file, check for missing blocks/headings + if (dest != null && link.link.contains("#")) { + const targetCache = plugin.app.metadataCache.getFileCache(dest); + if (link.link.contains("^") && (targetCache === null || targetCache === void 0 ? void 0 : targetCache.blocks)) { + const block = link.link.slice(link.link.indexOf("^") + 1).toLocaleLowerCase(); + destIsMissing = targetCache.blocks[block] == undefined; + } + else if (targetCache === null || targetCache === void 0 ? void 0 : targetCache.headings) { + const heading = link.link.slice(link.link.indexOf("#") + 1); + destIsMissing = + targetCache.headings.find((value) => { + if (obsidian.stripHeading(heading).toLocaleLowerCase() == obsidian.stripHeading(value.heading).toLocaleLowerCase()) { + return value; + } + return undefined; + }) == undefined; + } + } + if (destIsMissing) { + // Create model + const linkModel = { + id: link.link, + sortId: link.link.replace(/^#?\^?/, ""), + parent: fileModel, + fullText: link.original, + // Link may not have a position (in the case of a Frontmatter Link). + // Default to the top of the document (where frontmatter is anyway). + position: { + start: { line: 0, col: 0, offset: 0 }, + end: { line: 0, col: 0, offset: 0 }, + }, + }; + if ("position" in link) { + linkModel.position = link.position; + } + else if ("key" in link) { + linkModel.key = link.key; + } + if (!plugin.settings.consolidateLinks && link.displayText && link.displayText != link.link) { + linkModel.sortId += `|${link.displayText}`; + } + // Add the link to the file + fileModel.links.push(linkModel); + // Add to byLink list + let group = linkModels.find((g) => g.id == linkModel.sortId); + if (!group) { + group = { + id: linkModel.sortId, + show: true, + links: [], + }; + linkModels.push(group); + } + group.links.push(linkModel); + } + } +} +function sortFolderTree(folder, sort) { + // Sort folders A to Z + folder.folders = folder.folders.sort((a, b) => { + if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) + return -1; + else if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) + return 1; + else + return 0; + }); + // Sort files according to settings + folder.files = folder.files.sort((a, b) => { + let place = 0; + if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) + place = -1; + else if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) + place = 1; + if (sort == FolderSort.NameDesc) + place *= -1; + return place; + }); + // Sort links by position + folder.files.forEach((file) => { + file.links = file.links.sort((a, b) => { + if (a.position.start.offset < b.position.start.offset) + return -1; + else if (a.position.start.offset > b.position.start.offset) + return 1; + else + return 0; + }); + }); + // Recurse through subfolders + folder.folders.forEach((subfolder) => { + sortFolderTree(subfolder, sort); + }); +} +function sortFileTree(files, sort) { + // Sort files according to settings + const sorted = files.sort((a, b) => { + let place = 0; + if (sort == FileSort.NameAsc || sort == FileSort.NameDesc) { + if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) + place = -1; + else if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) + place = 1; + if (sort == FileSort.NameDesc) + place *= -1; + } + else if (sort == FileSort.CountAsc || sort == FileSort.CountDesc) { + if (a.links.length < b.links.length) + place = -1; + else if (a.links.length > b.links.length) + place = 1; + if (sort == FileSort.CountDesc) + place *= -1; + // For same link count, default to A to Z + if (a.links.length == b.links.length) { + if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) + place = -1; + else if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) + place = 1; + } + } + return place; + }); + // Sort links by position + sorted.forEach((file) => { + file.links = file.links.sort((a, b) => { + if (a.position.start.offset < b.position.start.offset) + return -1; + else if (a.position.start.offset > b.position.start.offset) + return 1; + else + return 0; + }); + }); + // Assign back to files + files = sorted; +} +function sortLinkTree(linkGroups, sort) { + // Sort links according to settings + const sorted = linkGroups.sort((a, b) => { + let place = 0; + if (sort == LinkSort.NameAsc || sort == LinkSort.NameDesc) { + if (a.id.toLocaleLowerCase() < b.id.toLocaleLowerCase()) + place = -1; + else if (a.id.toLocaleLowerCase() > b.id.toLocaleLowerCase()) + place = 1; + if (sort == LinkSort.NameDesc) + place *= -1; + } + else if (sort == LinkSort.CountAsc || sort == LinkSort.CountDesc) { + if (a.links.length < b.links.length) + place = -1; + else if (a.links.length > b.links.length) + place = 1; + if (sort == LinkSort.CountDesc) + place *= -1; + // For same link count, default to A to Z + if (a.links.length == b.links.length) { + if (a.id.toLocaleLowerCase() < b.id.toLocaleLowerCase()) + place = -1; + else if (a.id.toLocaleLowerCase() > b.id.toLocaleLowerCase()) + place = 1; + } + } + return place; + }); + // Sort files A to Z + for (let i = 0; i < sorted.length; i++) { + sorted[i].links = sorted[i].links.sort((a, b) => { + if (a.parent.name.toLocaleLowerCase() < b.parent.name.toLocaleLowerCase()) + return -1; + if (a.parent.name.toLocaleLowerCase() > b.parent.name.toLocaleLowerCase()) + return 1; + else + return 0; + }); + } + // Assign back to linkGroups + linkGroups = sorted; +} +function filterLinkTree(linkGroups, filter) { + for (const group of linkGroups) { + group.show = true; + // get the filter string as an array of each "word" + const words = filter.filterString.split(" ").filter((s) => s); + for (const word of words) { + if (filter.matchCase) { + if (!group.id.contains(word)) { + group.show = false; + } + } + else { + if (!group.id.toLocaleLowerCase().contains(word.toLocaleLowerCase())) { + group.show = false; + } + } + } + } +} + +const BROKEN_LINKS_VIEW_TYPE = "broken-links-view"; +class BrokenLinksView extends obsidian.ItemView { + constructor(leaf, plugin) { + super(leaf); + this.plugin = plugin; + } + getViewType() { + return BROKEN_LINKS_VIEW_TYPE; + } + getDisplayText() { + return "Broken links"; + } + getIcon() { + return "unlink"; + } + onOpen() { + return __awaiter(this, void 0, void 0, function* () { + this.brokenLinks = yield getBrokenLinks(this.plugin); + this.containerEl.empty(); + this.containerEl.addClass("broken-links"); + this.brokenLinksTree = new Broken_links_tree({ + target: this.containerEl, + props: { + plugin: this.plugin, + brokenLinks: this.brokenLinks, + groupBy: this.plugin.settings.groupBy, + linkFilter: this.plugin.settings.linkFilter, + groupByButtonClicked: this.groupByButtonClickedHandler.bind(this), + sortButtonClicked: this.sortButtonClickedHandler.bind(this), + expandButtonClicked: this.expandButtonClickedHandler.bind(this), + expandableItemClicked: this.expandableItemClickedHandler.bind(this), + folderContextClicked: this.folderContextClickedHandler.bind(this), + updateLinkFilter: this.updateLinkFilterHandler.bind(this), + linkClicked: this.linkClickedHandler.bind(this), + }, + }); + // Add callback to update the view when files get changed + this.registerEvent(this.app.metadataCache.on("resolved", this.updateView.bind(this))); + }); + } + onClose() { + return __awaiter(this, void 0, void 0, function* () { + this.brokenLinksTree.$destroy(); + }); + } + updateView(reloadLinks = true) { + return __awaiter(this, void 0, void 0, function* () { + if (reloadLinks) + this.brokenLinks = yield getBrokenLinks(this.plugin); + this.brokenLinksTree.$set({ + brokenLinks: this.brokenLinks, + }); + }); + } + groupByButtonClickedHandler(e) { + const menu = new obsidian.Menu(); + menu.addItem((item) => item + .setTitle("Group by folder") + .setIcon("lucide-folder") + .setChecked(this.plugin.settings.groupBy == LinkGrouping.ByFolder) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.groupBy != LinkGrouping.ByFolder) { + this.plugin.settings.groupBy = LinkGrouping.ByFolder; + this.brokenLinksTree.$set({ + groupBy: LinkGrouping.ByFolder, + }); + yield this.plugin.saveSettings(); + } + }))); + menu.addItem((item) => item + .setTitle("Group by file") + .setIcon("lucide-file") + .setChecked(this.plugin.settings.groupBy == LinkGrouping.ByFile) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.groupBy != LinkGrouping.ByFile) { + this.plugin.settings.groupBy = LinkGrouping.ByFile; + this.brokenLinksTree.$set({ + groupBy: LinkGrouping.ByFile, + }); + yield this.plugin.saveSettings(); + } + }))); + menu.addItem((item) => item + .setTitle("Group by link") + .setIcon("lucide-link") + .setChecked(this.plugin.settings.groupBy == LinkGrouping.ByLink) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.groupBy != LinkGrouping.ByLink) { + this.plugin.settings.groupBy = LinkGrouping.ByLink; + this.brokenLinksTree.$set({ + groupBy: LinkGrouping.ByLink, + }); + yield this.plugin.saveSettings(); + } + }))); + menu.showAtMouseEvent(e); + } + sortButtonClickedHandler(e) { + const menu = new obsidian.Menu(); + if (this.plugin.settings.groupBy == LinkGrouping.ByFolder) { + menu.addItem((item) => item + .setTitle("File name (A to Z)") + .setChecked(this.plugin.settings.folderSort == FolderSort.NameAsc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.folderSort != FolderSort.NameAsc) { + // Update settings + this.plugin.settings.folderSort = FolderSort.NameAsc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addItem((item) => item + .setTitle("File name (Z to A)") + .setChecked(this.plugin.settings.folderSort == FolderSort.NameDesc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.folderSort != FolderSort.NameDesc) { + // Update settings + this.plugin.settings.folderSort = FolderSort.NameDesc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.showAtMouseEvent(e); + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByFile) { + menu.addItem((item) => item + .setTitle("File name (A to Z)") + .setChecked(this.plugin.settings.fileSort == FileSort.NameAsc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.fileSort != FileSort.NameAsc) { + // Update settings + this.plugin.settings.fileSort = FileSort.NameAsc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addItem((item) => item + .setTitle("File name (Z to A)") + .setChecked(this.plugin.settings.fileSort == FileSort.NameDesc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.fileSort != FileSort.NameDesc) { + // Update settings + this.plugin.settings.fileSort = FileSort.NameDesc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addSeparator(); + menu.addItem((item) => item + .setTitle("Link count (fewest to most)") + .setChecked(this.plugin.settings.fileSort == FileSort.CountAsc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.fileSort != FileSort.CountAsc) { + // Update settings + this.plugin.settings.fileSort = FileSort.CountAsc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addItem((item) => item + .setTitle("Link count (most to fewest)") + .setChecked(this.plugin.settings.fileSort == FileSort.CountDesc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.fileSort != FileSort.CountDesc) { + // Update settings + this.plugin.settings.fileSort = FileSort.CountDesc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.showAtMouseEvent(e); + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByLink) { + menu.addItem((item) => item + .setTitle("File name (A to Z)") + .setChecked(this.plugin.settings.linkSort == LinkSort.NameAsc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.linkSort != LinkSort.NameAsc) { + // Update settings + this.plugin.settings.linkSort = LinkSort.NameAsc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addItem((item) => item + .setTitle("File name (Z to A)") + .setChecked(this.plugin.settings.linkSort == LinkSort.NameDesc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.linkSort != LinkSort.NameDesc) { + // Update settings + this.plugin.settings.linkSort = LinkSort.NameDesc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addSeparator(); + menu.addItem((item) => item + .setTitle("Link count (fewest to most)") + .setChecked(this.plugin.settings.linkSort == LinkSort.CountAsc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.linkSort != LinkSort.CountAsc) { + // Update settings + this.plugin.settings.linkSort = LinkSort.CountAsc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.addItem((item) => item + .setTitle("Link count (most to fewest)") + .setChecked(this.plugin.settings.linkSort == LinkSort.CountDesc) + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.linkSort != LinkSort.CountDesc) { + // Update settings + this.plugin.settings.linkSort = LinkSort.CountDesc; + yield this.plugin.saveSettings(); + // Refresh links list + yield this.updateView(); + } + }))); + menu.showAtMouseEvent(e); + } + } + expandButtonClickedHandler(e, el) { + return __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.groupBy == LinkGrouping.ByFolder) { + if (this.plugin.settings.expandedFolderItems.length == 0) { + el.querySelectorAll(".nav-folder, .nav-file").forEach((child) => { + this.plugin.settings.expandedFolderItems.push(child.id); + }); + } + else { + this.plugin.settings.expandedFolderItems = []; + } + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByFile) { + if (this.plugin.settings.expandedFileItems.length == 0) { + el.querySelectorAll(".nav-file").forEach((child) => { + this.plugin.settings.expandedFileItems.push(child.id); + }); + } + else { + this.plugin.settings.expandedFileItems = []; + } + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByLink) { + if (this.plugin.settings.expandedLinkItems.length == 0) { + el.querySelectorAll(".nav-link-group").forEach((child) => { + this.plugin.settings.expandedLinkItems.push(child.id); + }); + } + else { + this.plugin.settings.expandedLinkItems = []; + } + } + // Save settings + yield this.plugin.saveSettings(); + // Update broken links tree + yield this.updateView(false); + }); + } + expandableItemClickedHandler(e, el) { + return __awaiter(this, void 0, void 0, function* () { + if (this.plugin.settings.groupBy == LinkGrouping.ByFolder) { + if (this.plugin.settings.expandedFolderItems.contains(el.id)) { + this.plugin.settings.expandedFolderItems.remove(el.id); + } + else { + this.plugin.settings.expandedFolderItems.push(el.id); + } + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByFile) { + if (this.plugin.settings.expandedFileItems.contains(el.id)) { + this.plugin.settings.expandedFileItems.remove(el.id); + } + else { + this.plugin.settings.expandedFileItems.push(el.id); + } + } + else if (this.plugin.settings.groupBy == LinkGrouping.ByLink) { + if (this.plugin.settings.expandedLinkItems.contains(el.id)) { + this.plugin.settings.expandedLinkItems.remove(el.id); + } + else { + this.plugin.settings.expandedLinkItems.push(el.id); + } + } + // Save settings + yield this.plugin.saveSettings(); + // Update broken links tree + yield this.updateView(false); + }); + } + folderContextClickedHandler(e, el) { + return __awaiter(this, void 0, void 0, function* () { + const menu = new obsidian.Menu(); + menu.addItem((item) => { + item.setTitle("Expand all children") + .setIcon("chevrons-up-down") + .onClick(() => __awaiter(this, void 0, void 0, function* () { + // Expand selected item + this.plugin.settings.expandedFolderItems.push(el.id); + // Expand children + el.querySelectorAll(".nav-folder, .nav-file").forEach((child) => { + this.plugin.settings.expandedFolderItems.push(child.id); + }); + // Save settings + yield this.plugin.saveSettings(); + // Update broken links tree + yield this.updateView(false); + })); + }); + menu.addItem((item) => { + item.setTitle("Collapse all children") + .setIcon("chevrons-down-up") + .onClick(() => __awaiter(this, void 0, void 0, function* () { + // Collapse selected item + this.plugin.settings.expandedFolderItems.remove(el.id); + // Collapse children + el.querySelectorAll(".nav-folder, .nav-file").forEach((child) => { + this.plugin.settings.expandedFolderItems.remove(child.id); + }); + // Save settings + yield this.plugin.saveSettings(); + // Update broken links tree + yield this.updateView(false); + })); + }); + menu.showAtMouseEvent(e); + }); + } + updateLinkFilterHandler(filterString, matchCase) { + return __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.linkFilter.filterString = filterString; + this.plugin.settings.linkFilter.matchCase = matchCase; + yield this.plugin.saveSettings(); + filterLinkTree(this.brokenLinks.byLink, this.plugin.settings.linkFilter); + this.updateView(false); + }); + } + linkClickedHandler(e, link) { + return __awaiter(this, void 0, void 0, function* () { + if (!((e.instanceOf(MouseEvent) && e.button !== 0 && e.button !== 1) || e.defaultPrevented)) { + const file = this.app.vault.getAbstractFileByPath(link.parent.path); + if (file instanceof obsidian.TFile) { + const leaf = this.app.workspace.getLeaf(obsidian.Keymap.isModEvent(e)); + yield leaf.openFile(file); + // Scroll to section and highlight + if (leaf.view instanceof obsidian.MarkdownView) { + if (leaf.view.currentMode instanceof obsidian.MarkdownPreviewView) { + // @ts-ignore + const renderer = leaf.view.currentMode.renderer; // trust me, it's there + renderer.onRendered(() => { + renderer.applyScroll(link.position.start.line, { + center: true, + highlight: true, + }); + }); + } + else { + // Exclude frontmatter links for now + if (!link.key) { + // Update start/end col to highlight only the link text + const colStart = link.position.start.col + link.fullText.indexOf(link.id); + const colEnd = colStart + link.id.length; + leaf.view.editor.setSelection({ + line: link.position.start.line, + ch: colStart, + }, { + line: link.position.end.line, + ch: colEnd, + }); + leaf.view.editor.scrollIntoView({ + from: { line: link.position.start.line, ch: link.position.start.col }, + to: { line: link.position.end.line, ch: link.position.end.col }, + }, true); + } + } + } + } + } + }); + } +} + +var top = 'top'; +var bottom = 'bottom'; +var right = 'right'; +var left = 'left'; +var auto = 'auto'; +var basePlacements = [top, bottom, right, left]; +var start = 'start'; +var end = 'end'; +var clippingParents = 'clippingParents'; +var viewport = 'viewport'; +var popper = 'popper'; +var reference = 'reference'; +var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) { + return acc.concat([placement + "-" + start, placement + "-" + end]); +}, []); +var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) { + return acc.concat([placement, placement + "-" + start, placement + "-" + end]); +}, []); // modifiers that need to read the DOM + +var beforeRead = 'beforeRead'; +var read = 'read'; +var afterRead = 'afterRead'; // pure-logic modifiers + +var beforeMain = 'beforeMain'; +var main = 'main'; +var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state) + +var beforeWrite = 'beforeWrite'; +var write = 'write'; +var afterWrite = 'afterWrite'; +var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite]; + +function getNodeName(element) { + return element ? (element.nodeName || '').toLowerCase() : null; +} + +function getWindow(node) { + if (node == null) { + return window; + } + + if (node.toString() !== '[object Window]') { + var ownerDocument = node.ownerDocument; + return ownerDocument ? ownerDocument.defaultView || window : window; + } + + return node; +} + +function isElement(node) { + var OwnElement = getWindow(node).Element; + return node instanceof OwnElement || node instanceof Element; +} + +function isHTMLElement(node) { + var OwnElement = getWindow(node).HTMLElement; + return node instanceof OwnElement || node instanceof HTMLElement; +} + +function isShadowRoot(node) { + // IE 11 has no ShadowRoot + if (typeof ShadowRoot === 'undefined') { + return false; + } + + var OwnElement = getWindow(node).ShadowRoot; + return node instanceof OwnElement || node instanceof ShadowRoot; +} + +// and applies them to the HTMLElements such as popper and arrow + +function applyStyles(_ref) { + var state = _ref.state; + Object.keys(state.elements).forEach(function (name) { + var style = state.styles[name] || {}; + var attributes = state.attributes[name] || {}; + var element = state.elements[name]; // arrow is optional + virtual elements + + if (!isHTMLElement(element) || !getNodeName(element)) { + return; + } // Flow doesn't support to extend this property, but it's the most + // effective way to apply styles to an HTMLElement + // $FlowFixMe[cannot-write] + + + Object.assign(element.style, style); + Object.keys(attributes).forEach(function (name) { + var value = attributes[name]; + + if (value === false) { + element.removeAttribute(name); + } else { + element.setAttribute(name, value === true ? '' : value); + } + }); + }); +} + +function effect$2(_ref2) { + var state = _ref2.state; + var initialStyles = { + popper: { + position: state.options.strategy, + left: '0', + top: '0', + margin: '0' + }, + arrow: { + position: 'absolute' + }, + reference: {} + }; + Object.assign(state.elements.popper.style, initialStyles.popper); + state.styles = initialStyles; + + if (state.elements.arrow) { + Object.assign(state.elements.arrow.style, initialStyles.arrow); + } + + return function () { + Object.keys(state.elements).forEach(function (name) { + var element = state.elements[name]; + var attributes = state.attributes[name] || {}; + var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them + + var style = styleProperties.reduce(function (style, property) { + style[property] = ''; + return style; + }, {}); // arrow is optional + virtual elements + + if (!isHTMLElement(element) || !getNodeName(element)) { + return; + } + + Object.assign(element.style, style); + Object.keys(attributes).forEach(function (attribute) { + element.removeAttribute(attribute); + }); + }); + }; +} // eslint-disable-next-line import/no-unused-modules + + +var applyStyles$1 = { + name: 'applyStyles', + enabled: true, + phase: 'write', + fn: applyStyles, + effect: effect$2, + requires: ['computeStyles'] +}; + +function getBasePlacement(placement) { + return placement.split('-')[0]; +} + +var max = Math.max; +var min = Math.min; +var round = Math.round; + +function getUAString() { + var uaData = navigator.userAgentData; + + if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) { + return uaData.brands.map(function (item) { + return item.brand + "/" + item.version; + }).join(' '); + } + + return navigator.userAgent; +} + +function isLayoutViewport() { + return !/^((?!chrome|android).)*safari/i.test(getUAString()); +} + +function getBoundingClientRect(element, includeScale, isFixedStrategy) { + if (includeScale === void 0) { + includeScale = false; + } + + if (isFixedStrategy === void 0) { + isFixedStrategy = false; + } + + var clientRect = element.getBoundingClientRect(); + var scaleX = 1; + var scaleY = 1; + + if (includeScale && isHTMLElement(element)) { + scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1; + scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1; + } + + var _ref = isElement(element) ? getWindow(element) : window, + visualViewport = _ref.visualViewport; + + var addVisualOffsets = !isLayoutViewport() && isFixedStrategy; + var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX; + var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY; + var width = clientRect.width / scaleX; + var height = clientRect.height / scaleY; + return { + width: width, + height: height, + top: y, + right: x + width, + bottom: y + height, + left: x, + x: x, + y: y + }; +} + +// means it doesn't take into account transforms. + +function getLayoutRect(element) { + var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed. + // Fixes https://github.com/popperjs/popper-core/issues/1223 + + var width = element.offsetWidth; + var height = element.offsetHeight; + + if (Math.abs(clientRect.width - width) <= 1) { + width = clientRect.width; + } + + if (Math.abs(clientRect.height - height) <= 1) { + height = clientRect.height; + } + + return { + x: element.offsetLeft, + y: element.offsetTop, + width: width, + height: height + }; +} + +function contains(parent, child) { + var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method + + if (parent.contains(child)) { + return true; + } // then fallback to custom implementation with Shadow DOM support + else if (rootNode && isShadowRoot(rootNode)) { + var next = child; + + do { + if (next && parent.isSameNode(next)) { + return true; + } // $FlowFixMe[prop-missing]: need a better way to handle this... + + + next = next.parentNode || next.host; + } while (next); + } // Give up, the result is false + + + return false; +} + +function getComputedStyle(element) { + return getWindow(element).getComputedStyle(element); +} + +function isTableElement(element) { + return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0; +} + +function getDocumentElement(element) { + // $FlowFixMe[incompatible-return]: assume body is always available + return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing] + element.document) || window.document).documentElement; +} + +function getParentNode(element) { + if (getNodeName(element) === 'html') { + return element; + } + + return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle + // $FlowFixMe[incompatible-return] + // $FlowFixMe[prop-missing] + element.assignedSlot || // step into the shadow DOM of the parent of a slotted node + element.parentNode || ( // DOM Element detected + isShadowRoot(element) ? element.host : null) || // ShadowRoot detected + // $FlowFixMe[incompatible-call]: HTMLElement is a Node + getDocumentElement(element) // fallback + + ); +} + +function getTrueOffsetParent(element) { + if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837 + getComputedStyle(element).position === 'fixed') { + return null; + } + + return element.offsetParent; +} // `.offsetParent` reports `null` for fixed elements, while absolute elements +// return the containing block + + +function getContainingBlock(element) { + var isFirefox = /firefox/i.test(getUAString()); + var isIE = /Trident/i.test(getUAString()); + + if (isIE && isHTMLElement(element)) { + // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport + var elementCss = getComputedStyle(element); + + if (elementCss.position === 'fixed') { + return null; + } + } + + var currentNode = getParentNode(element); + + if (isShadowRoot(currentNode)) { + currentNode = currentNode.host; + } + + while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) { + var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that + // create a containing block. + // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block + + if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') { + return currentNode; + } else { + currentNode = currentNode.parentNode; + } + } + + return null; +} // Gets the closest ancestor positioned element. Handles some edge cases, +// such as table ancestors and cross browser bugs. + + +function getOffsetParent(element) { + var window = getWindow(element); + var offsetParent = getTrueOffsetParent(element); + + while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') { + offsetParent = getTrueOffsetParent(offsetParent); + } + + if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) { + return window; + } + + return offsetParent || getContainingBlock(element) || window; +} + +function getMainAxisFromPlacement(placement) { + return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y'; +} + +function within(min$1, value, max$1) { + return max(min$1, min(value, max$1)); +} +function withinMaxClamp(min, value, max) { + var v = within(min, value, max); + return v > max ? max : v; +} + +function getFreshSideObject() { + return { + top: 0, + right: 0, + bottom: 0, + left: 0 + }; +} + +function mergePaddingObject(paddingObject) { + return Object.assign({}, getFreshSideObject(), paddingObject); +} + +function expandToHashMap(value, keys) { + return keys.reduce(function (hashMap, key) { + hashMap[key] = value; + return hashMap; + }, {}); +} + +var toPaddingObject = function toPaddingObject(padding, state) { + padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, { + placement: state.placement + })) : padding; + return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); +}; + +function arrow(_ref) { + var _state$modifiersData$; + + var state = _ref.state, + name = _ref.name, + options = _ref.options; + var arrowElement = state.elements.arrow; + var popperOffsets = state.modifiersData.popperOffsets; + var basePlacement = getBasePlacement(state.placement); + var axis = getMainAxisFromPlacement(basePlacement); + var isVertical = [left, right].indexOf(basePlacement) >= 0; + var len = isVertical ? 'height' : 'width'; + + if (!arrowElement || !popperOffsets) { + return; + } + + var paddingObject = toPaddingObject(options.padding, state); + var arrowRect = getLayoutRect(arrowElement); + var minProp = axis === 'y' ? top : left; + var maxProp = axis === 'y' ? bottom : right; + var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len]; + var startDiff = popperOffsets[axis] - state.rects.reference[axis]; + var arrowOffsetParent = getOffsetParent(arrowElement); + var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0; + var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is + // outside of the popper bounds + + var min = paddingObject[minProp]; + var max = clientSize - arrowRect[len] - paddingObject[maxProp]; + var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference; + var offset = within(min, center, max); // Prevents breaking syntax highlighting... + + var axisProp = axis; + state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$); +} + +function effect$1(_ref2) { + var state = _ref2.state, + options = _ref2.options; + var _options$element = options.element, + arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element; + + if (arrowElement == null) { + return; + } // CSS selector + + + if (typeof arrowElement === 'string') { + arrowElement = state.elements.popper.querySelector(arrowElement); + + if (!arrowElement) { + return; + } + } + + if (!contains(state.elements.popper, arrowElement)) { + return; + } + + state.elements.arrow = arrowElement; +} // eslint-disable-next-line import/no-unused-modules + + +var arrow$1 = { + name: 'arrow', + enabled: true, + phase: 'main', + fn: arrow, + effect: effect$1, + requires: ['popperOffsets'], + requiresIfExists: ['preventOverflow'] +}; + +function getVariation(placement) { + return placement.split('-')[1]; +} + +var unsetSides = { + top: 'auto', + right: 'auto', + bottom: 'auto', + left: 'auto' +}; // Round the offsets to the nearest suitable subpixel based on the DPR. +// Zooming can change the DPR, but it seems to report a value that will +// cleanly divide the values into the appropriate subpixels. + +function roundOffsetsByDPR(_ref, win) { + var x = _ref.x, + y = _ref.y; + var dpr = win.devicePixelRatio || 1; + return { + x: round(x * dpr) / dpr || 0, + y: round(y * dpr) / dpr || 0 + }; +} + +function mapToStyles(_ref2) { + var _Object$assign2; + + var popper = _ref2.popper, + popperRect = _ref2.popperRect, + placement = _ref2.placement, + variation = _ref2.variation, + offsets = _ref2.offsets, + position = _ref2.position, + gpuAcceleration = _ref2.gpuAcceleration, + adaptive = _ref2.adaptive, + roundOffsets = _ref2.roundOffsets, + isFixed = _ref2.isFixed; + var _offsets$x = offsets.x, + x = _offsets$x === void 0 ? 0 : _offsets$x, + _offsets$y = offsets.y, + y = _offsets$y === void 0 ? 0 : _offsets$y; + + var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({ + x: x, + y: y + }) : { + x: x, + y: y + }; + + x = _ref3.x; + y = _ref3.y; + var hasX = offsets.hasOwnProperty('x'); + var hasY = offsets.hasOwnProperty('y'); + var sideX = left; + var sideY = top; + var win = window; + + if (adaptive) { + var offsetParent = getOffsetParent(popper); + var heightProp = 'clientHeight'; + var widthProp = 'clientWidth'; + + if (offsetParent === getWindow(popper)) { + offsetParent = getDocumentElement(popper); + + if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') { + heightProp = 'scrollHeight'; + widthProp = 'scrollWidth'; + } + } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it + + + offsetParent = offsetParent; + + if (placement === top || (placement === left || placement === right) && variation === end) { + sideY = bottom; + var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing] + offsetParent[heightProp]; + y -= offsetY - popperRect.height; + y *= gpuAcceleration ? 1 : -1; + } + + if (placement === left || (placement === top || placement === bottom) && variation === end) { + sideX = right; + var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing] + offsetParent[widthProp]; + x -= offsetX - popperRect.width; + x *= gpuAcceleration ? 1 : -1; + } + } + + var commonStyles = Object.assign({ + position: position + }, adaptive && unsetSides); + + var _ref4 = roundOffsets === true ? roundOffsetsByDPR({ + x: x, + y: y + }, getWindow(popper)) : { + x: x, + y: y + }; + + x = _ref4.x; + y = _ref4.y; + + if (gpuAcceleration) { + var _Object$assign; + + return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); + } + + return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); +} + +function computeStyles(_ref5) { + var state = _ref5.state, + options = _ref5.options; + var _options$gpuAccelerat = options.gpuAcceleration, + gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, + _options$adaptive = options.adaptive, + adaptive = _options$adaptive === void 0 ? true : _options$adaptive, + _options$roundOffsets = options.roundOffsets, + roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets; + var commonStyles = { + placement: getBasePlacement(state.placement), + variation: getVariation(state.placement), + popper: state.elements.popper, + popperRect: state.rects.popper, + gpuAcceleration: gpuAcceleration, + isFixed: state.options.strategy === 'fixed' + }; + + if (state.modifiersData.popperOffsets != null) { + state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, { + offsets: state.modifiersData.popperOffsets, + position: state.options.strategy, + adaptive: adaptive, + roundOffsets: roundOffsets + }))); + } + + if (state.modifiersData.arrow != null) { + state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, { + offsets: state.modifiersData.arrow, + position: 'absolute', + adaptive: false, + roundOffsets: roundOffsets + }))); + } + + state.attributes.popper = Object.assign({}, state.attributes.popper, { + 'data-popper-placement': state.placement + }); +} // eslint-disable-next-line import/no-unused-modules + + +var computeStyles$1 = { + name: 'computeStyles', + enabled: true, + phase: 'beforeWrite', + fn: computeStyles, + data: {} +}; + +var passive = { + passive: true +}; + +function effect(_ref) { + var state = _ref.state, + instance = _ref.instance, + options = _ref.options; + var _options$scroll = options.scroll, + scroll = _options$scroll === void 0 ? true : _options$scroll, + _options$resize = options.resize, + resize = _options$resize === void 0 ? true : _options$resize; + var window = getWindow(state.elements.popper); + var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper); + + if (scroll) { + scrollParents.forEach(function (scrollParent) { + scrollParent.addEventListener('scroll', instance.update, passive); + }); + } + + if (resize) { + window.addEventListener('resize', instance.update, passive); + } + + return function () { + if (scroll) { + scrollParents.forEach(function (scrollParent) { + scrollParent.removeEventListener('scroll', instance.update, passive); + }); + } + + if (resize) { + window.removeEventListener('resize', instance.update, passive); + } + }; +} // eslint-disable-next-line import/no-unused-modules + + +var eventListeners = { + name: 'eventListeners', + enabled: true, + phase: 'write', + fn: function fn() {}, + effect: effect, + data: {} +}; + +var hash$1 = { + left: 'right', + right: 'left', + bottom: 'top', + top: 'bottom' +}; +function getOppositePlacement(placement) { + return placement.replace(/left|right|bottom|top/g, function (matched) { + return hash$1[matched]; + }); +} + +var hash = { + start: 'end', + end: 'start' +}; +function getOppositeVariationPlacement(placement) { + return placement.replace(/start|end/g, function (matched) { + return hash[matched]; + }); +} + +function getWindowScroll(node) { + var win = getWindow(node); + var scrollLeft = win.pageXOffset; + var scrollTop = win.pageYOffset; + return { + scrollLeft: scrollLeft, + scrollTop: scrollTop + }; +} + +function getWindowScrollBarX(element) { + // If has a CSS width greater than the viewport, then this will be + // incorrect for RTL. + // Popper 1 is broken in this case and never had a bug report so let's assume + // it's not an issue. I don't think anyone ever specifies width on + // anyway. + // Browsers where the left scrollbar doesn't cause an issue report `0` for + // this (e.g. Edge 2019, IE11, Safari) + return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft; +} + +function getViewportRect(element, strategy) { + var win = getWindow(element); + var html = getDocumentElement(element); + var visualViewport = win.visualViewport; + var width = html.clientWidth; + var height = html.clientHeight; + var x = 0; + var y = 0; + + if (visualViewport) { + width = visualViewport.width; + height = visualViewport.height; + var layoutViewport = isLayoutViewport(); + + if (layoutViewport || !layoutViewport && strategy === 'fixed') { + x = visualViewport.offsetLeft; + y = visualViewport.offsetTop; + } + } + + return { + width: width, + height: height, + x: x + getWindowScrollBarX(element), + y: y + }; +} + +// of the `` and `` rect bounds if horizontally scrollable + +function getDocumentRect(element) { + var _element$ownerDocumen; + + var html = getDocumentElement(element); + var winScroll = getWindowScroll(element); + var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body; + var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0); + var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0); + var x = -winScroll.scrollLeft + getWindowScrollBarX(element); + var y = -winScroll.scrollTop; + + if (getComputedStyle(body || html).direction === 'rtl') { + x += max(html.clientWidth, body ? body.clientWidth : 0) - width; + } + + return { + width: width, + height: height, + x: x, + y: y + }; +} + +function isScrollParent(element) { + // Firefox wants us to check `-x` and `-y` variations as well + var _getComputedStyle = getComputedStyle(element), + overflow = _getComputedStyle.overflow, + overflowX = _getComputedStyle.overflowX, + overflowY = _getComputedStyle.overflowY; + + return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX); +} + +function getScrollParent(node) { + if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) { + // $FlowFixMe[incompatible-return]: assume body is always available + return node.ownerDocument.body; + } + + if (isHTMLElement(node) && isScrollParent(node)) { + return node; + } + + return getScrollParent(getParentNode(node)); +} + +/* +given a DOM element, return the list of all scroll parents, up the list of ancesors +until we get to the top window object. This list is what we attach scroll listeners +to, because if any of these parent elements scroll, we'll need to re-calculate the +reference element's position. +*/ + +function listScrollParents(element, list) { + var _element$ownerDocumen; + + if (list === void 0) { + list = []; + } + + var scrollParent = getScrollParent(element); + var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body); + var win = getWindow(scrollParent); + var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent; + var updatedList = list.concat(target); + return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here + updatedList.concat(listScrollParents(getParentNode(target))); +} + +function rectToClientRect(rect) { + return Object.assign({}, rect, { + left: rect.x, + top: rect.y, + right: rect.x + rect.width, + bottom: rect.y + rect.height + }); +} + +function getInnerBoundingClientRect(element, strategy) { + var rect = getBoundingClientRect(element, false, strategy === 'fixed'); + rect.top = rect.top + element.clientTop; + rect.left = rect.left + element.clientLeft; + rect.bottom = rect.top + element.clientHeight; + rect.right = rect.left + element.clientWidth; + rect.width = element.clientWidth; + rect.height = element.clientHeight; + rect.x = rect.left; + rect.y = rect.top; + return rect; +} + +function getClientRectFromMixedType(element, clippingParent, strategy) { + return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element))); +} // A "clipping parent" is an overflowable container with the characteristic of +// clipping (or hiding) overflowing elements with a position different from +// `initial` + + +function getClippingParents(element) { + var clippingParents = listScrollParents(getParentNode(element)); + var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0; + var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element; + + if (!isElement(clipperElement)) { + return []; + } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414 + + + return clippingParents.filter(function (clippingParent) { + return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body'; + }); +} // Gets the maximum area that the element is visible in due to any number of +// clipping parents + + +function getClippingRect(element, boundary, rootBoundary, strategy) { + var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary); + var clippingParents = [].concat(mainClippingParents, [rootBoundary]); + var firstClippingParent = clippingParents[0]; + var clippingRect = clippingParents.reduce(function (accRect, clippingParent) { + var rect = getClientRectFromMixedType(element, clippingParent, strategy); + accRect.top = max(rect.top, accRect.top); + accRect.right = min(rect.right, accRect.right); + accRect.bottom = min(rect.bottom, accRect.bottom); + accRect.left = max(rect.left, accRect.left); + return accRect; + }, getClientRectFromMixedType(element, firstClippingParent, strategy)); + clippingRect.width = clippingRect.right - clippingRect.left; + clippingRect.height = clippingRect.bottom - clippingRect.top; + clippingRect.x = clippingRect.left; + clippingRect.y = clippingRect.top; + return clippingRect; +} + +function computeOffsets(_ref) { + var reference = _ref.reference, + element = _ref.element, + placement = _ref.placement; + var basePlacement = placement ? getBasePlacement(placement) : null; + var variation = placement ? getVariation(placement) : null; + var commonX = reference.x + reference.width / 2 - element.width / 2; + var commonY = reference.y + reference.height / 2 - element.height / 2; + var offsets; + + switch (basePlacement) { + case top: + offsets = { + x: commonX, + y: reference.y - element.height + }; + break; + + case bottom: + offsets = { + x: commonX, + y: reference.y + reference.height + }; + break; + + case right: + offsets = { + x: reference.x + reference.width, + y: commonY + }; + break; + + case left: + offsets = { + x: reference.x - element.width, + y: commonY + }; + break; + + default: + offsets = { + x: reference.x, + y: reference.y + }; + } + + var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null; + + if (mainAxis != null) { + var len = mainAxis === 'y' ? 'height' : 'width'; + + switch (variation) { + case start: + offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2); + break; + + case end: + offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2); + break; + } + } + + return offsets; +} + +function detectOverflow(state, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + _options$placement = _options.placement, + placement = _options$placement === void 0 ? state.placement : _options$placement, + _options$strategy = _options.strategy, + strategy = _options$strategy === void 0 ? state.strategy : _options$strategy, + _options$boundary = _options.boundary, + boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, + _options$rootBoundary = _options.rootBoundary, + rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, + _options$elementConte = _options.elementContext, + elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, + _options$altBoundary = _options.altBoundary, + altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, + _options$padding = _options.padding, + padding = _options$padding === void 0 ? 0 : _options$padding; + var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); + var altContext = elementContext === popper ? reference : popper; + var popperRect = state.rects.popper; + var element = state.elements[altBoundary ? altContext : elementContext]; + var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy); + var referenceClientRect = getBoundingClientRect(state.elements.reference); + var popperOffsets = computeOffsets({ + reference: referenceClientRect, + element: popperRect, + strategy: 'absolute', + placement: placement + }); + var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets)); + var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect + // 0 or negative = within the clipping rect + + var overflowOffsets = { + top: clippingClientRect.top - elementClientRect.top + paddingObject.top, + bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom, + left: clippingClientRect.left - elementClientRect.left + paddingObject.left, + right: elementClientRect.right - clippingClientRect.right + paddingObject.right + }; + var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element + + if (elementContext === popper && offsetData) { + var offset = offsetData[placement]; + Object.keys(overflowOffsets).forEach(function (key) { + var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1; + var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x'; + overflowOffsets[key] += offset[axis] * multiply; + }); + } + + return overflowOffsets; +} + +function computeAutoPlacement(state, options) { + if (options === void 0) { + options = {}; + } + + var _options = options, + placement = _options.placement, + boundary = _options.boundary, + rootBoundary = _options.rootBoundary, + padding = _options.padding, + flipVariations = _options.flipVariations, + _options$allowedAutoP = _options.allowedAutoPlacements, + allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP; + var variation = getVariation(placement); + var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) { + return getVariation(placement) === variation; + }) : basePlacements; + var allowedPlacements = placements$1.filter(function (placement) { + return allowedAutoPlacements.indexOf(placement) >= 0; + }); + + if (allowedPlacements.length === 0) { + allowedPlacements = placements$1; + } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions... + + + var overflows = allowedPlacements.reduce(function (acc, placement) { + acc[placement] = detectOverflow(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding + })[getBasePlacement(placement)]; + return acc; + }, {}); + return Object.keys(overflows).sort(function (a, b) { + return overflows[a] - overflows[b]; + }); +} + +function getExpandedFallbackPlacements(placement) { + if (getBasePlacement(placement) === auto) { + return []; + } + + var oppositePlacement = getOppositePlacement(placement); + return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)]; +} + +function flip(_ref) { + var state = _ref.state, + options = _ref.options, + name = _ref.name; + + if (state.modifiersData[name]._skip) { + return; + } + + var _options$mainAxis = options.mainAxis, + checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, + _options$altAxis = options.altAxis, + checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, + specifiedFallbackPlacements = options.fallbackPlacements, + padding = options.padding, + boundary = options.boundary, + rootBoundary = options.rootBoundary, + altBoundary = options.altBoundary, + _options$flipVariatio = options.flipVariations, + flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, + allowedAutoPlacements = options.allowedAutoPlacements; + var preferredPlacement = state.options.placement; + var basePlacement = getBasePlacement(preferredPlacement); + var isBasePlacement = basePlacement === preferredPlacement; + var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement)); + var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) { + return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding, + flipVariations: flipVariations, + allowedAutoPlacements: allowedAutoPlacements + }) : placement); + }, []); + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var checksMap = new Map(); + var makeFallbackChecks = true; + var firstFittingPlacement = placements[0]; + + for (var i = 0; i < placements.length; i++) { + var placement = placements[i]; + + var _basePlacement = getBasePlacement(placement); + + var isStartVariation = getVariation(placement) === start; + var isVertical = [top, bottom].indexOf(_basePlacement) >= 0; + var len = isVertical ? 'width' : 'height'; + var overflow = detectOverflow(state, { + placement: placement, + boundary: boundary, + rootBoundary: rootBoundary, + altBoundary: altBoundary, + padding: padding + }); + var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top; + + if (referenceRect[len] > popperRect[len]) { + mainVariationSide = getOppositePlacement(mainVariationSide); + } + + var altVariationSide = getOppositePlacement(mainVariationSide); + var checks = []; + + if (checkMainAxis) { + checks.push(overflow[_basePlacement] <= 0); + } + + if (checkAltAxis) { + checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0); + } + + if (checks.every(function (check) { + return check; + })) { + firstFittingPlacement = placement; + makeFallbackChecks = false; + break; + } + + checksMap.set(placement, checks); + } + + if (makeFallbackChecks) { + // `2` may be desired in some cases – research later + var numberOfChecks = flipVariations ? 3 : 1; + + var _loop = function _loop(_i) { + var fittingPlacement = placements.find(function (placement) { + var checks = checksMap.get(placement); + + if (checks) { + return checks.slice(0, _i).every(function (check) { + return check; + }); + } + }); + + if (fittingPlacement) { + firstFittingPlacement = fittingPlacement; + return "break"; + } + }; + + for (var _i = numberOfChecks; _i > 0; _i--) { + var _ret = _loop(_i); + + if (_ret === "break") break; + } + } + + if (state.placement !== firstFittingPlacement) { + state.modifiersData[name]._skip = true; + state.placement = firstFittingPlacement; + state.reset = true; + } +} // eslint-disable-next-line import/no-unused-modules + + +var flip$1 = { + name: 'flip', + enabled: true, + phase: 'main', + fn: flip, + requiresIfExists: ['offset'], + data: { + _skip: false + } +}; + +function getSideOffsets(overflow, rect, preventedOffsets) { + if (preventedOffsets === void 0) { + preventedOffsets = { + x: 0, + y: 0 + }; + } + + return { + top: overflow.top - rect.height - preventedOffsets.y, + right: overflow.right - rect.width + preventedOffsets.x, + bottom: overflow.bottom - rect.height + preventedOffsets.y, + left: overflow.left - rect.width - preventedOffsets.x + }; +} + +function isAnySideFullyClipped(overflow) { + return [top, right, bottom, left].some(function (side) { + return overflow[side] >= 0; + }); +} + +function hide(_ref) { + var state = _ref.state, + name = _ref.name; + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var preventedOffsets = state.modifiersData.preventOverflow; + var referenceOverflow = detectOverflow(state, { + elementContext: 'reference' + }); + var popperAltOverflow = detectOverflow(state, { + altBoundary: true + }); + var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect); + var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets); + var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets); + var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets); + state.modifiersData[name] = { + referenceClippingOffsets: referenceClippingOffsets, + popperEscapeOffsets: popperEscapeOffsets, + isReferenceHidden: isReferenceHidden, + hasPopperEscaped: hasPopperEscaped + }; + state.attributes.popper = Object.assign({}, state.attributes.popper, { + 'data-popper-reference-hidden': isReferenceHidden, + 'data-popper-escaped': hasPopperEscaped + }); +} // eslint-disable-next-line import/no-unused-modules + + +var hide$1 = { + name: 'hide', + enabled: true, + phase: 'main', + requiresIfExists: ['preventOverflow'], + fn: hide +}; + +function distanceAndSkiddingToXY(placement, rects, offset) { + var basePlacement = getBasePlacement(placement); + var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1; + + var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, { + placement: placement + })) : offset, + skidding = _ref[0], + distance = _ref[1]; + + skidding = skidding || 0; + distance = (distance || 0) * invertDistance; + return [left, right].indexOf(basePlacement) >= 0 ? { + x: distance, + y: skidding + } : { + x: skidding, + y: distance + }; +} + +function offset(_ref2) { + var state = _ref2.state, + options = _ref2.options, + name = _ref2.name; + var _options$offset = options.offset, + offset = _options$offset === void 0 ? [0, 0] : _options$offset; + var data = placements.reduce(function (acc, placement) { + acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset); + return acc; + }, {}); + var _data$state$placement = data[state.placement], + x = _data$state$placement.x, + y = _data$state$placement.y; + + if (state.modifiersData.popperOffsets != null) { + state.modifiersData.popperOffsets.x += x; + state.modifiersData.popperOffsets.y += y; + } + + state.modifiersData[name] = data; +} // eslint-disable-next-line import/no-unused-modules + + +var offset$1 = { + name: 'offset', + enabled: true, + phase: 'main', + requires: ['popperOffsets'], + fn: offset +}; + +function popperOffsets(_ref) { + var state = _ref.state, + name = _ref.name; + // Offsets are the actual position the popper needs to have to be + // properly positioned near its reference element + // This is the most basic placement, and will be adjusted by + // the modifiers in the next step + state.modifiersData[name] = computeOffsets({ + reference: state.rects.reference, + element: state.rects.popper, + strategy: 'absolute', + placement: state.placement + }); +} // eslint-disable-next-line import/no-unused-modules + + +var popperOffsets$1 = { + name: 'popperOffsets', + enabled: true, + phase: 'read', + fn: popperOffsets, + data: {} +}; + +function getAltAxis(axis) { + return axis === 'x' ? 'y' : 'x'; +} + +function preventOverflow(_ref) { + var state = _ref.state, + options = _ref.options, + name = _ref.name; + var _options$mainAxis = options.mainAxis, + checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, + _options$altAxis = options.altAxis, + checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, + boundary = options.boundary, + rootBoundary = options.rootBoundary, + altBoundary = options.altBoundary, + padding = options.padding, + _options$tether = options.tether, + tether = _options$tether === void 0 ? true : _options$tether, + _options$tetherOffset = options.tetherOffset, + tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset; + var overflow = detectOverflow(state, { + boundary: boundary, + rootBoundary: rootBoundary, + padding: padding, + altBoundary: altBoundary + }); + var basePlacement = getBasePlacement(state.placement); + var variation = getVariation(state.placement); + var isBasePlacement = !variation; + var mainAxis = getMainAxisFromPlacement(basePlacement); + var altAxis = getAltAxis(mainAxis); + var popperOffsets = state.modifiersData.popperOffsets; + var referenceRect = state.rects.reference; + var popperRect = state.rects.popper; + var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, { + placement: state.placement + })) : tetherOffset; + var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? { + mainAxis: tetherOffsetValue, + altAxis: tetherOffsetValue + } : Object.assign({ + mainAxis: 0, + altAxis: 0 + }, tetherOffsetValue); + var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null; + var data = { + x: 0, + y: 0 + }; + + if (!popperOffsets) { + return; + } + + if (checkMainAxis) { + var _offsetModifierState$; + + var mainSide = mainAxis === 'y' ? top : left; + var altSide = mainAxis === 'y' ? bottom : right; + var len = mainAxis === 'y' ? 'height' : 'width'; + var offset = popperOffsets[mainAxis]; + var min$1 = offset + overflow[mainSide]; + var max$1 = offset - overflow[altSide]; + var additive = tether ? -popperRect[len] / 2 : 0; + var minLen = variation === start ? referenceRect[len] : popperRect[len]; + var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go + // outside the reference bounds + + var arrowElement = state.elements.arrow; + var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { + width: 0, + height: 0 + }; + var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject(); + var arrowPaddingMin = arrowPaddingObject[mainSide]; + var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want + // to include its full size in the calculation. If the reference is small + // and near the edge of a boundary, the popper can overflow even if the + // reference is not overflowing as well (e.g. virtual elements with no + // width or height) + + var arrowLen = within(0, referenceRect[len], arrowRect[len]); + var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis; + var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis; + var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow); + var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0; + var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0; + var tetherMin = offset + minOffset - offsetModifierValue - clientOffset; + var tetherMax = offset + maxOffset - offsetModifierValue; + var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1); + popperOffsets[mainAxis] = preventedOffset; + data[mainAxis] = preventedOffset - offset; + } + + if (checkAltAxis) { + var _offsetModifierState$2; + + var _mainSide = mainAxis === 'x' ? top : left; + + var _altSide = mainAxis === 'x' ? bottom : right; + + var _offset = popperOffsets[altAxis]; + + var _len = altAxis === 'y' ? 'height' : 'width'; + + var _min = _offset + overflow[_mainSide]; + + var _max = _offset - overflow[_altSide]; + + var isOriginSide = [top, left].indexOf(basePlacement) !== -1; + + var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0; + + var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis; + + var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max; + + var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max); + + popperOffsets[altAxis] = _preventedOffset; + data[altAxis] = _preventedOffset - _offset; + } + + state.modifiersData[name] = data; +} // eslint-disable-next-line import/no-unused-modules + + +var preventOverflow$1 = { + name: 'preventOverflow', + enabled: true, + phase: 'main', + fn: preventOverflow, + requiresIfExists: ['offset'] +}; + +function getHTMLElementScroll(element) { + return { + scrollLeft: element.scrollLeft, + scrollTop: element.scrollTop + }; +} + +function getNodeScroll(node) { + if (node === getWindow(node) || !isHTMLElement(node)) { + return getWindowScroll(node); + } else { + return getHTMLElementScroll(node); + } +} + +function isElementScaled(element) { + var rect = element.getBoundingClientRect(); + var scaleX = round(rect.width) / element.offsetWidth || 1; + var scaleY = round(rect.height) / element.offsetHeight || 1; + return scaleX !== 1 || scaleY !== 1; +} // Returns the composite rect of an element relative to its offsetParent. +// Composite means it takes into account transforms as well as layout. + + +function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) { + if (isFixed === void 0) { + isFixed = false; + } + + var isOffsetParentAnElement = isHTMLElement(offsetParent); + var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent); + var documentElement = getDocumentElement(offsetParent); + var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed); + var scroll = { + scrollLeft: 0, + scrollTop: 0 + }; + var offsets = { + x: 0, + y: 0 + }; + + if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { + if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078 + isScrollParent(documentElement)) { + scroll = getNodeScroll(offsetParent); + } + + if (isHTMLElement(offsetParent)) { + offsets = getBoundingClientRect(offsetParent, true); + offsets.x += offsetParent.clientLeft; + offsets.y += offsetParent.clientTop; + } else if (documentElement) { + offsets.x = getWindowScrollBarX(documentElement); + } + } + + return { + x: rect.left + scroll.scrollLeft - offsets.x, + y: rect.top + scroll.scrollTop - offsets.y, + width: rect.width, + height: rect.height + }; +} + +function order(modifiers) { + var map = new Map(); + var visited = new Set(); + var result = []; + modifiers.forEach(function (modifier) { + map.set(modifier.name, modifier); + }); // On visiting object, check for its dependencies and visit them recursively + + function sort(modifier) { + visited.add(modifier.name); + var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []); + requires.forEach(function (dep) { + if (!visited.has(dep)) { + var depModifier = map.get(dep); + + if (depModifier) { + sort(depModifier); + } + } + }); + result.push(modifier); + } + + modifiers.forEach(function (modifier) { + if (!visited.has(modifier.name)) { + // check for visited object + sort(modifier); + } + }); + return result; +} + +function orderModifiers(modifiers) { + // order based on dependencies + var orderedModifiers = order(modifiers); // order based on phase + + return modifierPhases.reduce(function (acc, phase) { + return acc.concat(orderedModifiers.filter(function (modifier) { + return modifier.phase === phase; + })); + }, []); +} + +function debounce(fn) { + var pending; + return function () { + if (!pending) { + pending = new Promise(function (resolve) { + Promise.resolve().then(function () { + pending = undefined; + resolve(fn()); + }); + }); + } + + return pending; + }; +} + +function mergeByName(modifiers) { + var merged = modifiers.reduce(function (merged, current) { + var existing = merged[current.name]; + merged[current.name] = existing ? Object.assign({}, existing, current, { + options: Object.assign({}, existing.options, current.options), + data: Object.assign({}, existing.data, current.data) + }) : current; + return merged; + }, {}); // IE11 does not support Object.values + + return Object.keys(merged).map(function (key) { + return merged[key]; + }); +} + +var DEFAULT_OPTIONS = { + placement: 'bottom', + modifiers: [], + strategy: 'absolute' +}; + +function areValidElements() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return !args.some(function (element) { + return !(element && typeof element.getBoundingClientRect === 'function'); + }); +} + +function popperGenerator(generatorOptions) { + if (generatorOptions === void 0) { + generatorOptions = {}; + } + + var _generatorOptions = generatorOptions, + _generatorOptions$def = _generatorOptions.defaultModifiers, + defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, + _generatorOptions$def2 = _generatorOptions.defaultOptions, + defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; + return function createPopper(reference, popper, options) { + if (options === void 0) { + options = defaultOptions; + } + + var state = { + placement: 'bottom', + orderedModifiers: [], + options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions), + modifiersData: {}, + elements: { + reference: reference, + popper: popper + }, + attributes: {}, + styles: {} + }; + var effectCleanupFns = []; + var isDestroyed = false; + var instance = { + state: state, + setOptions: function setOptions(setOptionsAction) { + var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction; + cleanupModifierEffects(); + state.options = Object.assign({}, defaultOptions, state.options, options); + state.scrollParents = { + reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], + popper: listScrollParents(popper) + }; // Orders the modifiers based on their dependencies and `phase` + // properties + + var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers + + state.orderedModifiers = orderedModifiers.filter(function (m) { + return m.enabled; + }); + runModifierEffects(); + return instance.update(); + }, + // Sync update – it will always be executed, even if not necessary. This + // is useful for low frequency updates where sync behavior simplifies the + // logic. + // For high frequency updates (e.g. `resize` and `scroll` events), always + // prefer the async Popper#update method + forceUpdate: function forceUpdate() { + if (isDestroyed) { + return; + } + + var _state$elements = state.elements, + reference = _state$elements.reference, + popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements + // anymore + + if (!areValidElements(reference, popper)) { + return; + } // Store the reference and popper rects to be read by modifiers + + + state.rects = { + reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), + popper: getLayoutRect(popper) + }; // Modifiers have the ability to reset the current update cycle. The + // most common use case for this is the `flip` modifier changing the + // placement, which then needs to re-run all the modifiers, because the + // logic was previously ran for the previous placement and is therefore + // stale/incorrect + + state.reset = false; + state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier + // is filled with the initial data specified by the modifier. This means + // it doesn't persist and is fresh on each update. + // To ensure persistent data, use `${name}#persistent` + + state.orderedModifiers.forEach(function (modifier) { + return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); + }); + + for (var index = 0; index < state.orderedModifiers.length; index++) { + if (state.reset === true) { + state.reset = false; + index = -1; + continue; + } + + var _state$orderedModifie = state.orderedModifiers[index], + fn = _state$orderedModifie.fn, + _state$orderedModifie2 = _state$orderedModifie.options, + _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, + name = _state$orderedModifie.name; + + if (typeof fn === 'function') { + state = fn({ + state: state, + options: _options, + name: name, + instance: instance + }) || state; + } + } + }, + // Async and optimistically optimized update – it will not be executed if + // not necessary (debounced to run at most once-per-tick) + update: debounce(function () { + return new Promise(function (resolve) { + instance.forceUpdate(); + resolve(state); + }); + }), + destroy: function destroy() { + cleanupModifierEffects(); + isDestroyed = true; + } + }; + + if (!areValidElements(reference, popper)) { + return instance; + } + + instance.setOptions(options).then(function (state) { + if (!isDestroyed && options.onFirstUpdate) { + options.onFirstUpdate(state); + } + }); // Modifiers have the ability to execute arbitrary code before the first + // update cycle runs. They will be executed in the same order as the update + // cycle. This is useful when a modifier adds some persistent data that + // other modifiers need to use, but the modifier is run after the dependent + // one. + + function runModifierEffects() { + state.orderedModifiers.forEach(function (_ref) { + var name = _ref.name, + _ref$options = _ref.options, + options = _ref$options === void 0 ? {} : _ref$options, + effect = _ref.effect; + + if (typeof effect === 'function') { + var cleanupFn = effect({ + state: state, + name: name, + instance: instance, + options: options + }); + + var noopFn = function noopFn() {}; + + effectCleanupFns.push(cleanupFn || noopFn); + } + }); + } + + function cleanupModifierEffects() { + effectCleanupFns.forEach(function (fn) { + return fn(); + }); + effectCleanupFns = []; + } + + return instance; + }; +} + +var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; +var createPopper = /*#__PURE__*/popperGenerator({ + defaultModifiers: defaultModifiers +}); // eslint-disable-next-line import/no-unused-modules + +/* Credit: liamcain's Periodic Notes Plugin (https://github.com/liamcain/obsidian-periodic-notes) */ +const wrapAround = (value, size) => { + return ((value % size) + size) % size; +}; +class Suggest { + constructor(owner, containerEl, scope) { + this.owner = owner; + this.containerEl = containerEl; + containerEl.on("click", ".suggestion-item", this.onSuggestionClick.bind(this)); + containerEl.on("mousemove", ".suggestion-item", this.onSuggestionMouseover.bind(this)); + scope.register([], "ArrowUp", (event) => { + if (!event.isComposing) { + this.setSelectedItem(this.selectedItem - 1, true); + return false; + } + }); + scope.register([], "ArrowDown", (event) => { + if (!event.isComposing) { + this.setSelectedItem(this.selectedItem + 1, true); + return false; + } + }); + scope.register([], "Enter", (event) => { + if (!event.isComposing) { + this.useSelectedItem(event); + return false; + } + }); + } + onSuggestionClick(event, el) { + event.preventDefault(); + const item = this.suggestions.indexOf(el); + this.setSelectedItem(item, false); + this.useSelectedItem(event); + } + onSuggestionMouseover(_event, el) { + const item = this.suggestions.indexOf(el); + this.setSelectedItem(item, false); + } + setSuggestions(values) { + this.containerEl.empty(); + const suggestionEls = []; + values.forEach((value) => { + const suggestionEl = this.containerEl.createDiv("suggestion-item"); + this.owner.renderSuggestion(value, suggestionEl); + suggestionEls.push(suggestionEl); + }); + this.values = values; + this.suggestions = suggestionEls; + this.setSelectedItem(0, false); + } + useSelectedItem(event) { + const currentValue = this.values[this.selectedItem]; + if (currentValue) { + this.owner.selectSuggestion(currentValue, event); + } + } + setSelectedItem(selectedIndex, scrollIntoView) { + const normalizedIndex = wrapAround(selectedIndex, this.suggestions.length); + const prevSelectedSuggestion = this.suggestions[this.selectedItem]; + const selectedSuggestion = this.suggestions[normalizedIndex]; + prevSelectedSuggestion === null || prevSelectedSuggestion === void 0 ? void 0 : prevSelectedSuggestion.removeClass("is-selected"); + selectedSuggestion === null || selectedSuggestion === void 0 ? void 0 : selectedSuggestion.addClass("is-selected"); + this.selectedItem = normalizedIndex; + if (scrollIntoView) { + selectedSuggestion.scrollIntoView(false); + } + } +} +class TextInputSuggest { + constructor(app, inputEl) { + this.app = app; + this.inputEl = inputEl; + this.scope = new obsidian.Scope(); + this.suggestEl = createDiv("suggestion-container"); + const suggestion = this.suggestEl.createDiv("suggestion"); + this.suggest = new Suggest(this, suggestion, this.scope); + this.scope.register([], "Escape", this.close.bind(this)); + this.inputEl.addEventListener("input", this.onInputChanged.bind(this)); + this.inputEl.addEventListener("focus", this.onInputChanged.bind(this)); + this.inputEl.addEventListener("blur", this.close.bind(this)); + this.suggestEl.on("mousedown", ".suggestion-container", (event) => { + event.preventDefault(); + }); + } + onInputChanged() { + const inputStr = this.inputEl.value; + const suggestions = this.getSuggestions(inputStr); + if (suggestions.length > 0) { + this.suggest.setSuggestions(suggestions); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.open(this.app.dom.appContainerEl, this.inputEl); + } + } + open(container, inputEl) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.app.keymap.pushScope(this.scope); + container.appendChild(this.suggestEl); + this.popper = createPopper(inputEl, this.suggestEl, { + placement: "bottom-start", + modifiers: [ + { + name: "sameWidth", + enabled: true, + fn: ({ state, instance }) => { + // Note: positioning needs to be calculated twice - + // first pass - positioning it according to the width of the popper + // second pass - position it with the width bound to the reference element + // we need to early exit to avoid an infinite loop + const targetWidth = `${state.rects.reference.width}px`; + if (state.styles.popper.width === targetWidth) { + return; + } + state.styles.popper.width = targetWidth; + instance.update(); + }, + phase: "beforeWrite", + requires: ["computeStyles"], + }, + ], + }); + } + close() { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.app.keymap.popScope(this.scope); + this.suggest.setSuggestions([]); + this.popper.destroy(); + this.suggestEl.detach(); + } +} + +/* Credit: liamcain's Periodic Notes Plugin (https://github.com/liamcain/obsidian-periodic-notes) */ +class FolderSuggest extends TextInputSuggest { + getSuggestions(inputStr) { + const abstractFiles = app.vault.getAllLoadedFiles(); + const folders = []; + const lowerCaseInputStr = inputStr.toLowerCase(); + abstractFiles.forEach((folder) => { + if (folder instanceof obsidian.TFolder && folder.path.toLowerCase().contains(lowerCaseInputStr)) { + folders.push(folder); + } + }); + return folders; + } + renderSuggestion(file, el) { + el.setText(file.path); + } + selectSuggestion(file) { + this.inputEl.value = file.path; + this.inputEl.trigger("input"); + this.close(); + } +} + +/* src/views/settings-ignored-folders.svelte generated by Svelte v4.2.9 */ + +function get_each_context(ctx, list, i) { + const child_ctx = ctx.slice(); + child_ctx[5] = list[i]; + return child_ctx; +} + +// (13:4) {#each ignoredFolders as folder} +function create_each_block(ctx) { + let div3; + let div0; + let t0; + let div1; + let t1; + let div2; + let t2_value = /*folder*/ ctx[5] + ""; + let t2; + let t3; + let mounted; + let dispose; + + function click_handler() { + return /*click_handler*/ ctx[3](/*folder*/ ctx[5]); + } + + return { + c() { + div3 = element("div"); + div0 = element("div"); + t0 = space(); + div1 = element("div"); + t1 = space(); + div2 = element("div"); + t2 = text(t2_value); + t3 = space(); + attr(div0, "class", "clickable-icon"); + attr(div0, "data-icon", "lucide-x"); + attr(div0, "aria-label", "Remove folder"); + attr(div1, "class", "broken-links-settings-folder-icon"); + attr(div1, "data-icon", "lucide-folder"); + attr(div2, "class", "broken-links-settings-folder-title"); + attr(div3, "class", "broken-links-settings-folder"); + }, + m(target, anchor) { + insert$1(target, div3, anchor); + append(div3, div0); + append(div3, t0); + append(div3, div1); + append(div3, t1); + append(div3, div2); + append(div2, t2); + append(div3, t3); + + if (!mounted) { + dispose = listen(div0, "click", click_handler); + mounted = true; + } + }, + p(new_ctx, dirty) { + ctx = new_ctx; + if (dirty & /*ignoredFolders*/ 1 && t2_value !== (t2_value = /*folder*/ ctx[5] + "")) set_data(t2, t2_value); + }, + d(detaching) { + if (detaching) { + detach(div3); + } + + mounted = false; + dispose(); + } + }; +} + +function create_fragment(ctx) { + let div; + let each_value = ensure_array_like(/*ignoredFolders*/ ctx[0]); + let each_blocks = []; + + for (let i = 0; i < each_value.length; i += 1) { + each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i)); + } + + return { + c() { + div = element("div"); + + for (let i = 0; i < each_blocks.length; i += 1) { + each_blocks[i].c(); + } + + attr(div, "class", "broken-links-settings-folders"); + }, + m(target, anchor) { + insert$1(target, div, anchor); + + for (let i = 0; i < each_blocks.length; i += 1) { + if (each_blocks[i]) { + each_blocks[i].m(div, null); + } + } + + /*div_binding*/ ctx[4](div); + }, + p(ctx, [dirty]) { + if (dirty & /*ignoredFolders, removeFolder*/ 3) { + each_value = ensure_array_like(/*ignoredFolders*/ ctx[0]); + let i; + + for (i = 0; i < each_value.length; i += 1) { + const child_ctx = get_each_context(ctx, each_value, i); + + if (each_blocks[i]) { + each_blocks[i].p(child_ctx, dirty); + } else { + each_blocks[i] = create_each_block(child_ctx); + each_blocks[i].c(); + each_blocks[i].m(div, null); + } + } + + for (; i < each_blocks.length; i += 1) { + each_blocks[i].d(1); + } + + each_blocks.length = each_value.length; + } + }, + i: noop, + o: noop, + d(detaching) { + if (detaching) { + detach(div); + } + + destroy_each(each_blocks, detaching); + /*div_binding*/ ctx[4](null); + } + }; +} + +function instance($$self, $$props, $$invalidate) { + let { ignoredFolders = [] } = $$props; + let { removeFolder } = $$props; + let list; + + afterUpdate(() => { + list.querySelectorAll(".broken-links-settings-folder-icon").forEach(el => { + var _a; + + return obsidian.setIcon(el, (_a = el.getAttr("data-icon")) !== null && _a !== void 0 + ? _a + : ""); + }); + + list.querySelectorAll(".clickable-icon").forEach(el => { + var _a; + + return obsidian.setIcon(el, (_a = el.getAttr("data-icon")) !== null && _a !== void 0 + ? _a + : ""); + }); + }); + + const click_handler = folder => removeFolder(folder); + + function div_binding($$value) { + binding_callbacks[$$value ? 'unshift' : 'push'](() => { + list = $$value; + $$invalidate(2, list); + }); + } + + $$self.$$set = $$props => { + if ('ignoredFolders' in $$props) $$invalidate(0, ignoredFolders = $$props.ignoredFolders); + if ('removeFolder' in $$props) $$invalidate(1, removeFolder = $$props.removeFolder); + }; + + return [ignoredFolders, removeFolder, list, click_handler, div_binding]; +} + +class Settings_ignored_folders extends SvelteComponent { + constructor(options) { + super(); + init(this, options, instance, create_fragment, safe_not_equal, { ignoredFolders: 0, removeFolder: 1 }); + } +} + +class BrokenLinksSettingsTab extends obsidian.PluginSettingTab { + constructor(app, plugin) { + super(app, plugin); + this.plugin = plugin; + } + display() { + const { containerEl } = this; + containerEl.empty(); + containerEl.addClass("broken-links-settings"); + this.addLinkSeparationSetting(); + this.addIgnoreFoldersSetting(); + } + addLinkSeparationSetting() { + const { containerEl } = this; + new obsidian.Setting(containerEl) + .setName("Consolidate links") + .setDesc("Links to the same file/heading but with different display names will be grouped together in the link view, resulting in a shorter list.") + .addToggle((toggle) => { + toggle.setValue(this.plugin.settings.consolidateLinks).onChange((value) => __awaiter(this, void 0, void 0, function* () { + // Update settings + this.plugin.settings.consolidateLinks = value; + yield this.plugin.saveSettings(); + // Force refresh of broken links panel + yield this.plugin.updateView(); + // Refresh settings view + this.display(); + })); + }); + } + addIgnoreFoldersSetting() { + const { containerEl } = this; + let search; + new obsidian.Setting(containerEl) + .setName("Ignore folders") + .setDesc("Folders (and their subfolders) listed here will not be searched for broken links.") + .addSearch((comp) => { + search = comp; + new FolderSuggest(this.plugin.app, comp.inputEl); + comp.setPlaceholder("Example: folder 1/folder 2"); + }) + .addExtraButton((comp) => { + comp.setIcon("plus-circle") + .setTooltip("Add folder") + .onClick(() => __awaiter(this, void 0, void 0, function* () { + if (search) { + const folder = search.getValue(); + if (folder.trim().length > 0) { + // If it's already in the list, remove it, then re-add it (effectively moving it to the top) + if (this.plugin.settings.ignoredFolders.contains(folder)) { + this.plugin.settings.ignoredFolders.remove(folder); + } + // Add the folder to the top of the list + this.plugin.settings.ignoredFolders.splice(0, 0, folder); + // Save the settings + yield this.plugin.saveSettings(); + // Force refresh of broken links panel + yield this.plugin.updateView(); + // Refresh settings view + this.display(); + } + } + })); + }); + // List ignored folders + const folderList = new Settings_ignored_folders({ + target: containerEl, + props: { + ignoredFolders: this.plugin.settings.ignoredFolders, + removeFolder: (folder) => __awaiter(this, void 0, void 0, function* () { + this.plugin.settings.ignoredFolders.remove(folder); + // Save the settings + yield this.plugin.saveSettings(); + // Force refresh of broken links panel + yield this.plugin.updateView(); + // Update list + folderList.$set({ + ignoredFolders: this.plugin.settings.ignoredFolders, + }); + }), + }, + }); + } +} + +var re$4 = {exports: {}}; + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +const SEMVER_SPEC_VERSION = '2.0.0'; + +const MAX_LENGTH$1 = 256; +const MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER || +/* istanbul ignore next */ 9007199254740991; + +// Max safe segment length for coercion. +const MAX_SAFE_COMPONENT_LENGTH = 16; + +// Max safe length for a build identifier. The max length minus 6 characters for +// the shortest version with a build 0.0.0+BUILD. +const MAX_SAFE_BUILD_LENGTH = MAX_LENGTH$1 - 6; + +const RELEASE_TYPES = [ + 'major', + 'premajor', + 'minor', + 'preminor', + 'patch', + 'prepatch', + 'prerelease', +]; + +var constants$1 = { + MAX_LENGTH: MAX_LENGTH$1, + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_SAFE_INTEGER: MAX_SAFE_INTEGER$1, + RELEASE_TYPES, + SEMVER_SPEC_VERSION, + FLAG_INCLUDE_PRERELEASE: 0b001, + FLAG_LOOSE: 0b010, +}; + +const debug$3 = ( + typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG) +) ? (...args) => console.error('SEMVER', ...args) + : () => {}; + +var debug_1 = debug$3; + +(function (module, exports) { +const { + MAX_SAFE_COMPONENT_LENGTH, + MAX_SAFE_BUILD_LENGTH, + MAX_LENGTH, +} = constants$1; +const debug = debug_1; +exports = module.exports = {}; + +// The actual regexps go on exports.re +const re = exports.re = []; +const safeRe = exports.safeRe = []; +const src = exports.src = []; +const t = exports.t = {}; +let R = 0; + +const LETTERDASHNUMBER = '[a-zA-Z0-9-]'; + +// Replace some greedy regex tokens to prevent regex dos issues. These regex are +// used internally via the safeRe object since all inputs in this library get +// normalized first to trim and collapse all extra whitespace. The original +// regexes are exported for userland consumption and lower level usage. A +// future breaking change could export the safer regex only with a note that +// all input should have extra whitespace removed. +const safeRegexReplacements = [ + ['\\s', 1], + ['\\d', MAX_LENGTH], + [LETTERDASHNUMBER, MAX_SAFE_BUILD_LENGTH], +]; + +const makeSafeRegex = (value) => { + for (const [token, max] of safeRegexReplacements) { + value = value + .split(`${token}*`).join(`${token}{0,${max}}`) + .split(`${token}+`).join(`${token}{1,${max}}`); + } + return value +}; + +const createToken = (name, value, isGlobal) => { + const safe = makeSafeRegex(value); + const index = R++; + debug(name, index, value); + t[name] = index; + src[index] = value; + re[index] = new RegExp(value, isGlobal ? 'g' : undefined); + safeRe[index] = new RegExp(safe, isGlobal ? 'g' : undefined); +}; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*'); +createToken('NUMERICIDENTIFIERLOOSE', '\\d+'); + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +createToken('NONNUMERICIDENTIFIER', `\\d*[a-zA-Z-]${LETTERDASHNUMBER}*`); + +// ## Main Version +// Three dot-separated numeric identifiers. + +createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})`); + +createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})`); + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] +}|${src[t.NONNUMERICIDENTIFIER]})`); + +createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] +}|${src[t.NONNUMERICIDENTIFIER]})`); + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] +}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`); + +createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] +}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`); + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +createToken('BUILDIDENTIFIER', `${LETTERDASHNUMBER}+`); + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] +}(?:\\.${src[t.BUILDIDENTIFIER]})*))`); + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +createToken('FULLPLAIN', `v?${src[t.MAINVERSION] +}${src[t.PRERELEASE]}?${ + src[t.BUILD]}?`); + +createToken('FULL', `^${src[t.FULLPLAIN]}$`); + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] +}${src[t.PRERELEASELOOSE]}?${ + src[t.BUILD]}?`); + +createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`); + +createToken('GTLT', '((?:<|>)?=?)'); + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`); +createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`); + +createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:${src[t.PRERELEASE]})?${ + src[t.BUILD]}?` + + `)?)?`); + +createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:${src[t.PRERELEASELOOSE]})?${ + src[t.BUILD]}?` + + `)?)?`); + +createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`); +createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`); + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +createToken('COERCEPLAIN', `${'(^|[^\\d])' + + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?`); +createToken('COERCE', `${src[t.COERCEPLAIN]}(?:$|[^\\d])`); +createToken('COERCEFULL', src[t.COERCEPLAIN] + + `(?:${src[t.PRERELEASE]})?` + + `(?:${src[t.BUILD]})?` + + `(?:$|[^\\d])`); +createToken('COERCERTL', src[t.COERCE], true); +createToken('COERCERTLFULL', src[t.COERCEFULL], true); + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +createToken('LONETILDE', '(?:~>?)'); + +createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true); +exports.tildeTrimReplace = '$1~'; + +createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`); +createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`); + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +createToken('LONECARET', '(?:\\^)'); + +createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true); +exports.caretTrimReplace = '$1^'; + +createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`); +createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`); + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`); +createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`); + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] +}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true); +exports.comparatorTrimReplace = '$1$2$3'; + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAIN]})` + + `\\s*$`); + +createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAINLOOSE]})` + + `\\s*$`); + +// Star ranges basically just allow anything at all. +createToken('STAR', '(<|>)?=?\\s*\\*'); +// >=0.0.0 is like a star +createToken('GTE0', '^\\s*>=\\s*0\\.0\\.0\\s*$'); +createToken('GTE0PRE', '^\\s*>=\\s*0\\.0\\.0-0\\s*$'); +}(re$4, re$4.exports)); + +// parse out just the options we care about +const looseOption = Object.freeze({ loose: true }); +const emptyOpts = Object.freeze({ }); +const parseOptions$3 = options => { + if (!options) { + return emptyOpts + } + + if (typeof options !== 'object') { + return looseOption + } + + return options +}; +var parseOptions_1 = parseOptions$3; + +const numeric = /^[0-9]+$/; +const compareIdentifiers$1 = (a, b) => { + const anum = numeric.test(a); + const bnum = numeric.test(b); + + if (anum && bnum) { + a = +a; + b = +b; + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +}; + +const rcompareIdentifiers = (a, b) => compareIdentifiers$1(b, a); + +var identifiers$1 = { + compareIdentifiers: compareIdentifiers$1, + rcompareIdentifiers, +}; + +const debug$2 = debug_1; +const { MAX_LENGTH, MAX_SAFE_INTEGER } = constants$1; +const { safeRe: re$3, t: t$3 } = re$4.exports; + +const parseOptions$2 = parseOptions_1; +const { compareIdentifiers } = identifiers$1; +class SemVer$f { + constructor (version, options) { + options = parseOptions$2(options); + + if (version instanceof SemVer$f) { + if (version.loose === !!options.loose && + version.includePrerelease === !!options.includePrerelease) { + return version + } else { + version = version.version; + } + } else if (typeof version !== 'string') { + throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version}".`) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ) + } + + debug$2('SemVer', version, options); + this.options = options; + this.loose = !!options.loose; + // this isn't actually relevant for versions, but keep it so that we + // don't run into trouble passing this.options around. + this.includePrerelease = !!options.includePrerelease; + + const m = version.trim().match(options.loose ? re$3[t$3.LOOSE] : re$3[t$3.FULL]); + + if (!m) { + throw new TypeError(`Invalid Version: ${version}`) + } + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = []; + } else { + this.prerelease = m[4].split('.').map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }); + } + + this.build = m[5] ? m[5].split('.') : []; + this.format(); + } + + format () { + this.version = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease.length) { + this.version += `-${this.prerelease.join('.')}`; + } + return this.version + } + + toString () { + return this.version + } + + compare (other) { + debug$2('SemVer.compare', this.version, this.options, other); + if (!(other instanceof SemVer$f)) { + if (typeof other === 'string' && other === this.version) { + return 0 + } + other = new SemVer$f(other, this.options); + } + + if (other.version === this.version) { + return 0 + } + + return this.compareMain(other) || this.comparePre(other) + } + + compareMain (other) { + if (!(other instanceof SemVer$f)) { + other = new SemVer$f(other, this.options); + } + + return ( + compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) + ) + } + + comparePre (other) { + if (!(other instanceof SemVer$f)) { + other = new SemVer$f(other, this.options); + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + let i = 0; + do { + const a = this.prerelease[i]; + const b = other.prerelease[i]; + debug$2('prerelease compare', i, a, b); + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + compareBuild (other) { + if (!(other instanceof SemVer$f)) { + other = new SemVer$f(other, this.options); + } + + let i = 0; + do { + const a = this.build[i]; + const b = other.build[i]; + debug$2('prerelease compare', i, a, b); + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc (release, identifier, identifierBase) { + switch (release) { + case 'premajor': + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc('pre', identifier, identifierBase); + break + case 'preminor': + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc('pre', identifier, identifierBase); + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0; + this.inc('patch', identifier, identifierBase); + this.inc('pre', identifier, identifierBase); + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier, identifierBase); + } + this.inc('pre', identifier, identifierBase); + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if ( + this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0 + ) { + this.major++; + } + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++; + } + this.patch = 0; + this.prerelease = []; + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++; + } + this.prerelease = []; + break + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case 'pre': { + const base = Number(identifierBase) ? 1 : 0; + + if (!identifier && identifierBase === false) { + throw new Error('invalid increment argument: identifier is empty') + } + + if (this.prerelease.length === 0) { + this.prerelease = [base]; + } else { + let i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) { + // didn't increment anything + if (identifier === this.prerelease.join('.') && identifierBase === false) { + throw new Error('invalid increment argument: identifier already exists') + } + this.prerelease.push(base); + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + let prerelease = [identifier, base]; + if (identifierBase === false) { + prerelease = [identifier]; + } + if (compareIdentifiers(this.prerelease[0], identifier) === 0) { + if (isNaN(this.prerelease[1])) { + this.prerelease = prerelease; + } + } else { + this.prerelease = prerelease; + } + } + break + } + default: + throw new Error(`invalid increment argument: ${release}`) + } + this.raw = this.format(); + if (this.build.length) { + this.raw += `+${this.build.join('.')}`; + } + return this + } +} + +var semver$1 = SemVer$f; + +const SemVer$e = semver$1; +const parse$6 = (version, options, throwErrors = false) => { + if (version instanceof SemVer$e) { + return version + } + try { + return new SemVer$e(version, options) + } catch (er) { + if (!throwErrors) { + return null + } + throw er + } +}; + +var parse_1 = parse$6; + +const parse$5 = parse_1; +const valid$2 = (version, options) => { + const v = parse$5(version, options); + return v ? v.version : null +}; +var valid_1 = valid$2; + +const parse$4 = parse_1; +const clean$1 = (version, options) => { + const s = parse$4(version.trim().replace(/^[=v]+/, ''), options); + return s ? s.version : null +}; +var clean_1 = clean$1; + +const SemVer$d = semver$1; + +const inc$1 = (version, release, options, identifier, identifierBase) => { + if (typeof (options) === 'string') { + identifierBase = identifier; + identifier = options; + options = undefined; + } + + try { + return new SemVer$d( + version instanceof SemVer$d ? version.version : version, + options + ).inc(release, identifier, identifierBase).version + } catch (er) { + return null + } +}; +var inc_1 = inc$1; + +const parse$3 = parse_1; + +const diff$1 = (version1, version2) => { + const v1 = parse$3(version1, null, true); + const v2 = parse$3(version2, null, true); + const comparison = v1.compare(v2); + + if (comparison === 0) { + return null + } + + const v1Higher = comparison > 0; + const highVersion = v1Higher ? v1 : v2; + const lowVersion = v1Higher ? v2 : v1; + const highHasPre = !!highVersion.prerelease.length; + const lowHasPre = !!lowVersion.prerelease.length; + + if (lowHasPre && !highHasPre) { + // Going from prerelease -> no prerelease requires some special casing + + // If the low version has only a major, then it will always be a major + // Some examples: + // 1.0.0-1 -> 1.0.0 + // 1.0.0-1 -> 1.1.1 + // 1.0.0-1 -> 2.0.0 + if (!lowVersion.patch && !lowVersion.minor) { + return 'major' + } + + // Otherwise it can be determined by checking the high version + + if (highVersion.patch) { + // anything higher than a patch bump would result in the wrong version + return 'patch' + } + + if (highVersion.minor) { + // anything higher than a minor bump would result in the wrong version + return 'minor' + } + + // bumping major/minor/patch all have same result + return 'major' + } + + // add the `pre` prefix if we are going to a prerelease version + const prefix = highHasPre ? 'pre' : ''; + + if (v1.major !== v2.major) { + return prefix + 'major' + } + + if (v1.minor !== v2.minor) { + return prefix + 'minor' + } + + if (v1.patch !== v2.patch) { + return prefix + 'patch' + } + + // high and low are preleases + return 'prerelease' +}; + +var diff_1 = diff$1; + +const SemVer$c = semver$1; +const major$1 = (a, loose) => new SemVer$c(a, loose).major; +var major_1 = major$1; + +const SemVer$b = semver$1; +const minor$1 = (a, loose) => new SemVer$b(a, loose).minor; +var minor_1 = minor$1; + +const SemVer$a = semver$1; +const patch$1 = (a, loose) => new SemVer$a(a, loose).patch; +var patch_1 = patch$1; + +const parse$2 = parse_1; +const prerelease$1 = (version, options) => { + const parsed = parse$2(version, options); + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +}; +var prerelease_1 = prerelease$1; + +const SemVer$9 = semver$1; +const compare$b = (a, b, loose) => + new SemVer$9(a, loose).compare(new SemVer$9(b, loose)); + +var compare_1 = compare$b; + +const compare$a = compare_1; +const rcompare$1 = (a, b, loose) => compare$a(b, a, loose); +var rcompare_1 = rcompare$1; + +const compare$9 = compare_1; +const compareLoose$1 = (a, b) => compare$9(a, b, true); +var compareLoose_1 = compareLoose$1; + +const SemVer$8 = semver$1; +const compareBuild$3 = (a, b, loose) => { + const versionA = new SemVer$8(a, loose); + const versionB = new SemVer$8(b, loose); + return versionA.compare(versionB) || versionA.compareBuild(versionB) +}; +var compareBuild_1 = compareBuild$3; + +const compareBuild$2 = compareBuild_1; +const sort$1 = (list, loose) => list.sort((a, b) => compareBuild$2(a, b, loose)); +var sort_1 = sort$1; + +const compareBuild$1 = compareBuild_1; +const rsort$1 = (list, loose) => list.sort((a, b) => compareBuild$1(b, a, loose)); +var rsort_1 = rsort$1; + +const compare$8 = compare_1; +const gt$4 = (a, b, loose) => compare$8(a, b, loose) > 0; +var gt_1 = gt$4; + +const compare$7 = compare_1; +const lt$3 = (a, b, loose) => compare$7(a, b, loose) < 0; +var lt_1 = lt$3; + +const compare$6 = compare_1; +const eq$2 = (a, b, loose) => compare$6(a, b, loose) === 0; +var eq_1 = eq$2; + +const compare$5 = compare_1; +const neq$2 = (a, b, loose) => compare$5(a, b, loose) !== 0; +var neq_1 = neq$2; + +const compare$4 = compare_1; +const gte$3 = (a, b, loose) => compare$4(a, b, loose) >= 0; +var gte_1 = gte$3; + +const compare$3 = compare_1; +const lte$3 = (a, b, loose) => compare$3(a, b, loose) <= 0; +var lte_1 = lte$3; + +const eq$1 = eq_1; +const neq$1 = neq_1; +const gt$3 = gt_1; +const gte$2 = gte_1; +const lt$2 = lt_1; +const lte$2 = lte_1; + +const cmp$2 = (a, op, b, loose) => { + switch (op) { + case '===': + if (typeof a === 'object') { + a = a.version; + } + if (typeof b === 'object') { + b = b.version; + } + return a === b + + case '!==': + if (typeof a === 'object') { + a = a.version; + } + if (typeof b === 'object') { + b = b.version; + } + return a !== b + + case '': + case '=': + case '==': + return eq$1(a, b, loose) + + case '!=': + return neq$1(a, b, loose) + + case '>': + return gt$3(a, b, loose) + + case '>=': + return gte$2(a, b, loose) + + case '<': + return lt$2(a, b, loose) + + case '<=': + return lte$2(a, b, loose) + + default: + throw new TypeError(`Invalid operator: ${op}`) + } +}; +var cmp_1 = cmp$2; + +const SemVer$7 = semver$1; +const parse$1 = parse_1; +const { safeRe: re$2, t: t$2 } = re$4.exports; + +const coerce$1 = (version, options) => { + if (version instanceof SemVer$7) { + return version + } + + if (typeof version === 'number') { + version = String(version); + } + + if (typeof version !== 'string') { + return null + } + + options = options || {}; + + let match = null; + if (!options.rtl) { + match = version.match(options.includePrerelease ? re$2[t$2.COERCEFULL] : re$2[t$2.COERCE]); + } else { + // Find the right-most coercible string that does not share + // a terminus with a more left-ward coercible string. + // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' + // With includePrerelease option set, '1.2.3.4-rc' wants to coerce '2.3.4-rc', not '2.3.4' + // + // Walk through the string checking with a /g regexp + // Manually set the index so as to pick up overlapping matches. + // Stop when we get a match that ends at the string end, since no + // coercible string can be more right-ward without the same terminus. + const coerceRtlRegex = options.includePrerelease ? re$2[t$2.COERCERTLFULL] : re$2[t$2.COERCERTL]; + let next; + while ((next = coerceRtlRegex.exec(version)) && + (!match || match.index + match[0].length !== version.length) + ) { + if (!match || + next.index + next[0].length !== match.index + match[0].length) { + match = next; + } + coerceRtlRegex.lastIndex = next.index + next[1].length + next[2].length; + } + // leave it in a clean state + coerceRtlRegex.lastIndex = -1; + } + + if (match === null) { + return null + } + + const major = match[2]; + const minor = match[3] || '0'; + const patch = match[4] || '0'; + const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : ''; + const build = options.includePrerelease && match[6] ? `+${match[6]}` : ''; + + return parse$1(`${major}.${minor}.${patch}${prerelease}${build}`, options) +}; +var coerce_1 = coerce$1; + +var yallist = Yallist$1; + +Yallist$1.Node = Node; +Yallist$1.create = Yallist$1; + +function Yallist$1 (list) { + var self = this; + if (!(self instanceof Yallist$1)) { + self = new Yallist$1(); + } + + self.tail = null; + self.head = null; + self.length = 0; + + if (list && typeof list.forEach === 'function') { + list.forEach(function (item) { + self.push(item); + }); + } else if (arguments.length > 0) { + for (var i = 0, l = arguments.length; i < l; i++) { + self.push(arguments[i]); + } + } + + return self +} + +Yallist$1.prototype.removeNode = function (node) { + if (node.list !== this) { + throw new Error('removing node which does not belong to this list') + } + + var next = node.next; + var prev = node.prev; + + if (next) { + next.prev = prev; + } + + if (prev) { + prev.next = next; + } + + if (node === this.head) { + this.head = next; + } + if (node === this.tail) { + this.tail = prev; + } + + node.list.length--; + node.next = null; + node.prev = null; + node.list = null; + + return next +}; + +Yallist$1.prototype.unshiftNode = function (node) { + if (node === this.head) { + return + } + + if (node.list) { + node.list.removeNode(node); + } + + var head = this.head; + node.list = this; + node.next = head; + if (head) { + head.prev = node; + } + + this.head = node; + if (!this.tail) { + this.tail = node; + } + this.length++; +}; + +Yallist$1.prototype.pushNode = function (node) { + if (node === this.tail) { + return + } + + if (node.list) { + node.list.removeNode(node); + } + + var tail = this.tail; + node.list = this; + node.prev = tail; + if (tail) { + tail.next = node; + } + + this.tail = node; + if (!this.head) { + this.head = node; + } + this.length++; +}; + +Yallist$1.prototype.push = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + push(this, arguments[i]); + } + return this.length +}; + +Yallist$1.prototype.unshift = function () { + for (var i = 0, l = arguments.length; i < l; i++) { + unshift(this, arguments[i]); + } + return this.length +}; + +Yallist$1.prototype.pop = function () { + if (!this.tail) { + return undefined + } + + var res = this.tail.value; + this.tail = this.tail.prev; + if (this.tail) { + this.tail.next = null; + } else { + this.head = null; + } + this.length--; + return res +}; + +Yallist$1.prototype.shift = function () { + if (!this.head) { + return undefined + } + + var res = this.head.value; + this.head = this.head.next; + if (this.head) { + this.head.prev = null; + } else { + this.tail = null; + } + this.length--; + return res +}; + +Yallist$1.prototype.forEach = function (fn, thisp) { + thisp = thisp || this; + for (var walker = this.head, i = 0; walker !== null; i++) { + fn.call(thisp, walker.value, i, this); + walker = walker.next; + } +}; + +Yallist$1.prototype.forEachReverse = function (fn, thisp) { + thisp = thisp || this; + for (var walker = this.tail, i = this.length - 1; walker !== null; i--) { + fn.call(thisp, walker.value, i, this); + walker = walker.prev; + } +}; + +Yallist$1.prototype.get = function (n) { + for (var i = 0, walker = this.head; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.next; + } + if (i === n && walker !== null) { + return walker.value + } +}; + +Yallist$1.prototype.getReverse = function (n) { + for (var i = 0, walker = this.tail; walker !== null && i < n; i++) { + // abort out of the list early if we hit a cycle + walker = walker.prev; + } + if (i === n && walker !== null) { + return walker.value + } +}; + +Yallist$1.prototype.map = function (fn, thisp) { + thisp = thisp || this; + var res = new Yallist$1(); + for (var walker = this.head; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)); + walker = walker.next; + } + return res +}; + +Yallist$1.prototype.mapReverse = function (fn, thisp) { + thisp = thisp || this; + var res = new Yallist$1(); + for (var walker = this.tail; walker !== null;) { + res.push(fn.call(thisp, walker.value, this)); + walker = walker.prev; + } + return res +}; + +Yallist$1.prototype.reduce = function (fn, initial) { + var acc; + var walker = this.head; + if (arguments.length > 1) { + acc = initial; + } else if (this.head) { + walker = this.head.next; + acc = this.head.value; + } else { + throw new TypeError('Reduce of empty list with no initial value') + } + + for (var i = 0; walker !== null; i++) { + acc = fn(acc, walker.value, i); + walker = walker.next; + } + + return acc +}; + +Yallist$1.prototype.reduceReverse = function (fn, initial) { + var acc; + var walker = this.tail; + if (arguments.length > 1) { + acc = initial; + } else if (this.tail) { + walker = this.tail.prev; + acc = this.tail.value; + } else { + throw new TypeError('Reduce of empty list with no initial value') + } + + for (var i = this.length - 1; walker !== null; i--) { + acc = fn(acc, walker.value, i); + walker = walker.prev; + } + + return acc +}; + +Yallist$1.prototype.toArray = function () { + var arr = new Array(this.length); + for (var i = 0, walker = this.head; walker !== null; i++) { + arr[i] = walker.value; + walker = walker.next; + } + return arr +}; + +Yallist$1.prototype.toArrayReverse = function () { + var arr = new Array(this.length); + for (var i = 0, walker = this.tail; walker !== null; i++) { + arr[i] = walker.value; + walker = walker.prev; + } + return arr +}; + +Yallist$1.prototype.slice = function (from, to) { + to = to || this.length; + if (to < 0) { + to += this.length; + } + from = from || 0; + if (from < 0) { + from += this.length; + } + var ret = new Yallist$1(); + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0; + } + if (to > this.length) { + to = this.length; + } + for (var i = 0, walker = this.head; walker !== null && i < from; i++) { + walker = walker.next; + } + for (; walker !== null && i < to; i++, walker = walker.next) { + ret.push(walker.value); + } + return ret +}; + +Yallist$1.prototype.sliceReverse = function (from, to) { + to = to || this.length; + if (to < 0) { + to += this.length; + } + from = from || 0; + if (from < 0) { + from += this.length; + } + var ret = new Yallist$1(); + if (to < from || to < 0) { + return ret + } + if (from < 0) { + from = 0; + } + if (to > this.length) { + to = this.length; + } + for (var i = this.length, walker = this.tail; walker !== null && i > to; i--) { + walker = walker.prev; + } + for (; walker !== null && i > from; i--, walker = walker.prev) { + ret.push(walker.value); + } + return ret +}; + +Yallist$1.prototype.splice = function (start, deleteCount, ...nodes) { + if (start > this.length) { + start = this.length - 1; + } + if (start < 0) { + start = this.length + start; + } + + for (var i = 0, walker = this.head; walker !== null && i < start; i++) { + walker = walker.next; + } + + var ret = []; + for (var i = 0; walker && i < deleteCount; i++) { + ret.push(walker.value); + walker = this.removeNode(walker); + } + if (walker === null) { + walker = this.tail; + } + + if (walker !== this.head && walker !== this.tail) { + walker = walker.prev; + } + + for (var i = 0; i < nodes.length; i++) { + walker = insert(this, walker, nodes[i]); + } + return ret; +}; + +Yallist$1.prototype.reverse = function () { + var head = this.head; + var tail = this.tail; + for (var walker = head; walker !== null; walker = walker.prev) { + var p = walker.prev; + walker.prev = walker.next; + walker.next = p; + } + this.head = tail; + this.tail = head; + return this +}; + +function insert (self, node, value) { + var inserted = node === self.head ? + new Node(value, null, node, self) : + new Node(value, node, node.next, self); + + if (inserted.next === null) { + self.tail = inserted; + } + if (inserted.prev === null) { + self.head = inserted; + } + + self.length++; + + return inserted +} + +function push (self, item) { + self.tail = new Node(item, self.tail, null, self); + if (!self.head) { + self.head = self.tail; + } + self.length++; +} + +function unshift (self, item) { + self.head = new Node(item, null, self.head, self); + if (!self.tail) { + self.tail = self.head; + } + self.length++; +} + +function Node (value, prev, next, list) { + if (!(this instanceof Node)) { + return new Node(value, prev, next, list) + } + + this.list = list; + this.value = value; + + if (prev) { + prev.next = this; + this.prev = prev; + } else { + this.prev = null; + } + + if (next) { + next.prev = this; + this.next = next; + } else { + this.next = null; + } +} + +try { + // add if support for Symbol.iterator is present + require('./iterator.js')(Yallist$1); +} catch (er) {} + +// A linked list to keep track of recently-used-ness +const Yallist = yallist; + +const MAX = Symbol('max'); +const LENGTH = Symbol('length'); +const LENGTH_CALCULATOR = Symbol('lengthCalculator'); +const ALLOW_STALE = Symbol('allowStale'); +const MAX_AGE = Symbol('maxAge'); +const DISPOSE = Symbol('dispose'); +const NO_DISPOSE_ON_SET = Symbol('noDisposeOnSet'); +const LRU_LIST = Symbol('lruList'); +const CACHE = Symbol('cache'); +const UPDATE_AGE_ON_GET = Symbol('updateAgeOnGet'); + +const naiveLength = () => 1; + +// lruList is a yallist where the head is the youngest +// item, and the tail is the oldest. the list contains the Hit +// objects as the entries. +// Each Hit object has a reference to its Yallist.Node. This +// never changes. +// +// cache is a Map (or PseudoMap) that matches the keys to +// the Yallist.Node object. +class LRUCache { + constructor (options) { + if (typeof options === 'number') + options = { max: options }; + + if (!options) + options = {}; + + if (options.max && (typeof options.max !== 'number' || options.max < 0)) + throw new TypeError('max must be a non-negative number') + // Kind of weird to have a default max of Infinity, but oh well. + this[MAX] = options.max || Infinity; + + const lc = options.length || naiveLength; + this[LENGTH_CALCULATOR] = (typeof lc !== 'function') ? naiveLength : lc; + this[ALLOW_STALE] = options.stale || false; + if (options.maxAge && typeof options.maxAge !== 'number') + throw new TypeError('maxAge must be a number') + this[MAX_AGE] = options.maxAge || 0; + this[DISPOSE] = options.dispose; + this[NO_DISPOSE_ON_SET] = options.noDisposeOnSet || false; + this[UPDATE_AGE_ON_GET] = options.updateAgeOnGet || false; + this.reset(); + } + + // resize the cache when the max changes. + set max (mL) { + if (typeof mL !== 'number' || mL < 0) + throw new TypeError('max must be a non-negative number') + + this[MAX] = mL || Infinity; + trim(this); + } + get max () { + return this[MAX] + } + + set allowStale (allowStale) { + this[ALLOW_STALE] = !!allowStale; + } + get allowStale () { + return this[ALLOW_STALE] + } + + set maxAge (mA) { + if (typeof mA !== 'number') + throw new TypeError('maxAge must be a non-negative number') + + this[MAX_AGE] = mA; + trim(this); + } + get maxAge () { + return this[MAX_AGE] + } + + // resize the cache when the lengthCalculator changes. + set lengthCalculator (lC) { + if (typeof lC !== 'function') + lC = naiveLength; + + if (lC !== this[LENGTH_CALCULATOR]) { + this[LENGTH_CALCULATOR] = lC; + this[LENGTH] = 0; + this[LRU_LIST].forEach(hit => { + hit.length = this[LENGTH_CALCULATOR](hit.value, hit.key); + this[LENGTH] += hit.length; + }); + } + trim(this); + } + get lengthCalculator () { return this[LENGTH_CALCULATOR] } + + get length () { return this[LENGTH] } + get itemCount () { return this[LRU_LIST].length } + + rforEach (fn, thisp) { + thisp = thisp || this; + for (let walker = this[LRU_LIST].tail; walker !== null;) { + const prev = walker.prev; + forEachStep(this, fn, walker, thisp); + walker = prev; + } + } + + forEach (fn, thisp) { + thisp = thisp || this; + for (let walker = this[LRU_LIST].head; walker !== null;) { + const next = walker.next; + forEachStep(this, fn, walker, thisp); + walker = next; + } + } + + keys () { + return this[LRU_LIST].toArray().map(k => k.key) + } + + values () { + return this[LRU_LIST].toArray().map(k => k.value) + } + + reset () { + if (this[DISPOSE] && + this[LRU_LIST] && + this[LRU_LIST].length) { + this[LRU_LIST].forEach(hit => this[DISPOSE](hit.key, hit.value)); + } + + this[CACHE] = new Map(); // hash of items by key + this[LRU_LIST] = new Yallist(); // list of items in order of use recency + this[LENGTH] = 0; // length of items in the list + } + + dump () { + return this[LRU_LIST].map(hit => + isStale(this, hit) ? false : { + k: hit.key, + v: hit.value, + e: hit.now + (hit.maxAge || 0) + }).toArray().filter(h => h) + } + + dumpLru () { + return this[LRU_LIST] + } + + set (key, value, maxAge) { + maxAge = maxAge || this[MAX_AGE]; + + if (maxAge && typeof maxAge !== 'number') + throw new TypeError('maxAge must be a number') + + const now = maxAge ? Date.now() : 0; + const len = this[LENGTH_CALCULATOR](value, key); + + if (this[CACHE].has(key)) { + if (len > this[MAX]) { + del(this, this[CACHE].get(key)); + return false + } + + const node = this[CACHE].get(key); + const item = node.value; + + // dispose of the old one before overwriting + // split out into 2 ifs for better coverage tracking + if (this[DISPOSE]) { + if (!this[NO_DISPOSE_ON_SET]) + this[DISPOSE](key, item.value); + } + + item.now = now; + item.maxAge = maxAge; + item.value = value; + this[LENGTH] += len - item.length; + item.length = len; + this.get(key); + trim(this); + return true + } + + const hit = new Entry(key, value, len, now, maxAge); + + // oversized objects fall out of cache automatically. + if (hit.length > this[MAX]) { + if (this[DISPOSE]) + this[DISPOSE](key, value); + + return false + } + + this[LENGTH] += hit.length; + this[LRU_LIST].unshift(hit); + this[CACHE].set(key, this[LRU_LIST].head); + trim(this); + return true + } + + has (key) { + if (!this[CACHE].has(key)) return false + const hit = this[CACHE].get(key).value; + return !isStale(this, hit) + } + + get (key) { + return get(this, key, true) + } + + peek (key) { + return get(this, key, false) + } + + pop () { + const node = this[LRU_LIST].tail; + if (!node) + return null + + del(this, node); + return node.value + } + + del (key) { + del(this, this[CACHE].get(key)); + } + + load (arr) { + // reset the cache + this.reset(); + + const now = Date.now(); + // A previous serialized cache has the most recent items first + for (let l = arr.length - 1; l >= 0; l--) { + const hit = arr[l]; + const expiresAt = hit.e || 0; + if (expiresAt === 0) + // the item was created without expiration in a non aged cache + this.set(hit.k, hit.v); + else { + const maxAge = expiresAt - now; + // dont add already expired items + if (maxAge > 0) { + this.set(hit.k, hit.v, maxAge); + } + } + } + } + + prune () { + this[CACHE].forEach((value, key) => get(this, key, false)); + } +} + +const get = (self, key, doUse) => { + const node = self[CACHE].get(key); + if (node) { + const hit = node.value; + if (isStale(self, hit)) { + del(self, node); + if (!self[ALLOW_STALE]) + return undefined + } else { + if (doUse) { + if (self[UPDATE_AGE_ON_GET]) + node.value.now = Date.now(); + self[LRU_LIST].unshiftNode(node); + } + } + return hit.value + } +}; + +const isStale = (self, hit) => { + if (!hit || (!hit.maxAge && !self[MAX_AGE])) + return false + + const diff = Date.now() - hit.now; + return hit.maxAge ? diff > hit.maxAge + : self[MAX_AGE] && (diff > self[MAX_AGE]) +}; + +const trim = self => { + if (self[LENGTH] > self[MAX]) { + for (let walker = self[LRU_LIST].tail; + self[LENGTH] > self[MAX] && walker !== null;) { + // We know that we're about to delete this one, and also + // what the next least recently used key will be, so just + // go ahead and set it now. + const prev = walker.prev; + del(self, walker); + walker = prev; + } + } +}; + +const del = (self, node) => { + if (node) { + const hit = node.value; + if (self[DISPOSE]) + self[DISPOSE](hit.key, hit.value); + + self[LENGTH] -= hit.length; + self[CACHE].delete(hit.key); + self[LRU_LIST].removeNode(node); + } +}; + +class Entry { + constructor (key, value, length, now, maxAge) { + this.key = key; + this.value = value; + this.length = length; + this.now = now; + this.maxAge = maxAge || 0; + } +} + +const forEachStep = (self, fn, node, thisp) => { + let hit = node.value; + if (isStale(self, hit)) { + del(self, node); + if (!self[ALLOW_STALE]) + hit = undefined; + } + if (hit) + fn.call(thisp, hit.value, hit.key, self); +}; + +var lruCache = LRUCache; + +// hoisted class for cyclic dependency +class Range$b { + constructor (range, options) { + options = parseOptions$1(options); + + if (range instanceof Range$b) { + if ( + range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease + ) { + return range + } else { + return new Range$b(range.raw, options) + } + } + + if (range instanceof Comparator$4) { + // just put it in the set and return + this.raw = range.value; + this.set = [[range]]; + this.format(); + return this + } + + this.options = options; + this.loose = !!options.loose; + this.includePrerelease = !!options.includePrerelease; + + // First reduce all whitespace as much as possible so we do not have to rely + // on potentially slow regexes like \s*. This is then stored and used for + // future error messages as well. + this.raw = range + .trim() + .split(/\s+/) + .join(' '); + + // First, split on || + this.set = this.raw + .split('||') + // map the range to a 2d array of comparators + .map(r => this.parseRange(r.trim())) + // throw out any comparator lists that are empty + // this generally means that it was not a valid range, which is allowed + // in loose mode, but will still throw if the WHOLE range is invalid. + .filter(c => c.length); + + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${this.raw}`) + } + + // if we have any that are not the null set, throw out null sets. + if (this.set.length > 1) { + // keep the first one, in case they're all null sets + const first = this.set[0]; + this.set = this.set.filter(c => !isNullSet(c[0])); + if (this.set.length === 0) { + this.set = [first]; + } else if (this.set.length > 1) { + // if we have any that are *, then the range is just * + for (const c of this.set) { + if (c.length === 1 && isAny(c[0])) { + this.set = [c]; + break + } + } + } + } + + this.format(); + } + + format () { + this.range = this.set + .map((comps) => comps.join(' ').trim()) + .join('||') + .trim(); + return this.range + } + + toString () { + return this.range + } + + parseRange (range) { + // memoize range parsing for performance. + // this is a very hot path, and fully deterministic. + const memoOpts = + (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | + (this.options.loose && FLAG_LOOSE); + const memoKey = memoOpts + ':' + range; + const cached = cache.get(memoKey); + if (cached) { + return cached + } + + const loose = this.options.loose; + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + const hr = loose ? re$1[t$1.HYPHENRANGELOOSE] : re$1[t$1.HYPHENRANGE]; + range = range.replace(hr, hyphenReplace(this.options.includePrerelease)); + debug$1('hyphen replace', range); + + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re$1[t$1.COMPARATORTRIM], comparatorTrimReplace); + debug$1('comparator trim', range); + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re$1[t$1.TILDETRIM], tildeTrimReplace); + debug$1('tilde trim', range); + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re$1[t$1.CARETTRIM], caretTrimReplace); + debug$1('caret trim', range); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + let rangeList = range + .split(' ') + .map(comp => parseComparator(comp, this.options)) + .join(' ') + .split(/\s+/) + // >=0.0.0 is equivalent to * + .map(comp => replaceGTE0(comp, this.options)); + + if (loose) { + // in loose mode, throw out any that are not valid comparators + rangeList = rangeList.filter(comp => { + debug$1('loose invalid filter', comp, this.options); + return !!comp.match(re$1[t$1.COMPARATORLOOSE]) + }); + } + debug$1('range list', rangeList); + + // if any comparators are the null set, then replace with JUST null set + // if more than one comparator, remove any * comparators + // also, don't include the same comparator more than once + const rangeMap = new Map(); + const comparators = rangeList.map(comp => new Comparator$4(comp, this.options)); + for (const comp of comparators) { + if (isNullSet(comp)) { + return [comp] + } + rangeMap.set(comp.value, comp); + } + if (rangeMap.size > 1 && rangeMap.has('')) { + rangeMap.delete(''); + } + + const result = [...rangeMap.values()]; + cache.set(memoKey, result); + return result + } + + intersects (range, options) { + if (!(range instanceof Range$b)) { + throw new TypeError('a Range is required') + } + + return this.set.some((thisComparators) => { + return ( + isSatisfiable(thisComparators, options) && + range.set.some((rangeComparators) => { + return ( + isSatisfiable(rangeComparators, options) && + thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options) + }) + }) + ) + }) + ) + }) + } + + // if ANY of the sets match ALL of its comparators, then pass + test (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + try { + version = new SemVer$6(version, this.options); + } catch (er) { + return false + } + } + + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false + } +} + +var range = Range$b; + +const LRU = lruCache; +const cache = new LRU({ max: 1000 }); + +const parseOptions$1 = parseOptions_1; +const Comparator$4 = comparator; +const debug$1 = debug_1; +const SemVer$6 = semver$1; +const { + safeRe: re$1, + t: t$1, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace, +} = re$4.exports; +const { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = constants$1; + +const isNullSet = c => c.value === '<0.0.0-0'; +const isAny = c => c.value === ''; + +// take a set of comparators and determine whether there +// exists a version which can satisfy it +const isSatisfiable = (comparators, options) => { + let result = true; + const remainingComparators = comparators.slice(); + let testComparator = remainingComparators.pop(); + + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options) + }); + + testComparator = remainingComparators.pop(); + } + + return result +}; + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +const parseComparator = (comp, options) => { + debug$1('comp', comp, options); + comp = replaceCarets(comp, options); + debug$1('caret', comp); + comp = replaceTildes(comp, options); + debug$1('tildes', comp); + comp = replaceXRanges(comp, options); + debug$1('xrange', comp); + comp = replaceStars(comp, options); + debug$1('stars', comp); + return comp +}; + +const isX = id => !id || id.toLowerCase() === 'x' || id === '*'; + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0-0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0-0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0-0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0-0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0-0 +// ~0.0.1 --> >=0.0.1 <0.1.0-0 +const replaceTildes = (comp, options) => { + return comp + .trim() + .split(/\s+/) + .map((c) => replaceTilde(c, options)) + .join(' ') +}; + +const replaceTilde = (comp, options) => { + const r = options.loose ? re$1[t$1.TILDELOOSE] : re$1[t$1.TILDE]; + return comp.replace(r, (_, M, m, p, pr) => { + debug$1('tilde', comp, _, M, m, p, pr); + let ret; + + if (isX(M)) { + ret = ''; + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0-0`; + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0-0 + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`; + } else if (pr) { + debug$1('replaceTilde pr', pr); + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0-0`; + } else { + // ~1.2.3 == >=1.2.3 <1.3.0-0 + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0-0`; + } + + debug$1('tilde return', ret); + return ret + }) +}; + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0-0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0-0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0-0 +// ^1.2.3 --> >=1.2.3 <2.0.0-0 +// ^1.2.0 --> >=1.2.0 <2.0.0-0 +// ^0.0.1 --> >=0.0.1 <0.0.2-0 +// ^0.1.0 --> >=0.1.0 <0.2.0-0 +const replaceCarets = (comp, options) => { + return comp + .trim() + .split(/\s+/) + .map((c) => replaceCaret(c, options)) + .join(' ') +}; + +const replaceCaret = (comp, options) => { + debug$1('caret', comp, options); + const r = options.loose ? re$1[t$1.CARETLOOSE] : re$1[t$1.CARET]; + const z = options.includePrerelease ? '-0' : ''; + return comp.replace(r, (_, M, m, p, pr) => { + debug$1('caret', comp, _, M, m, p, pr); + let ret; + + if (isX(M)) { + ret = ''; + } else if (isX(m)) { + ret = `>=${M}.0.0${z} <${+M + 1}.0.0-0`; + } else if (isX(p)) { + if (M === '0') { + ret = `>=${M}.${m}.0${z} <${M}.${+m + 1}.0-0`; + } else { + ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; + } + } else if (pr) { + debug$1('replaceCaret pr', pr); + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${+M + 1}.0.0-0`; + } + } else { + debug$1('no pr'); + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p + }${z} <${M}.${m}.${+p + 1}-0`; + } else { + ret = `>=${M}.${m}.${p + }${z} <${M}.${+m + 1}.0-0`; + } + } else { + ret = `>=${M}.${m}.${p + } <${+M + 1}.0.0-0`; + } + } + + debug$1('caret return', ret); + return ret + }) +}; + +const replaceXRanges = (comp, options) => { + debug$1('replaceXRanges', comp, options); + return comp + .split(/\s+/) + .map((c) => replaceXRange(c, options)) + .join(' ') +}; + +const replaceXRange = (comp, options) => { + comp = comp.trim(); + const r = options.loose ? re$1[t$1.XRANGELOOSE] : re$1[t$1.XRANGE]; + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug$1('xRange', comp, ret, gtlt, M, m, p, pr); + const xM = isX(M); + const xm = xM || isX(m); + const xp = xm || isX(p); + const anyX = xp; + + if (gtlt === '=' && anyX) { + gtlt = ''; + } + + // if we're including prereleases in the match, then we need + // to fix this to -0, the lowest possible prerelease value + pr = options.includePrerelease ? '-0' : ''; + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0-0'; + } else { + // nothing is forbidden + ret = '*'; + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0; + } + p = 0; + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + gtlt = '>='; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else { + m = +m + 1; + p = 0; + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<'; + if (xm) { + M = +M + 1; + } else { + m = +m + 1; + } + } + + if (gtlt === '<') { + pr = '-0'; + } + + ret = `${gtlt + M}.${m}.${p}${pr}`; + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0-0`; + } else if (xp) { + ret = `>=${M}.${m}.0${pr + } <${M}.${+m + 1}.0-0`; + } + + debug$1('xRange return', ret); + + return ret + }) +}; + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +const replaceStars = (comp, options) => { + debug$1('replaceStars', comp, options); + // Looseness is ignored here. star is always as loose as it gets! + return comp + .trim() + .replace(re$1[t$1.STAR], '') +}; + +const replaceGTE0 = (comp, options) => { + debug$1('replaceGTE0', comp, options); + return comp + .trim() + .replace(re$1[options.includePrerelease ? t$1.GTE0PRE : t$1.GTE0], '') +}; + +// This function is passed to string.replace(re[t.HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0-0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0-0 +const hyphenReplace = incPr => ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) => { + if (isX(fM)) { + from = ''; + } else if (isX(fm)) { + from = `>=${fM}.0.0${incPr ? '-0' : ''}`; + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0${incPr ? '-0' : ''}`; + } else if (fpr) { + from = `>=${from}`; + } else { + from = `>=${from}${incPr ? '-0' : ''}`; + } + + if (isX(tM)) { + to = ''; + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0-0`; + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0-0`; + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}`; + } else if (incPr) { + to = `<${tM}.${tm}.${+tp + 1}-0`; + } else { + to = `<=${to}`; + } + + return `${from} ${to}`.trim() +}; + +const testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (let i = 0; i < set.length; i++) { + debug$1(set[i].semver); + if (set[i].semver === Comparator$4.ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver; + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +}; + +const ANY$2 = Symbol('SemVer ANY'); +// hoisted class for cyclic dependency +class Comparator$3 { + static get ANY () { + return ANY$2 + } + + constructor (comp, options) { + options = parseOptions(options); + + if (comp instanceof Comparator$3) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value; + } + } + + comp = comp.trim().split(/\s+/).join(' '); + debug('comparator', comp, options); + this.options = options; + this.loose = !!options.loose; + this.parse(comp); + + if (this.semver === ANY$2) { + this.value = ''; + } else { + this.value = this.operator + this.semver.version; + } + + debug('comp', this); + } + + parse (comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; + const m = comp.match(r); + + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`) + } + + this.operator = m[1] !== undefined ? m[1] : ''; + if (this.operator === '=') { + this.operator = ''; + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY$2; + } else { + this.semver = new SemVer$5(m[2], this.options.loose); + } + } + + toString () { + return this.value + } + + test (version) { + debug('Comparator.test', version, this.options.loose); + + if (this.semver === ANY$2 || version === ANY$2) { + return true + } + + if (typeof version === 'string') { + try { + version = new SemVer$5(version, this.options); + } catch (er) { + return false + } + } + + return cmp$1(version, this.operator, this.semver, this.options) + } + + intersects (comp, options) { + if (!(comp instanceof Comparator$3)) { + throw new TypeError('a Comparator is required') + } + + if (this.operator === '') { + if (this.value === '') { + return true + } + return new Range$a(comp.value, options).test(this.value) + } else if (comp.operator === '') { + if (comp.value === '') { + return true + } + return new Range$a(this.value, options).test(comp.semver) + } + + options = parseOptions(options); + + // Special cases where nothing can possibly be lower + if (options.includePrerelease && + (this.value === '<0.0.0-0' || comp.value === '<0.0.0-0')) { + return false + } + if (!options.includePrerelease && + (this.value.startsWith('<0.0.0') || comp.value.startsWith('<0.0.0'))) { + return false + } + + // Same direction increasing (> or >=) + if (this.operator.startsWith('>') && comp.operator.startsWith('>')) { + return true + } + // Same direction decreasing (< or <=) + if (this.operator.startsWith('<') && comp.operator.startsWith('<')) { + return true + } + // same SemVer and both sides are inclusive (<= or >=) + if ( + (this.semver.version === comp.semver.version) && + this.operator.includes('=') && comp.operator.includes('=')) { + return true + } + // opposite directions less than + if (cmp$1(this.semver, '<', comp.semver, options) && + this.operator.startsWith('>') && comp.operator.startsWith('<')) { + return true + } + // opposite directions greater than + if (cmp$1(this.semver, '>', comp.semver, options) && + this.operator.startsWith('<') && comp.operator.startsWith('>')) { + return true + } + return false + } +} + +var comparator = Comparator$3; + +const parseOptions = parseOptions_1; +const { safeRe: re, t } = re$4.exports; +const cmp$1 = cmp_1; +const debug = debug_1; +const SemVer$5 = semver$1; +const Range$a = range; + +const Range$9 = range; +const satisfies$4 = (version, range, options) => { + try { + range = new Range$9(range, options); + } catch (er) { + return false + } + return range.test(version) +}; +var satisfies_1 = satisfies$4; + +const Range$8 = range; + +// Mostly just for testing and legacy API reasons +const toComparators$1 = (range, options) => + new Range$8(range, options).set + .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')); + +var toComparators_1 = toComparators$1; + +const SemVer$4 = semver$1; +const Range$7 = range; + +const maxSatisfying$1 = (versions, range, options) => { + let max = null; + let maxSV = null; + let rangeObj = null; + try { + rangeObj = new Range$7(range, options); + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v; + maxSV = new SemVer$4(max, options); + } + } + }); + return max +}; +var maxSatisfying_1 = maxSatisfying$1; + +const SemVer$3 = semver$1; +const Range$6 = range; +const minSatisfying$1 = (versions, range, options) => { + let min = null; + let minSV = null; + let rangeObj = null; + try { + rangeObj = new Range$6(range, options); + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v; + minSV = new SemVer$3(min, options); + } + } + }); + return min +}; +var minSatisfying_1 = minSatisfying$1; + +const SemVer$2 = semver$1; +const Range$5 = range; +const gt$2 = gt_1; + +const minVersion$1 = (range, loose) => { + range = new Range$5(range, loose); + + let minver = new SemVer$2('0.0.0'); + if (range.test(minver)) { + return minver + } + + minver = new SemVer$2('0.0.0-0'); + if (range.test(minver)) { + return minver + } + + minver = null; + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + + let setMin = null; + comparators.forEach((comparator) => { + // Clone to avoid manipulating the comparator's semver object. + const compver = new SemVer$2(comparator.semver.version); + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++; + } else { + compver.prerelease.push(0); + } + compver.raw = compver.format(); + /* fallthrough */ + case '': + case '>=': + if (!setMin || gt$2(compver, setMin)) { + setMin = compver; + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`) + } + }); + if (setMin && (!minver || gt$2(minver, setMin))) { + minver = setMin; + } + } + + if (minver && range.test(minver)) { + return minver + } + + return null +}; +var minVersion_1 = minVersion$1; + +const Range$4 = range; +const validRange$1 = (range, options) => { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range$4(range, options).range || '*' + } catch (er) { + return null + } +}; +var valid$1 = validRange$1; + +const SemVer$1 = semver$1; +const Comparator$2 = comparator; +const { ANY: ANY$1 } = Comparator$2; +const Range$3 = range; +const satisfies$3 = satisfies_1; +const gt$1 = gt_1; +const lt$1 = lt_1; +const lte$1 = lte_1; +const gte$1 = gte_1; + +const outside$3 = (version, range, hilo, options) => { + version = new SemVer$1(version, options); + range = new Range$3(range, options); + + let gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt$1; + ltefn = lte$1; + ltfn = lt$1; + comp = '>'; + ecomp = '>='; + break + case '<': + gtfn = lt$1; + ltefn = gte$1; + ltfn = gt$1; + comp = '<'; + ecomp = '<='; + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisfies the range it is not outside + if (satisfies$3(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i]; + + let high = null; + let low = null; + + comparators.forEach((comparator) => { + if (comparator.semver === ANY$1) { + comparator = new Comparator$2('>=0.0.0'); + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +}; + +var outside_1 = outside$3; + +// Determine if version is greater than all the versions possible in the range. +const outside$2 = outside_1; +const gtr$1 = (version, range, options) => outside$2(version, range, '>', options); +var gtr_1 = gtr$1; + +const outside$1 = outside_1; +// Determine if version is less than all the versions possible in the range +const ltr$1 = (version, range, options) => outside$1(version, range, '<', options); +var ltr_1 = ltr$1; + +const Range$2 = range; +const intersects$1 = (r1, r2, options) => { + r1 = new Range$2(r1, options); + r2 = new Range$2(r2, options); + return r1.intersects(r2, options) +}; +var intersects_1 = intersects$1; + +// given a set of versions and a range, create a "simplified" range +// that includes the same versions that the original range does +// If the original range is shorter than the simplified one, return that. +const satisfies$2 = satisfies_1; +const compare$2 = compare_1; +var simplify = (versions, range, options) => { + const set = []; + let first = null; + let prev = null; + const v = versions.sort((a, b) => compare$2(a, b, options)); + for (const version of v) { + const included = satisfies$2(version, range, options); + if (included) { + prev = version; + if (!first) { + first = version; + } + } else { + if (prev) { + set.push([first, prev]); + } + prev = null; + first = null; + } + } + if (first) { + set.push([first, null]); + } + + const ranges = []; + for (const [min, max] of set) { + if (min === max) { + ranges.push(min); + } else if (!max && min === v[0]) { + ranges.push('*'); + } else if (!max) { + ranges.push(`>=${min}`); + } else if (min === v[0]) { + ranges.push(`<=${max}`); + } else { + ranges.push(`${min} - ${max}`); + } + } + const simplified = ranges.join(' || '); + const original = typeof range.raw === 'string' ? range.raw : String(range); + return simplified.length < original.length ? simplified : range +}; + +const Range$1 = range; +const Comparator$1 = comparator; +const { ANY } = Comparator$1; +const satisfies$1 = satisfies_1; +const compare$1 = compare_1; + +// Complex range `r1 || r2 || ...` is a subset of `R1 || R2 || ...` iff: +// - Every simple range `r1, r2, ...` is a null set, OR +// - Every simple range `r1, r2, ...` which is not a null set is a subset of +// some `R1, R2, ...` +// +// Simple range `c1 c2 ...` is a subset of simple range `C1 C2 ...` iff: +// - If c is only the ANY comparator +// - If C is only the ANY comparator, return true +// - Else if in prerelease mode, return false +// - else replace c with `[>=0.0.0]` +// - If C is only the ANY comparator +// - if in prerelease mode, return true +// - else replace C with `[>=0.0.0]` +// - Let EQ be the set of = comparators in c +// - If EQ is more than one, return true (null set) +// - Let GT be the highest > or >= comparator in c +// - Let LT be the lowest < or <= comparator in c +// - If GT and LT, and GT.semver > LT.semver, return true (null set) +// - If any C is a = range, and GT or LT are set, return false +// - If EQ +// - If GT, and EQ does not satisfy GT, return true (null set) +// - If LT, and EQ does not satisfy LT, return true (null set) +// - If EQ satisfies every C, return true +// - Else return false +// - If GT +// - If GT.semver is lower than any > or >= comp in C, return false +// - If GT is >=, and GT.semver does not satisfy every C, return false +// - If GT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the GT.semver tuple, return false +// - If LT +// - If LT.semver is greater than any < or <= comp in C, return false +// - If LT is <=, and LT.semver does not satisfy every C, return false +// - If GT.semver has a prerelease, and not in prerelease mode +// - If no C has a prerelease and the LT.semver tuple, return false +// - Else return true + +const subset$1 = (sub, dom, options = {}) => { + if (sub === dom) { + return true + } + + sub = new Range$1(sub, options); + dom = new Range$1(dom, options); + let sawNonNull = false; + + OUTER: for (const simpleSub of sub.set) { + for (const simpleDom of dom.set) { + const isSub = simpleSubset(simpleSub, simpleDom, options); + sawNonNull = sawNonNull || isSub !== null; + if (isSub) { + continue OUTER + } + } + // the null set is a subset of everything, but null simple ranges in + // a complex range should be ignored. so if we saw a non-null range, + // then we know this isn't a subset, but if EVERY simple range was null, + // then it is a subset. + if (sawNonNull) { + return false + } + } + return true +}; + +const minimumVersionWithPreRelease = [new Comparator$1('>=0.0.0-0')]; +const minimumVersion = [new Comparator$1('>=0.0.0')]; + +const simpleSubset = (sub, dom, options) => { + if (sub === dom) { + return true + } + + if (sub.length === 1 && sub[0].semver === ANY) { + if (dom.length === 1 && dom[0].semver === ANY) { + return true + } else if (options.includePrerelease) { + sub = minimumVersionWithPreRelease; + } else { + sub = minimumVersion; + } + } + + if (dom.length === 1 && dom[0].semver === ANY) { + if (options.includePrerelease) { + return true + } else { + dom = minimumVersion; + } + } + + const eqSet = new Set(); + let gt, lt; + for (const c of sub) { + if (c.operator === '>' || c.operator === '>=') { + gt = higherGT(gt, c, options); + } else if (c.operator === '<' || c.operator === '<=') { + lt = lowerLT(lt, c, options); + } else { + eqSet.add(c.semver); + } + } + + if (eqSet.size > 1) { + return null + } + + let gtltComp; + if (gt && lt) { + gtltComp = compare$1(gt.semver, lt.semver, options); + if (gtltComp > 0) { + return null + } else if (gtltComp === 0 && (gt.operator !== '>=' || lt.operator !== '<=')) { + return null + } + } + + // will iterate one or zero times + for (const eq of eqSet) { + if (gt && !satisfies$1(eq, String(gt), options)) { + return null + } + + if (lt && !satisfies$1(eq, String(lt), options)) { + return null + } + + for (const c of dom) { + if (!satisfies$1(eq, String(c), options)) { + return false + } + } + + return true + } + + let higher, lower; + let hasDomLT, hasDomGT; + // if the subset has a prerelease, we need a comparator in the superset + // with the same tuple and a prerelease, or it's not a subset + let needDomLTPre = lt && + !options.includePrerelease && + lt.semver.prerelease.length ? lt.semver : false; + let needDomGTPre = gt && + !options.includePrerelease && + gt.semver.prerelease.length ? gt.semver : false; + // exception: <1.2.3-0 is the same as <1.2.3 + if (needDomLTPre && needDomLTPre.prerelease.length === 1 && + lt.operator === '<' && needDomLTPre.prerelease[0] === 0) { + needDomLTPre = false; + } + + for (const c of dom) { + hasDomGT = hasDomGT || c.operator === '>' || c.operator === '>='; + hasDomLT = hasDomLT || c.operator === '<' || c.operator === '<='; + if (gt) { + if (needDomGTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomGTPre.major && + c.semver.minor === needDomGTPre.minor && + c.semver.patch === needDomGTPre.patch) { + needDomGTPre = false; + } + } + if (c.operator === '>' || c.operator === '>=') { + higher = higherGT(gt, c, options); + if (higher === c && higher !== gt) { + return false + } + } else if (gt.operator === '>=' && !satisfies$1(gt.semver, String(c), options)) { + return false + } + } + if (lt) { + if (needDomLTPre) { + if (c.semver.prerelease && c.semver.prerelease.length && + c.semver.major === needDomLTPre.major && + c.semver.minor === needDomLTPre.minor && + c.semver.patch === needDomLTPre.patch) { + needDomLTPre = false; + } + } + if (c.operator === '<' || c.operator === '<=') { + lower = lowerLT(lt, c, options); + if (lower === c && lower !== lt) { + return false + } + } else if (lt.operator === '<=' && !satisfies$1(lt.semver, String(c), options)) { + return false + } + } + if (!c.operator && (lt || gt) && gtltComp !== 0) { + return false + } + } + + // if there was a < or >, and nothing in the dom, then must be false + // UNLESS it was limited by another range in the other direction. + // Eg, >1.0.0 <1.0.1 is still a subset of <2.0.0 + if (gt && hasDomLT && !lt && gtltComp !== 0) { + return false + } + + if (lt && hasDomGT && !gt && gtltComp !== 0) { + return false + } + + // we needed a prerelease range in a specific tuple, but didn't get one + // then this isn't a subset. eg >=1.2.3-pre is not a subset of >=1.0.0, + // because it includes prereleases in the 1.2.3 tuple + if (needDomGTPre || needDomLTPre) { + return false + } + + return true +}; + +// >=1.2.3 is lower than >1.2.3 +const higherGT = (a, b, options) => { + if (!a) { + return b + } + const comp = compare$1(a.semver, b.semver, options); + return comp > 0 ? a + : comp < 0 ? b + : b.operator === '>' && a.operator === '>=' ? b + : a +}; + +// <=1.2.3 is higher than <1.2.3 +const lowerLT = (a, b, options) => { + if (!a) { + return b + } + const comp = compare$1(a.semver, b.semver, options); + return comp < 0 ? a + : comp > 0 ? b + : b.operator === '<' && a.operator === '<=' ? b + : a +}; + +var subset_1 = subset$1; + +// just pre-load all the stuff that index.js lazily exports +const internalRe = re$4.exports; +const constants = constants$1; +const SemVer = semver$1; +const identifiers = identifiers$1; +const parse = parse_1; +const valid = valid_1; +const clean = clean_1; +const inc = inc_1; +const diff = diff_1; +const major = major_1; +const minor = minor_1; +const patch = patch_1; +const prerelease = prerelease_1; +const compare = compare_1; +const rcompare = rcompare_1; +const compareLoose = compareLoose_1; +const compareBuild = compareBuild_1; +const sort = sort_1; +const rsort = rsort_1; +const gt = gt_1; +const lt = lt_1; +const eq = eq_1; +const neq = neq_1; +const gte = gte_1; +const lte = lte_1; +const cmp = cmp_1; +const coerce = coerce_1; +const Comparator = comparator; +const Range = range; +const satisfies = satisfies_1; +const toComparators = toComparators_1; +const maxSatisfying = maxSatisfying_1; +const minSatisfying = minSatisfying_1; +const minVersion = minVersion_1; +const validRange = valid$1; +const outside = outside_1; +const gtr = gtr_1; +const ltr = ltr_1; +const intersects = intersects_1; +const simplifyRange = simplify; +const subset = subset_1; +var semver = { + parse, + valid, + clean, + inc, + diff, + major, + minor, + patch, + prerelease, + compare, + rcompare, + compareLoose, + compareBuild, + sort, + rsort, + gt, + lt, + eq, + neq, + gte, + lte, + cmp, + coerce, + Comparator, + Range, + satisfies, + toComparators, + maxSatisfying, + minSatisfying, + minVersion, + validRange, + outside, + gtr, + ltr, + intersects, + simplifyRange, + subset, + SemVer, + re: internalRe.re, + src: internalRe.src, + tokens: internalRe.t, + SEMVER_SPEC_VERSION: constants.SEMVER_SPEC_VERSION, + RELEASE_TYPES: constants.RELEASE_TYPES, + compareIdentifiers: identifiers.compareIdentifiers, + rcompareIdentifiers: identifiers.rcompareIdentifiers, +}; + +const DEFAULT_SETTINGS = { + version: "", + previousVersion: "", + groupBy: LinkGrouping.ByFolder, + expandedFolderItems: [], + expandedFileItems: [], + expandedLinkItems: [], + folderSort: FolderSort.NameAsc, + fileSort: FileSort.CountDesc, + linkSort: LinkSort.CountDesc, + linkFilter: { + filterString: "", + matchCase: false, + }, + ignoredFolders: [], + consolidateLinks: false, +}; +class BrokenLinks extends obsidian.Plugin { + onload() { + return __awaiter(this, void 0, void 0, function* () { + yield this.loadSettings(); + yield this.runSettingsVersionCheck(); + this.registerView(BROKEN_LINKS_VIEW_TYPE, (leaf) => new BrokenLinksView(leaf, this)); + this.addRibbonIcon("unlink", "View broken links", () => { + this.activateView(); + }); + this.addCommand({ + id: "list", + name: "View broken links", + callback: () => { + this.activateView(); + }, + }); + this.addSettingTab(new BrokenLinksSettingsTab(this.app, this)); + console.log("Broken Links plugin loaded"); + }); + } + onunload() { + return __awaiter(this, void 0, void 0, function* () { + console.log("Broken Links plugin unloaded"); + }); + } + loadSettings() { + return __awaiter(this, void 0, void 0, function* () { + this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData()); + }); + } + saveSettings() { + return __awaiter(this, void 0, void 0, function* () { + yield this.saveData(this.settings); + }); + } + activateView() { + return __awaiter(this, void 0, void 0, function* () { + const { workspace } = this.app; + let leaf = null; + const leaves = workspace.getLeavesOfType(BROKEN_LINKS_VIEW_TYPE); + if (leaves.length > 0) { + // A leaf with the Broken Links view already exists, use that + leaf = leaves[0]; + } + else { + // The view could not be found in the workspace, + // create a new leaf in the right sidebar + leaf = workspace.getRightLeaf(false); + yield leaf.setViewState({ type: BROKEN_LINKS_VIEW_TYPE, active: true }); + } + // Show the leaf in case it is in a collapsed sidebar + workspace.revealLeaf(leaf); + }); + } + updateView() { + return __awaiter(this, void 0, void 0, function* () { + this.app.workspace.getLeavesOfType(BROKEN_LINKS_VIEW_TYPE).forEach((leaf) => __awaiter(this, void 0, void 0, function* () { + if (leaf.view instanceof BrokenLinksView) { + yield leaf.view.updateView(); + } + })); + }); + } + runSettingsVersionCheck() { + return __awaiter(this, void 0, void 0, function* () { + // Check previous version + if (!semver.valid(this.settings.version)) + this.settings.version = "1.0.0"; + if (semver.lt(this.settings.version, this.manifest.version)) { + // Changes to settings in 1.2.0 + if (semver.lt(this.settings.version, "1.2.0")) { + switch (this.settings.groupBy) { + case "folder": + default: + this.settings.groupBy = LinkGrouping.ByFolder; + break; + case "file": + this.settings.groupBy = LinkGrouping.ByFile; + break; + case "link": + this.settings.groupBy = LinkGrouping.ByLink; + break; + } + switch (this.settings.folderSort) { + case "nameAsc": + default: + this.settings.folderSort = FolderSort.NameAsc; + break; + case "nameDesc": + this.settings.folderSort = FolderSort.NameDesc; + break; + } + switch (this.settings.fileSort) { + case "nameAsc": + this.settings.fileSort = FileSort.NameAsc; + break; + case "nameDesc": + this.settings.fileSort = FileSort.NameDesc; + break; + case "countAsc": + this.settings.fileSort = FileSort.CountAsc; + break; + case "countDesc": + default: + this.settings.fileSort = FileSort.CountDesc; + break; + } + switch (this.settings.linkSort) { + case "nameAsc": + this.settings.linkSort = LinkSort.NameAsc; + break; + case "nameDesc": + this.settings.linkSort = LinkSort.NameDesc; + break; + case "countAsc": + this.settings.linkSort = LinkSort.CountAsc; + break; + case "countDesc": + default: + this.settings.linkSort = LinkSort.CountDesc; + break; + } + } + this.settings.previousVersion = this.settings.version; + this.settings.version = this.manifest.version; + yield this.saveSettings(); + } + }); + } +} + +module.exports = BrokenLinks; + + +/* nosourcemap */ \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/broken-links/manifest.json b/10_Wiki/Topics/.obsidian/plugins/broken-links/manifest.json new file mode 100644 index 00000000..e6c5b19f --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/broken-links/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "broken-links", + "name": "Broken Links", + "version": "1.2.2", + "minAppVersion": "1.0.0", + "description": "Find broken links in your vault that don't connect to notes.", + "author": "ipshing", + "authorUrl": "https://github.com/ipshing", + "isDesktopOnly": false, + "fundingUrl": "https://ko-fi.com/ipshing" +} diff --git a/10_Wiki/Topics/.obsidian/plugins/broken-links/styles.css b/10_Wiki/Topics/.obsidian/plugins/broken-links/styles.css new file mode 100644 index 00000000..61db92f1 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/broken-links/styles.css @@ -0,0 +1,111 @@ +.broken-links-settings .setting-item-control input { + min-width: 250px; +} +.broken-links-settings-folder { + display: flex; + align-items: center; + justify-items: left; + gap: 5px; + padding: var(--size-4-1) 0; +} +.broken-links-settings-folder-icon { + margin-top: var(--size-4-1); +} + +div.broken-links .hidden { + display: none; +} +div.broken-links .tree-item-children .tree-item-icon + .tree-item-icon { + margin-left: 0; +} +div.broken-links .tree-item-children .tree-item-icon + .tree-item-icon + .tree-item-inner { + margin-left: var(--size-4-5); +} +div.broken-links > .nav-files-container { + padding: 0 var(--size-4-3) var(--size-4-9) var(--size-4-3); +} +div.broken-links .nav-folder.mod-root > .nav-folder-title { + font-size: var(--font-ui-medium); +} +div.broken-links .nav-folder.mod-root > .nav-folder-children .nav-folder .nav-folder-title-content { + font-weight: var(--font-semibold); +} +div.broken-links .nav-folder-children .nav-folder-title > .tree-item-icon + .tree-item-icon { + margin-left: 0; +} +div.broken-links .nav-folder-children .nav-folder-title > .nav-folder-title-content { + flex-grow: 1; +} +div.broken-links .nav-link-title, +div.broken-links .nav-link-title.is-clickable:hover, +div.broken-links .nav-link-title .tree-item-icon { + color: var(--link-color); +} + +div.broken-links .filter-row { + display: flex; + margin: var(--size-4-2) var(--size-4-2) 0; + gap: var(--size-4-1); +} +div.broken-links .filter-input-container { + flex-grow: 1; + position: relative; +} +div.broken-links .filter-input-container::before { + top: calc((var(--input-height) - var(--search-icon-size)) / 2); + left: 8px; + position: absolute; + content: ""; + height: var(--search-icon-size); + width: var(--search-icon-size); + display: block; + background-color: var(--search-icon-color); + -webkit-mask-image: url('data:image/svg+xml,'); + -webkit-mask-repeat: no-repeat; +} +div.broken-links .filter-input-container input { + display: block; + width: 100%; + padding-left: 36px; + padding-right: 56px; +} +div.broken-links .filter-input-clear-button { + position: absolute; + background: transparent; + border-radius: 50%; + color: var(--search-clear-button-color); + cursor: var(--cursor); + top: 0px; + right: 2px; + bottom: 0px; + line-height: 0; + height: var(--input-height); + width: 28px; + margin: auto; + padding: 0 0; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + transition: color 0.15s ease-in-out; +} +div.broken-links .filter-input-clear-button::after { + content: ""; + height: var(--search-clear-button-size); + width: var(--search-clear-button-size); + display: block; + background-color: currentColor; + -webkit-mask-image: url("data:image/svg+xml,"); + -webkit-mask-repeat: no-repeat; +} +div.broken-links .filter-input-clear-button:active, +div.broken-links .filter-input-clear-button:hover { + color: var(--text-normal); + transition: color 0.15s ease-in-out; +} +div.broken-links .filter-input-container input:placeholder-shown ~ .filter-input-clear-button { + display: none; +} +div.broken-links .filter-input-container input:not(:placeholder-shown) ~ .input-right-decorator { + right: calc(var(--size-4-1) + 28px); +} diff --git a/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/data.json b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/data.json new file mode 100644 index 00000000..93db5088 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/data.json @@ -0,0 +1,19 @@ +{ + "collectAttachmentUsedByMultipleNotesMode": "Skip", + "consistencyReportFile": "consistency-report.md", + "emptyFolderBehavior": "DeleteWithEmptyParents", + "excludePaths": [], + "excludePathsFromAttachmentCollecting": [], + "includePaths": [], + "moveAttachmentToProperFolderUsedByMultipleNotesMode": "CopyAll", + "shouldChangeNoteBacklinksDisplayText": true, + "shouldCollectAttachmentsAutomatically": false, + "shouldDeleteAttachmentsWithNote": false, + "shouldDeleteExistingFilesWhenMovingNote": false, + "shouldMoveAttachmentsWithNote": false, + "shouldShowBackupWarning": false, + "shouldUpdateLinks": true, + "treatAsAttachmentExtensions": [ + ".excalidraw.md" + ] +} \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/main.js b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/main.js new file mode 100644 index 00000000..29df5287 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/main.js @@ -0,0 +1,458 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +(function initCjs() { + const globalThisRecord = globalThis; + globalThisRecord["__name"] ??= name; + const originalRequire = require; + if (originalRequire && !originalRequire.__isPatched) { + require = Object.assign( + (id) => requirePatched(id), + originalRequire, + { + __isPatched: true + } + ); + } + const newFuncs = { + __extractDefault() { + return extractDefault; + }, + process() { + const browserProcess = { + browser: true, + cwd() { + return "/"; + }, + env: {}, + platform: "android" + }; + return browserProcess; + } + }; + for (const key of Object.keys(newFuncs)) { + globalThisRecord[key] ??= newFuncs[key]?.(); + } + function name(obj) { + return obj; + } + function extractDefault(module2) { + return module2 && module2.__esModule && "default" in module2 ? module2.default : module2; + } + const OBSIDIAN_BUILT_IN_MODULE_NAMES = [ + "obsidian", + "@codemirror/autocomplete", + "@codemirror/collab", + "@codemirror/commands", + "@codemirror/language", + "@codemirror/lint", + "@codemirror/search", + "@codemirror/state", + "@codemirror/text", + "@codemirror/view", + "@lezer/common", + "@lezer/lr", + "@lezer/highlight" + ]; + const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = [ + "@codemirror/closebrackets", + "@codemirror/comment", + "@codemirror/fold", + "@codemirror/gutter", + "@codemirror/highlight", + "@codemirror/history", + "@codemirror/matchbrackets", + "@codemirror/panel", + "@codemirror/rangeset", + "@codemirror/rectangular-selection", + "@codemirror/stream-parser", + "@codemirror/tooltip" + ]; + function requirePatched(id) { + if (OBSIDIAN_BUILT_IN_MODULE_NAMES.includes(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.includes(id)) { + return originalRequire?.(id); + } + if (globalThis?.app?.isMobile) { + if (id === "process" || id === "node:process") { + console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`); + return globalThis.process; + } + } else { + const module2 = originalRequire?.(id); + if (module2) { + return extractDefault(module2); + } + } + console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`); + return {}; + } +})(); + +"use strict";var fh=Object.create;var ir=Object.defineProperty;var mh=Object.getOwnPropertyDescriptor;var gh=Object.getOwnPropertyNames;var bh=Object.getPrototypeOf,wh=Object.prototype.hasOwnProperty;var i=(t,e)=>ir(t,"name",{value:e,configurable:!0});var ct=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Kl=(t,e)=>{for(var n in e)ir(t,n,{get:e[n],enumerable:!0})},ql=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of gh(e))!wh.call(t,o)&&o!==n&&ir(t,o,{get:()=>e[o],enumerable:!(r=mh(e,o))||r.enumerable});return t};var hn=(t,e,n)=>(n=t!=null?fh(bh(t)):{},ql(e||!t||!t.__esModule?ir(n,"default",{value:t,enumerable:!0}):n,t)),yh=t=>ql(ir({},"__esModule",{value:!0}),t);var nc=ct((gw,tc)=>{"use strict";function dt(t){if(typeof t!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(t))}i(dt,"assertPath");function ec(t,e){for(var n="",r=0,o=-1,s=0,a,l=0;l<=t.length;++l){if(l2){var c=n.lastIndexOf("/");if(c!==n.length-1){c===-1?(n="",r=0):(n=n.slice(0,c),r=n.length-1-n.lastIndexOf("/")),o=l,s=0;continue}}else if(n.length===2||n.length===1){n="",r=0,o=l,s=0;continue}}e&&(n.length>0?n+="/..":n="..",r=2)}else n.length>0?n+="/"+t.slice(o+1,l):n=t.slice(o+1,l),r=l-o-1;o=l,s=0}else a===46&&s!==-1?++s:s=-1}return n}i(ec,"normalizeStringPosix");function Eh(t,e){var n=e.dir||e.root,r=e.base||(e.name||"")+(e.ext||"");return n?n===e.root?n+r:n+t+r:r}i(Eh,"_format");var fn={resolve:i(function(){for(var e="",n=!1,r,o=arguments.length-1;o>=-1&&!n;o--){var s;o>=0?s=arguments[o]:(r===void 0&&(r=process.cwd()),s=r),dt(s),s.length!==0&&(e=s+"/"+e,n=s.charCodeAt(0)===47)}return e=ec(e,!n),n?e.length>0?"/"+e:"/":e.length>0?e:"."},"resolve"),normalize:i(function(e){if(dt(e),e.length===0)return".";var n=e.charCodeAt(0)===47,r=e.charCodeAt(e.length-1)===47;return e=ec(e,!n),e.length===0&&!n&&(e="."),e.length>0&&r&&(e+="/"),n?"/"+e:e},"normalize"),isAbsolute:i(function(e){return dt(e),e.length>0&&e.charCodeAt(0)===47},"isAbsolute"),join:i(function(){if(arguments.length===0)return".";for(var e,n=0;n0&&(e===void 0?e=r:e+="/"+r)}return e===void 0?".":fn.normalize(e)},"join"),relative:i(function(e,n){if(dt(e),dt(n),e===n||(e=fn.resolve(e),n=fn.resolve(n),e===n))return"";for(var r=1;ru){if(n.charCodeAt(a+p)===47)return n.slice(a+p+1);if(p===0)return n.slice(a+p)}else s>u&&(e.charCodeAt(r+p)===47?d=p:p===0&&(d=0));break}var h=e.charCodeAt(r+p),f=n.charCodeAt(a+p);if(h!==f)break;h===47&&(d=p)}var b="";for(p=r+d+1;p<=o;++p)(p===o||e.charCodeAt(p)===47)&&(b.length===0?b+="..":b+="/..");return b.length>0?b+n.slice(a+d):(a+=d,n.charCodeAt(a)===47&&++a,n.slice(a))},"relative"),_makeLong:i(function(e){return e},"_makeLong"),dirname:i(function(e){if(dt(e),e.length===0)return".";for(var n=e.charCodeAt(0),r=n===47,o=-1,s=!0,a=e.length-1;a>=1;--a)if(n=e.charCodeAt(a),n===47){if(!s){o=a;break}}else s=!1;return o===-1?r?"/":".":r&&o===1?"//":e.slice(0,o)},"dirname"),basename:i(function(e,n){if(n!==void 0&&typeof n!="string")throw new TypeError('"ext" argument must be a string');dt(e);var r=0,o=-1,s=!0,a;if(n!==void 0&&n.length>0&&n.length<=e.length){if(n.length===e.length&&n===e)return"";var l=n.length-1,c=-1;for(a=e.length-1;a>=0;--a){var u=e.charCodeAt(a);if(u===47){if(!s){r=a+1;break}}else c===-1&&(s=!1,c=a+1),l>=0&&(u===n.charCodeAt(l)?--l===-1&&(o=a):(l=-1,o=c))}return r===o?o=c:o===-1&&(o=e.length),e.slice(r,o)}else{for(a=e.length-1;a>=0;--a)if(e.charCodeAt(a)===47){if(!s){r=a+1;break}}else o===-1&&(s=!1,o=a+1);return o===-1?"":e.slice(r,o)}},"basename"),extname:i(function(e){dt(e);for(var n=-1,r=0,o=-1,s=!0,a=0,l=e.length-1;l>=0;--l){var c=e.charCodeAt(l);if(c===47){if(!s){r=l+1;break}continue}o===-1&&(s=!1,o=l+1),c===46?n===-1?n=l:a!==1&&(a=1):n!==-1&&(a=-1)}return n===-1||o===-1||a===0||a===1&&n===o-1&&n===r+1?"":e.slice(n,o)},"extname"),format:i(function(e){if(e===null||typeof e!="object")throw new TypeError('The "pathObject" argument must be of type Object. Received type '+typeof e);return Eh("/",e)},"format"),parse:i(function(e){dt(e);var n={root:"",dir:"",base:"",ext:"",name:""};if(e.length===0)return n;var r=e.charCodeAt(0),o=r===47,s;o?(n.root="/",s=1):s=0;for(var a=-1,l=0,c=-1,u=!0,d=e.length-1,p=0;d>=s;--d){if(r=e.charCodeAt(d),r===47){if(!u){l=d+1;break}continue}c===-1&&(u=!1,c=d+1),r===46?a===-1?a=d:p!==1&&(p=1):a!==-1&&(p=-1)}return a===-1||c===-1||p===0||p===1&&a===c-1&&a===l+1?c!==-1&&(l===0&&o?n.base=n.name=e.slice(1,c):n.base=n.name=e.slice(l,c)):(l===0&&o?(n.name=e.slice(1,a),n.base=e.slice(1,c)):(n.name=e.slice(l,a),n.base=e.slice(l,c)),n.ext=e.slice(a,c)),l>0?n.dir=e.slice(0,l-1):o&&(n.dir="/"),n},"parse"),sep:"/",delimiter:":",win32:null,posix:null};fn.posix=fn;tc.exports=fn});var kc=ct((sy,yc)=>{var yn=1e3,kn=yn*60,Cn=kn*60,jt=Cn*24,Dh=jt*7,Bh=jt*365.25;yc.exports=function(t,e){e=e||{};var n=typeof t;if(n==="string"&&t.length>0)return _h(t);if(n==="number"&&isFinite(t))return e.long?zh(t):$h(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))};function _h(t){if(t=String(t),!(t.length>100)){var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(t);if(e){var n=parseFloat(e[1]),r=(e[2]||"ms").toLowerCase();switch(r){case"years":case"year":case"yrs":case"yr":case"y":return n*Bh;case"weeks":case"week":case"w":return n*Dh;case"days":case"day":case"d":return n*jt;case"hours":case"hour":case"hrs":case"hr":case"h":return n*Cn;case"minutes":case"minute":case"mins":case"min":case"m":return n*kn;case"seconds":case"second":case"secs":case"sec":case"s":return n*yn;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return n;default:return}}}}i(_h,"parse");function $h(t){var e=Math.abs(t);return e>=jt?Math.round(t/jt)+"d":e>=Cn?Math.round(t/Cn)+"h":e>=kn?Math.round(t/kn)+"m":e>=yn?Math.round(t/yn)+"s":t+"ms"}i($h,"fmtShort");function zh(t){var e=Math.abs(t);return e>=jt?Gr(t,e,jt,"day"):e>=Cn?Gr(t,e,Cn,"hour"):e>=kn?Gr(t,e,kn,"minute"):e>=yn?Gr(t,e,yn,"second"):t+" ms"}i(zh,"fmtLong");function Gr(t,e,n,r){var o=e>=n*1.5;return Math.round(t/n)+" "+r+(o?"s":"")}i(Gr,"plural")});var Cs=ct((ly,Cc)=>{function Vh(t){n.debug=n,n.default=n,n.coerce=c,n.disable=a,n.enable=o,n.enabled=l,n.humanize=kc(),n.destroy=u,Object.keys(t).forEach(d=>{n[d]=t[d]}),n.names=[],n.skips=[],n.formatters={};function e(d){let p=0;for(let h=0;h{if(C==="%%")return"%";P++;let H=n.formatters[$];if(typeof H=="function"){let R=y[P];C=H.call(w,R),y.splice(P,1),P--}return C}),n.formatArgs.call(w,y),(w.log||n.log).apply(w,y)}return i(k,"debug"),k.namespace=d,k.useColors=n.useColors(),k.color=n.selectColor(d),k.extend=r,k.destroy=n.destroy,Object.defineProperty(k,"enabled",{enumerable:!0,configurable:!1,get:i(()=>h!==null?h:(f!==n.namespaces&&(f=n.namespaces,b=n.enabled(d)),b),"get"),set:i(y=>{h=y},"set")}),typeof n.init=="function"&&n.init(k),k}i(n,"createDebug");function r(d,p){let h=n(this.namespace+(typeof p>"u"?":":p)+d);return h.log=this.log,h}i(r,"extend");function o(d){n.save(d),n.namespaces=d,n.names=[],n.skips=[];let p=(typeof d=="string"?d:"").trim().replace(/\s+/g,",").split(",").filter(Boolean);for(let h of p)h[0]==="-"?n.skips.push(h.slice(1)):n.names.push(h)}i(o,"enable");function s(d,p){let h=0,f=0,b=-1,k=0;for(;h"-"+p)].join(",");return n.enable(""),d}i(a,"disable");function l(d){for(let p of n.skips)if(s(d,p))return!1;for(let p of n.names)if(s(d,p))return!0;return!1}i(l,"enabled");function c(d){return d instanceof Error?d.stack||d.message:d}i(c,"coerce");function u(){console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.")}return i(u,"destroy"),n.enable(n.load()),n}i(Vh,"setup");Cc.exports=Vh});var Ac=ct((Re,Yr)=>{Re.formatArgs=Wh;Re.save=Hh;Re.load=jh;Re.useColors=Uh;Re.storage=Kh();Re.destroy=(()=>{let t=!1;return()=>{t||(t=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})();Re.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"];function Uh(){if(typeof window<"u"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))return!0;if(typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;let t;return typeof document<"u"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window<"u"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator<"u"&&navigator.userAgent&&(t=navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/))&&parseInt(t[1],10)>=31||typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)}i(Uh,"useColors");function Wh(t){if(t[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+t[0]+(this.useColors?"%c ":" ")+"+"+Yr.exports.humanize(this.diff),!this.useColors)return;let e="color: "+this.color;t.splice(1,0,e,"color: inherit");let n=0,r=0;t[0].replace(/%[a-zA-Z%]/g,o=>{o!=="%%"&&(n++,o==="%c"&&(r=n))}),t.splice(r,0,e)}i(Wh,"formatArgs");Re.log=console.debug||console.log||(()=>{});function Hh(t){try{t?Re.storage.setItem("debug",t):Re.storage.removeItem("debug")}catch{}}i(Hh,"save");function jh(){let t;try{t=Re.storage.getItem("debug")||Re.storage.getItem("DEBUG")}catch{}return!t&&typeof process<"u"&&"env"in process&&(t=process.env.DEBUG),t}i(jh,"load");function Kh(){try{return localStorage}catch{}}i(Kh,"localstorage");Yr.exports=Cs()(Re);var{formatters:qh}=Yr.exports;qh.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}}});var vc=ct((dy,xc)=>{"use strict";xc.exports=(t,e)=>{e=e||process.argv;let n=t.startsWith("-")?"":t.length===1?"-":"--",r=e.indexOf(n+t),o=e.indexOf("--");return r!==-1&&(o===-1?!0:r{"use strict";var Gh=require("os"),at=vc(),ye=process.env,An;at("no-color")||at("no-colors")||at("color=false")?An=!1:(at("color")||at("colors")||at("color=true")||at("color=always"))&&(An=!0);"FORCE_COLOR"in ye&&(An=ye.FORCE_COLOR.length===0||parseInt(ye.FORCE_COLOR,10)!==0);function Yh(t){return t===0?!1:{level:t,hasBasic:!0,has256:t>=2,has16m:t>=3}}i(Yh,"translateLevel");function Jh(t){if(An===!1)return 0;if(at("color=16m")||at("color=full")||at("color=truecolor"))return 3;if(at("color=256"))return 2;if(t&&!t.isTTY&&An!==!0)return 0;let e=An?1:0;if(process.platform==="win32"){let n=Gh.release().split(".");return Number(process.versions.node.split(".")[0])>=8&&Number(n[0])>=10&&Number(n[2])>=10586?Number(n[2])>=14931?3:2:1}if("CI"in ye)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI"].some(n=>n in ye)||ye.CI_NAME==="codeship"?1:e;if("TEAMCITY_VERSION"in ye)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(ye.TEAMCITY_VERSION)?1:0;if(ye.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in ye){let n=parseInt((ye.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(ye.TERM_PROGRAM){case"iTerm.app":return n>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(ye.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(ye.TERM)||"COLORTERM"in ye?1:(ye.TERM==="dumb",e)}i(Jh,"supportsColor");function As(t){let e=Jh(t);return Yh(e)}i(As,"getSupportLevel");Ec.exports={supportsColor:As,stdout:As(process.stdout),stderr:As(process.stderr)}});var Tc=ct((le,Qr)=>{var Qh=require("tty"),Jr=require("util");le.init=of;le.log=tf;le.formatArgs=Zh;le.save=nf;le.load=rf;le.useColors=Xh;le.destroy=Jr.deprecate(()=>{},"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.");le.colors=[6,2,3,4,5,1];try{let t=Sc();t&&(t.stderr||t).level>=2&&(le.colors=[20,21,26,27,32,33,38,39,40,41,42,43,44,45,56,57,62,63,68,69,74,75,76,77,78,79,80,81,92,93,98,99,112,113,128,129,134,135,148,149,160,161,162,163,164,165,166,167,168,169,170,171,172,173,178,179,184,185,196,197,198,199,200,201,202,203,204,205,206,207,208,209,214,215,220,221])}catch{}le.inspectOpts=Object.keys(process.env).filter(t=>/^debug_/i.test(t)).reduce((t,e)=>{let n=e.substring(6).toLowerCase().replace(/_([a-z])/g,(o,s)=>s.toUpperCase()),r=process.env[e];return/^(yes|on|true|enabled)$/i.test(r)?r=!0:/^(no|off|false|disabled)$/i.test(r)?r=!1:r==="null"?r=null:r=Number(r),t[n]=r,t},{});function Xh(){return"colors"in le.inspectOpts?!!le.inspectOpts.colors:Qh.isatty(process.stderr.fd)}i(Xh,"useColors");function Zh(t){let{namespace:e,useColors:n}=this;if(n){let r=this.color,o="\x1B[3"+(r<8?r:"8;5;"+r),s=` ${o};1m${e} \x1B[0m`;t[0]=s+t[0].split(` +`).join(` +`+s),t.push(o+"m+"+Qr.exports.humanize(this.diff)+"\x1B[0m")}else t[0]=ef()+e+" "+t[0]}i(Zh,"formatArgs");function ef(){return le.inspectOpts.hideDate?"":new Date().toISOString()+" "}i(ef,"getDate");function tf(...t){return process.stderr.write(Jr.formatWithOptions(le.inspectOpts,...t)+` +`)}i(tf,"log");function nf(t){t?process.env.DEBUG=t:delete process.env.DEBUG}i(nf,"save");function rf(){return process.env.DEBUG}i(rf,"load");function of(t){t.inspectOpts={};let e=Object.keys(le.inspectOpts);for(let n=0;ne.trim()).join(" ")};Pc.O=function(t){return this.inspectOpts.colors=this.useColors,Jr.inspect(t,this.inspectOpts)}});var Fc=ct((my,xs)=>{typeof process>"u"||process.type==="renderer"||process.browser===!0||process.__nwjs?xs.exports=Ac():xs.exports=Tc()});var Wc=ct((ii,Uc)=>{(function(t,e){typeof ii=="object"&&typeof Uc<"u"?e(ii):typeof define=="function"&&define.amd?define(["exports"],e):(t=typeof globalThis<"u"?globalThis:t||self,e(t.compareVersions={}))})(ii,(function(t){"use strict";let e=/^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i,n=i(y=>{if(typeof y!="string")throw new TypeError("Invalid argument expected string");let w=y.match(e);if(!w)throw new Error(`Invalid argument not valid semver ('${y}' received)`);return w.shift(),w},"validateAndParse"),r=i(y=>y==="*"||y==="x"||y==="X","isWildcard"),o=i(y=>{let w=parseInt(y,10);return isNaN(w)?y:w},"tryParse"),s=i((y,w)=>typeof y!=typeof w?[String(y),String(w)]:[y,w],"forceType"),a=i((y,w)=>{if(r(y)||r(w))return 0;let[A,v]=s(o(y),o(w));return A>v?1:A{for(let A=0;A{let A=n(y),v=n(w),P=A.pop(),I=v.pop(),C=l(A,v);return C!==0?C:P&&I?l(P.split("."),I.split(".")):P||I?P?-1:1:0},"compareVersions"),u=i((y,w,A)=>{h(A);let v=c(y,w);return d[A].includes(v)},"compare"),d={">":[1],">=":[0,1],"=":[0],"<=":[-1,0],"<":[-1],"!=":[-1,1]},p=Object.keys(d),h=i(y=>{if(typeof y!="string")throw new TypeError(`Invalid operator type, expected string but got ${typeof y}`);if(p.indexOf(y)===-1)throw new Error(`Invalid operator, expected one of ${p.join("|")}`)},"assertValidOperator"),f=i((y,w)=>{if(w=w.replace(/([><=]+)\s+/g,"$1"),w.includes("||"))return w.split("||").some(z=>f(y,z));if(w.includes(" - ")){let[z,j]=w.split(" - ",2);return f(y,`>=${z} <=${j}`)}else if(w.includes(" "))return w.trim().replace(/\s{2,}/g," ").split(" ").every(z=>f(y,z));let A=w.match(/^([<>=~^]+)/),v=A?A[1]:"=";if(v!=="^"&&v!=="~")return u(y,w,v);let[P,I,C,,$]=n(y),[H,R,V,,de]=n(w),W=[P,I,C],T=[H,R??"x",V??"x"];if(de&&(!$||l(W,T)!==0||l($.split("."),de.split("."))===-1))return!1;let L=T.findIndex(z=>z!=="0")+1,N=v==="~"?2:L>1?L:1;return!(l(W.slice(0,N),T.slice(0,N))!==0||l(W.slice(N),T.slice(N))===-1)},"satisfies"),b=i(y=>typeof y=="string"&&/^[v\d]/.test(y)&&e.test(y),"validate"),k=i(y=>typeof y=="string"&&/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(y),"validateStrict");t.compare=u,t.compareVersions=c,t.satisfies=f,t.validate=b,t.validateStrict=k}))});var Wd=ct((AP,Ud)=>{"use strict";var $i=Object.prototype.hasOwnProperty,Vd=Object.prototype.toString,Rd=Object.defineProperty,Dd=Object.getOwnPropertyDescriptor,Bd=i(function(e){return typeof Array.isArray=="function"?Array.isArray(e):Vd.call(e)==="[object Array]"},"isArray"),_d=i(function(e){if(!e||Vd.call(e)!=="[object Object]")return!1;var n=$i.call(e,"constructor"),r=e.constructor&&e.constructor.prototype&&$i.call(e.constructor.prototype,"isPrototypeOf");if(e.constructor&&!n&&!r)return!1;var o;for(o in e);return typeof o>"u"||$i.call(e,o)},"isPlainObject"),$d=i(function(e,n){Rd&&n.name==="__proto__"?Rd(e,n.name,{enumerable:!0,configurable:!0,value:n.newValue,writable:!0}):e[n.name]=n.newValue},"setProperty"),zd=i(function(e,n){if(n==="__proto__")if($i.call(e,n)){if(Dd)return Dd(e,n).value}else return;return e[n]},"getProperty");Ud.exports=i(function t(){var e,n,r,o,s,a,l=arguments[0],c=1,u=arguments.length,d=!1;for(typeof l=="boolean"&&(d=l,l=arguments[1]||{},c=2),(l==null||typeof l!="object"&&typeof l!="function")&&(l={});ciw});module.exports=yh(ow);var $e=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Me(){}i(Me,"noop");async function ut(){}i(ut,"noopAsync");function or(t){return async(...e)=>{await t(...e)}}i(or,"omitAsyncReturnType");var ot=require("obsidian");var kh=require("obsidian"),Yl=require("obsidian"),Jl=require("obsidian"),dw=require("obsidian"),pw=require("obsidian"),xh=require("obsidian"),vh=require("obsidian"),Xl=require("obsidian");var Gl=class{static{i(this,"CustomArrayDictImpl")}data=new Map;add(t,e){let n=this.get(t);n||(n=[],this.data.set(t,n)),n.includes(e)||n.push(e)}clear(t){this.data.delete(t)}clearAll(){this.data.clear()}contains(t,e){return!!this.get(t)?.contains(e)}count(){let t=0;for(let e of this.keys())t+=this.get(e)?.length??0;return t}get(t){return this.data.get(t)||null}keys(){return Array.from(this.data.keys())}remove(t,e){let n=this.get(t);n&&(n.remove(e),n.length===0&&this.clear(t))}};var Le={AudioRecorder:"audio-recorder",Backlink:"backlink",Bases:"bases",Bookmarks:"bookmarks",Canvas:"canvas",CommandPalette:"command-palette",DailyNotes:"daily-notes",EditorStatus:"editor-status",FileExplorer:"file-explorer",FileRecovery:"file-recovery",Footnotes:"footnotes",GlobalSearch:"global-search",Graph:"graph",MarkdownImporter:"markdown-importer",NoteComposer:"note-composer",OutgoingLink:"outgoing-link",Outline:"outline",PagePreview:"page-preview",Properties:"properties",Publish:"publish",RandomNote:"random-note",SlashCommand:"slash-command",Slides:"slides",Switcher:"switcher",Sync:"sync",TagPane:"tag-pane",Templates:"templates",Webviewer:"webviewer",WordCount:"word-count",Workspaces:"workspaces",ZkPrefixer:"zk-prefixer"},Br={AllProperties:"all-properties",Audio:"audio",Backlink:Le.Backlink,Bases:Le.Bases,Bookmarks:Le.Bookmarks,Canvas:Le.Canvas,Empty:"empty",FileExplorer:Le.FileExplorer,FileProperties:"file-properties",Graph:Le.Graph,Image:"image",LocalGraph:"localgraph",Markdown:"markdown",OutgoingLink:Le.OutgoingLink,Outline:Le.Outline,Pdf:"pdf",ReleaseNotes:"release-notes",Search:"search",Sync:"sync",Table:"table",Tag:"tag",Video:"video",Webviewer:"webviewer",WebviewerHistory:"webviewer-history"};function Ch(){return Yl.TFile}i(Ch,"getTFileConstructor");function Ah(){return Jl.TFolder}i(Ah,"getTFolderConstructor");function qe(t){return t.replace(/\/?[^\/]*$/,"")||"/"}i(qe,"parentFolderPath");function _r(t,e){let n=t.vault.getFolderByPath(e);return n||(n=new(Ah())(t.vault,e),n.parent=_r(t,qe(e)),n.deleted=!0,n)}i(_r,"createTFolderInstance");function Ql(t,e){let n=t.vault.getFileByPath(e);return n||(n=new(Ch())(t.vault,e),n.parent=_r(t,qe(e)),n.deleted=!0,n)}i(Ql,"createTFileInstance");async function Zl(){return await(0,Xl.loadPrism)()}i(Zl,"loadPrism");function tt(t){return!!t.position}i(tt,"isReferenceCache");function Ee(t){return!!t.key}i(Ee,"isFrontmatterLinkCache");var gs=hn(nc(),1);i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Sh=Number.POSITIVE_INFINITY;function nt(...t){let e=t.filter(s=>!!s);if(typeof AbortSignal.any=="function")return AbortSignal.any(e);if(e.length===0)return Se();if(e.length===1&&e[0])return e[0];let n=new AbortController;for(let s of e)if(s.aborted)return s;let r=[];for(let s of e)r.push(ic(s,o));return n.signal;function o(s){for(let a of r)a();n.abort(s.reason)}}i(nt,"abortSignalAny");function Se(){return new AbortController().signal}i(Se,"abortSignalNever");function rc(t){if(t===Sh)return Se();if(typeof AbortSignal.timeout=="function")return AbortSignal.timeout(t);let e=new AbortController;return window.setTimeout(()=>{e.abort(new Error(`Timed out in ${String(t)} milliseconds`))},t),e.signal}i(rc,"abortSignalTimeout");function ic(t,e){if(t.aborted)return e(t),Me;return t.addEventListener("abort",n,{once:!0}),()=>{t.removeEventListener("abort",n)};function n(r){e(r.target)}i(n,"wrappedCallback")}i(ic,"onAbort");function hs(t,e){return new Promise((n,r)=>{ic(t,()=>{e?r(t.reason):n(t.reason)})})}i(hs,"waitForAbort");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function sr(t,e){let n=t.length,r=0;for(let o=0;oo.callback!==n),r.length===0&&this.eventRefsMap.delete(e))}offref(e){let n=this.eventRefsMap.get(e.name);n&&(sr(n,r=>r!==e),n.length===0&&this.eventRefsMap.delete(e.name))}on(e,n,r){let o=this.eventRefsMap.get(e);o||(o=[],this.eventRefsMap.set(e,o));let s={asyncEvents:this,callback:n,name:e,thisArg:r};return o.push(s),s}once(e,n,r){let o=this.on(e,n,r),s=this.on(e,()=>{this.offref(o),this.offref(s)});return o}trigger(e,...n){let r=this.eventRefsMap.get(e)??[];for(let o of r.slice())this.tryTrigger(o,n)}async triggerAsync(e,...n){let r=this.eventRefsMap.get(e)??[];for(let o of r.slice())await this.tryTriggerAsync(o,n)}tryTrigger(e,n){try{e.callback.apply(e.thisArg,n)}catch(r){window.setTimeout(()=>{throw r},0)}}async tryTriggerAsync(e,n){try{await e.callback.call(e.thisArg,...n)}catch(r){window.setTimeout(()=>{throw r},0)}}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Ge(t,e){if(t!=null)return;throw e??=t===null?"Value is null":"Value is undefined",typeof e=="string"?new Error(e):e}i(Ge,"assertNonNullable");function ee(t,e){return Ge(t,e),t}i(ee,"ensureNonNullable");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var fs="asyncError",$r=new pt;$r.on(fs,Ph);var zr="An unhandled error occurred executing async operation",sc=" at",rt=class t extends Error{static{i(this,"CustomStackTraceError")}constructor(e,n,r){super(e,{cause:r}),this.name="CustomStackTraceError",Error.captureStackTrace?.(this,t);let o=r,s=new Set;for(;o instanceof t;){if(s.has(o))throw new Error("Circular cause detected");s.add(o),o=o.cause}let a=ee(this.stack).split(` +`),l=n.split(` +`);/^\w*Error(?:: |$)/.test(ee(l[0]))&&l.splice(0,1),a.splice(1,a.length-1,...l),this.stack=a.join(` +`)}},mn=class t extends Error{static{i(this,"SilentError")}constructor(e){super(e),this.name="SilentError",Error.captureStackTrace?.(this,t)}};function Vr(t){$r.trigger(fs,t)}i(Vr,"emitAsyncErrorEvent");function Ur(t){if(!(t instanceof Error))return String(t);let e=t.stack??`${t.name}: ${t.message}`;if(t.cause!==void 0){let n=Ur(t.cause).split(` +`);e+=` +${oc("Caused by:")}`;for(let r of n)r.trim()&&(e+=r.startsWith(sc)?` +${r}`:` +${oc(r)}`)}return e}i(Ur,"errorToString");function Pe(t=0){return ee(new Error().stack).split(` +`).slice(t+2).join(` +`)}i(Pe,"getStackTrace");function Wt(t,e){e??=globalThis.console,e.error(Ur(t))}i(Wt,"printError");function ac(t){let e=$r.on(fs,t);return()=>{$r.offref(e)}}i(ac,"registerAsyncErrorEventHandler");function oc(t){return`${sc} --- ${t} --- (0)`}i(oc,"generateStackTraceLine");function Ph(t){Wt(t)}i(Ph,"handleAsyncError");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function ms(t){return t.replaceAll(/[.*+?^${}()|[\]\\]/g,"\\$&")}i(ms,"escapeRegExp");function lc(t){try{return new RegExp(t),!0}catch{return!1}}i(lc,"isValidRegExp");var cc=/(?:)/,uc=/.^/;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function gn(t,e,...n){return e??=Se(),e.throwIfAborted(),Th(t)?await t(e,...n):t}i(gn,"resolveValue");function Th(t){return typeof t=="function"}i(Th,"isFunction");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Fh={"\n":"\\n","\r":"\\r"," ":"\\t","\b":"\\b","\f":"\\f","'":"\\'",'"':'\\"',"\\":"\\\\"};var Ih={};for(let[t,e]of Object.entries(Fh))Ih[e]=t;function dc(t,e,n,r){return r??=n,t.slice(0,n)+e+t.slice(r)}i(dc,"insertAt");function ar(t){return we(t,/\u00A0|\u202F/g," ").normalize("NFC")}i(ar,"normalize");function we(t,e,n){return typeof n>"u"?t:(e instanceof RegExp&&!e.global&&(e=new RegExp(e.source,`${e.flags}g`)),typeof n=="string"?t.replaceAll(e,n):t.replaceAll(e,(r,...o)=>{let a=typeof o.at(-1)=="object",l=a?o.length-2:o.length-1,c={groups:a?o.at(-1):void 0,missingGroupIndices:[],offset:o.at(l-1),source:o.at(l),substring:r},u=o.slice(0,l-1).map((d,p)=>{if(typeof d=="string")return d;if(typeof d>"u")return c.missingGroupIndices.push(p),"";throw new Error(`Unexpected argument type: ${typeof d}`)});return n(c,...u)??c.substring}))}i(we,"replaceAll");function lr(t,e,n){if(t.endsWith(e))return t.slice(0,-e.length);if(n)throw new Error(`String ${t} does not end with suffix ${e}`);return t}i(lr,"trimEnd");function Wr(t,e,n){if(t.startsWith(e))return t.slice(e.length);if(n)throw new Error(`String ${t} does not start with prefix ${e}`);return t}i(Wr,"trimStart");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Mh=/[a-zA-Z]:\/[^:]*$/,ht=gs.default.posix,qw=ht.delimiter,Gw=gs.default.posix.sep,Ne=ht.basename,K=ht.dirname,it=ht.extname,Yw=ht.format;var oe=ht.join,Jw=ht.normalize,Qw=ht.parse,bn=ht.relative;function pc(t,e){return e?`${t}.${e}`:t}i(pc,"makeFileName");function hc(...t){let e=ht.resolve(...t);return e=Lh(e),Mh.exec(e)?.[0]??e}i(hc,"resolve");function Lh(t){return we(t,"\\","/")}i(Lh,"toPosixPath");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Nh="base",Hr="canvas",Ht="md";function bs(t){return t.map(e=>jr(e))}i(bs,"asArrayOfFiles");function ws(t){return t.map(e=>Kr(e))}i(ws,"asArrayOfFolders");function jr(t){return ee(ys(t),"Abstract file is not a file")}i(jr,"asFile");function ys(t){if(t===null)return null;if(t instanceof ot.TFile)return t;throw new Error("Abstract file is not a file")}i(ys,"asFileOrNull");function Kr(t){return ee(qr(t),"Abstract file is not a folder")}i(Kr,"asFolder");function qr(t){if(t===null)return null;if(t instanceof ot.TFolder)return t;throw new Error("Abstract file is not a folder")}i(qr,"asFolderOrNull");function ks(t,e,n){if(Z(e))return e.extension===n;if(typeof e=="string"){let r=X(t,e);return r?r.extension===n:it(e).slice(1)===n}return!1}i(ks,"checkExtension");function mc(t,e,n){return ee(ft(t,e,n),`Abstract file not found: ${e}`)}i(mc,"getAbstractFile");function ft(t,e,n){if(e===null)return null;if(bc(e))return Z(e)?t.vault.getFileByPath(e.path)??e:Ve(e)?t.vault.getFolderByPath(e.path)??e:t.vault.getAbstractFileByPath(e.path)??e;let r=fc(t,e,n);if(r)return r;let o=wc(e);return o===e?null:fc(t,o,n)}i(ft,"getAbstractFileOrNull");function ae(t,e,n,r){let o=X(t,e,r);if(!o)if(n)o=Ql(t,e);else throw new Error(`File not found: ${e}`);return o}i(ae,"getFile");function X(t,e,n){let r=ft(t,e,n);return Z(r)?r:null}i(X,"getFileOrNull");function wn(t,e,n,r){let o=st(t,e,r);if(!o)if(n)o=_r(t,e);else throw new Error(`Folder not found: ${e}`);return o}i(wn,"getFolder");function st(t,e,n){let r=ft(t,e,n);return Ve(r)?r:null}i(st,"getFolderOrNull");async function gc(t,e){let n=X(t,e);if(n)return n;let r=qe(e);return await Oh(t,r),await t.vault.create(e,"")}i(gc,"getOrCreateFile");async function Oh(t,e){let n=st(t,e);return n||await t.vault.createFolder(e)}i(Oh,"getOrCreateFolder");function G(t,e){if(bc(e))return e.path;let n=ft(t,e);return n?n.path:wc(e)}i(G,"getPath");function bc(t){return t instanceof ot.TAbstractFile}i(bc,"isAbstractFile");function Rh(t,e){return ks(t,e,Nh)}i(Rh,"isBaseFile");function St(t,e){return ks(t,e,Hr)}i(St,"isCanvasFile");function Z(t){return t instanceof ot.TFile}i(Z,"isFile");function Ve(t){return t instanceof ot.TFolder}i(Ve,"isFolder");function Ye(t,e){return ks(t,e,Ht)}i(Ye,"isMarkdownFile");function Oe(t,e){return Ye(t,e)||St(t,e)||Rh(t,e)}i(Oe,"isNote");function fc(t,e,n){return n??=t.vault.adapter.insensitive,n?t.vault.getAbstractFileByPathInsensitive(e):t.vault.getAbstractFileByPath(e)}i(fc,"getFileInternal");function wc(t){return(0,ot.normalizePath)(hc("/",t))}i(wc,"getResolvedPath");var Gc=require("obsidian");var Ps=hn(Fc(),1);i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var vs="50.0.0",Xr="obsidian-dev-utils",Ic=`.obsidian-dev-utils.code-highlighter-component textarea, .obsidian-dev-utils.code-highlighter-component pre, .obsidian-dev-utils.code-highlighter-component code { + font-family: var(--font-monospace); + line-height: var(--line-height-normal); + margin: 0; +} +.obsidian-dev-utils.code-highlighter-component textarea, .obsidian-dev-utils.code-highlighter-component code { + font-size: var(--code-size); +} +.obsidian-dev-utils.code-highlighter-component textarea { + background: transparent; + color: transparent; + z-index: 2; + width: 20em; + height: 10em; +} +.obsidian-dev-utils.code-highlighter-component pre { + position: absolute; + pointer-events: none; + border: var(--input-border-width) solid transparent; + overflow: auto; + inset: 0; + padding: var(--size-4-1) var(--size-4-2); + z-index: 1; +} +.obsidian-dev-utils.code-highlighter-component pre::after { + content: ""; + display: block; + height: var(--bottom-gap, 0); +} +.obsidian-dev-utils.code-highlighter-component pre.is-placeholder { + opacity: 0.6; +} +.obsidian-dev-utils.code-highlighter-component code { + display: block; + padding: 0; +} + +.obsidian-dev-utils input[type=url] { + height: var(--input-height); +} +.obsidian-dev-utils input[type=month], +.obsidian-dev-utils input[type=tel], +.obsidian-dev-utils input[type=time], +.obsidian-dev-utils input[type=url], +.obsidian-dev-utils input[type=week] { + -webkit-app-region: no-drag; + background: var(--background-modifier-form-field); + border: var(--input-border-width) solid var(--background-modifier-border); + color: var(--text-normal); + font-family: inherit; + padding: var(--size-4-1) var(--size-4-2); + font-size: var(--font-ui-small); + border-radius: var(--input-radius); + outline: none; +} +@media (hover: hover) { + .obsidian-dev-utils input[type=month]:hover, + .obsidian-dev-utils input[type=tel]:hover, + .obsidian-dev-utils input[type=time]:hover, + .obsidian-dev-utils input[type=url]:hover, + .obsidian-dev-utils input[type=week]:hover { + border-color: var(--background-modifier-border-hover); + transition: box-shadow 0.15s ease-in-out, border 0.15s ease-in-out; + } +} +.obsidian-dev-utils input[type=month]:active, .obsidian-dev-utils input[type=month]:focus, +.obsidian-dev-utils input[type=tel]:active, +.obsidian-dev-utils input[type=tel]:focus, +.obsidian-dev-utils input[type=time]:active, +.obsidian-dev-utils input[type=time]:focus, +.obsidian-dev-utils input[type=url]:active, +.obsidian-dev-utils input[type=url]:focus, +.obsidian-dev-utils input[type=week]:active, +.obsidian-dev-utils input[type=week]:focus { + border-color: var(--background-modifier-border-focus); + transition: box-shadow 0.15s ease-in-out, border 0.15s ease-in-out; +} +.obsidian-dev-utils input[type=month]:active, .obsidian-dev-utils input[type=month]:focus, .obsidian-dev-utils input[type=month]:focus-visible, +.obsidian-dev-utils input[type=tel]:active, +.obsidian-dev-utils input[type=tel]:focus, +.obsidian-dev-utils input[type=tel]:focus-visible, +.obsidian-dev-utils input[type=time]:active, +.obsidian-dev-utils input[type=time]:focus, +.obsidian-dev-utils input[type=time]:focus-visible, +.obsidian-dev-utils input[type=url]:active, +.obsidian-dev-utils input[type=url]:focus, +.obsidian-dev-utils input[type=url]:focus-visible, +.obsidian-dev-utils input[type=week]:active, +.obsidian-dev-utils input[type=week]:focus, +.obsidian-dev-utils input[type=week]:focus-visible { + box-shadow: 0 0 0 2px var(--background-modifier-border-focus); +} +.obsidian-dev-utils input[type=month]::placeholder, +.obsidian-dev-utils input[type=tel]::placeholder, +.obsidian-dev-utils input[type=time]::placeholder, +.obsidian-dev-utils input[type=url]::placeholder, +.obsidian-dev-utils input[type=week]::placeholder { + color: var(--text-faint); +} +.mod-rtl input[type=month], +.mod-rtl input[type=time], +.mod-rtl input[type=week], +.is-rtl input[type=month], +.is-rtl input[type=time], +.is-rtl input[type=week], +.rtl input[type=month], +.rtl input[type=time], +.rtl input[type=week] { + direction: rtl; +} +.mod-rtl input[type=month]::-webkit-calendar-picker-indicator, +.mod-rtl input[type=time]::-webkit-calendar-picker-indicator, +.mod-rtl input[type=week]::-webkit-calendar-picker-indicator, +.is-rtl input[type=month]::-webkit-calendar-picker-indicator, +.is-rtl input[type=time]::-webkit-calendar-picker-indicator, +.is-rtl input[type=week]::-webkit-calendar-picker-indicator, +.rtl input[type=month]::-webkit-calendar-picker-indicator, +.rtl input[type=time]::-webkit-calendar-picker-indicator, +.rtl input[type=week]::-webkit-calendar-picker-indicator { + right: var(--size-4-1); + left: auto; +} + +.obsidian-dev-utils input[type=month], +.obsidian-dev-utils input[type=time], +.obsidian-dev-utils input[type=week] { + font-variant-numeric: tabular-nums; + position: relative; +} +.obsidian-dev-utils input[type=month]::-webkit-datetime-edit-text, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-text, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-text { + color: var(--text-faint); + padding-inline-end: 0; +} +.obsidian-dev-utils input[type=month]::-webkit-calendar-picker-indicator, +.obsidian-dev-utils input[type=time]::-webkit-calendar-picker-indicator, +.obsidian-dev-utils input[type=week]::-webkit-calendar-picker-indicator { + position: absolute; + left: var(--size-4-1); + right: auto; + opacity: 0.5; +} +.obsidian-dev-utils input[type=month]::-webkit-datetime-edit-month-field:active, .obsidian-dev-utils input[type=month]::-webkit-datetime-edit-month-field:focus, .obsidian-dev-utils input[type=month]::-webkit-datetime-edit-day-field:active, .obsidian-dev-utils input[type=month]::-webkit-datetime-edit-day-field:focus, .obsidian-dev-utils input[type=month]::-webkit-datetime-edit-year-field:active, .obsidian-dev-utils input[type=month]::-webkit-datetime-edit-year-field:focus, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-month-field:active, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-month-field:focus, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-day-field:active, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-day-field:focus, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-year-field:active, +.obsidian-dev-utils input[type=time]::-webkit-datetime-edit-year-field:focus, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-month-field:active, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-month-field:focus, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-day-field:active, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-day-field:focus, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-year-field:active, +.obsidian-dev-utils input[type=week]::-webkit-datetime-edit-year-field:focus { + background-color: var(--text-selection); + color: var(--text-normal); + cursor: text; +} +.mod-rtl .obsidian-dev-utils input[type=month], .is-rtl .obsidian-dev-utils input[type=month], .rtl .obsidian-dev-utils input[type=month], +.mod-rtl .obsidian-dev-utils input[type=time], +.is-rtl .obsidian-dev-utils input[type=time], +.rtl .obsidian-dev-utils input[type=time], +.mod-rtl .obsidian-dev-utils input[type=week], +.is-rtl .obsidian-dev-utils input[type=week], +.rtl .obsidian-dev-utils input[type=week] { + direction: rtl; +} +.mod-rtl .obsidian-dev-utils input[type=month]::-webkit-calendar-picker-indicator, .is-rtl .obsidian-dev-utils input[type=month]::-webkit-calendar-picker-indicator, .rtl .obsidian-dev-utils input[type=month]::-webkit-calendar-picker-indicator, +.mod-rtl .obsidian-dev-utils input[type=time]::-webkit-calendar-picker-indicator, +.is-rtl .obsidian-dev-utils input[type=time]::-webkit-calendar-picker-indicator, +.rtl .obsidian-dev-utils input[type=time]::-webkit-calendar-picker-indicator, +.mod-rtl .obsidian-dev-utils input[type=week]::-webkit-calendar-picker-indicator, +.is-rtl .obsidian-dev-utils input[type=week]::-webkit-calendar-picker-indicator, +.rtl .obsidian-dev-utils input[type=week]::-webkit-calendar-picker-indicator { + left: auto; + right: var(--size-4-1); +} + +body:not(.is-ios):not(.is-android) .obsidian-dev-utils input[type=month], +body:not(.is-ios):not(.is-android) .obsidian-dev-utils input[type=time], +body:not(.is-ios):not(.is-android) .obsidian-dev-utils input[type=week] { + padding-inline-start: var(--size-4-6); +} + +.obsidian-dev-utils input[type=time]::-webkit-calendar-picker-indicator { + margin-inline-start: 0; +} + +.obsidian-dev-utilsprogress.loop { + min-width: 200px; +} + +.obsidian-dev-utils.modal-container .ok-button { + margin-right: 10px; + margin-top: 20px; +} + +.obsidian-dev-utils .multiple-dropdown-component select, +.obsidian-dev-utils .multiple-dropdown-component select:focus, +.obsidian-dev-utils .multiple-dropdown-component .dropdown { + height: auto; + padding-top: 3px; +} +.obsidian-dev-utils .multiple-dropdown-component select option:checked, +.obsidian-dev-utils .multiple-dropdown-component select:focus option:checked, +.obsidian-dev-utils .multiple-dropdown-component .dropdown option:checked { + background-color: #1967d2; + color: #fff; +} + +.obsidian-dev-utils.plugin-settings-tab a:focus { + outline: 2px solid var(--link-color); +} + +.obsidian-dev-utils.prompt-modal .text-box { + width: 100%; +} + +.obsidian-dev-utils.tri-state-checkbox-component input[type=checkbox]:indeterminate { + appearance: checkbox; +} + +.obsidian-dev-utils :invalid { + box-shadow: 0 0 0 2px var(--text-error); +} +.obsidian-dev-utils input.metadata-input-text:active:invalid, .obsidian-dev-utils input.metadata-input-text:focus-visible:invalid, .obsidian-dev-utils input.metadata-input-text:focus:invalid, +.obsidian-dev-utils input[type=date]:active:invalid, +.obsidian-dev-utils input[type=date]:focus-visible:invalid, +.obsidian-dev-utils input[type=date]:focus:invalid, +.obsidian-dev-utils input[type=datetime-local]:active:invalid, +.obsidian-dev-utils input[type=datetime-local]:focus-visible:invalid, +.obsidian-dev-utils input[type=datetime-local]:focus:invalid, +.obsidian-dev-utils input[type=email]:active:invalid, +.obsidian-dev-utils input[type=email]:focus-visible:invalid, +.obsidian-dev-utils input[type=email]:focus:invalid, +.obsidian-dev-utils input[type=number]:active:invalid, +.obsidian-dev-utils input[type=number]:focus-visible:invalid, +.obsidian-dev-utils input[type=number]:focus:invalid, +.obsidian-dev-utils input[type=password]:active:invalid, +.obsidian-dev-utils input[type=password]:focus-visible:invalid, +.obsidian-dev-utils input[type=password]:focus:invalid, +.obsidian-dev-utils input[type=search]:active:invalid, +.obsidian-dev-utils input[type=search]:focus-visible:invalid, +.obsidian-dev-utils input[type=search]:focus:invalid, +.obsidian-dev-utils input[type=text]:active:invalid, +.obsidian-dev-utils input[type=text]:focus-visible:invalid, +.obsidian-dev-utils input[type=text]:focus:invalid, +.obsidian-dev-utils textarea:active:invalid, +.obsidian-dev-utils textarea:focus-visible:invalid, +.obsidian-dev-utils textarea:focus:invalid { + box-shadow: 0 0 0 2px var(--text-error); +} +.obsidian-dev-utils.setting-component-wrapper { + position: relative; + display: inline-flex; +} +.obsidian-dev-utils.overlay-validator { + caret-color: transparent; + cursor: default; + position: absolute; + background-color: transparent; + border: none; + outline: none; + pointer-events: none; + z-index: 9999; + left: 0; + top: 0; + width: 100%; + height: 100%; +} +.obsidian-dev-utils.tooltip.tooltip-validator { + position: absolute; + top: calc(100% + 8px); + width: max-content; +} + +/*# sourceMappingURL=data:application/json;charset=utf-8,%7B%22version%22:3,%22sourceRoot%22:%22%22,%22sources%22:%5B%22../src/styles/code-highlighter-component.scss%22,%22../src/styles/input.scss%22,%22../src/styles/input-time.scss%22,%22../src/styles/loop.scss%22,%22../src/styles/modal-container.scss%22,%22../src/styles/multiple-dropdown-component.scss%22,%22../src/styles/plugin-settings-tab.scss%22,%22../src/styles/prompt-modal.scss%22,%22../src/styles/tri-state-checkbox-component.scss%22,%22../src/styles/validation.scss%22%5D,%22names%22:%5B%5D,%22mappings%22:%22AAEI;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;;;ACzCJ;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;EAKE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGE;EACE;AAAA;AAAA;AAAA;AAAA;IACE;IACA,YACE;;;AAMR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;EACA,YACE;;AAIJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAGF;AAAA;AAAA;AAAA;AAAA;EACE;;AASE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGE;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;;AC7DV;AAAA;AAAA;EAGE;EACA;;AAEA;AAAA;AAAA;EACE;EACA;;AAGF;AAAA;AAAA;EACE;EACA;EACA;EACA;;AAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAEE;EACA;EACA;;AAIK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EAGP;;AAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EACE;EACA;;;AAKF;AAAA;AAAA;EACE;;;AAMJ;EACE;;;ACjDJ;EACE;;;ACAA;EACE;EACA;;;ACFF;AAAA;AAAA;EAGE;EACA;;AAEA;AAAA;AAAA;EACE;EACA;;;ACRJ;EACE;;;ACDF;EACE;;;ACDF;EACE;;;ACEJ;EAJA;;AAoBI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;EApBJ;;AA0BA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA%22,%22file%22:%22styles.css%22,%22sourcesContent%22:%5B%22.obsidian-dev-utils%20%7B%5Cn%20%20&.code-highlighter-component%20%7B%5Cn%20%20%20%20textarea,%20pre,%20code%20%7B%5Cn%20%20%20%20%20%20font-family:%20var(--font-monospace);%5Cn%20%20%20%20%20%20line-height:%20var(--line-height-normal);%5Cn%20%20%20%20%20%20margin:%200;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20textarea,%20code%20%7B%5Cn%20%20%20%20%20%20font-size:%20var(--code-size);%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20textarea%20%7B%5Cn%20%20%20%20%20%20background:%20transparent;%5Cn%20%20%20%20%20%20color:%20transparent;%5Cn%20%20%20%20%20%20z-index:%202;%5Cn%20%20%20%20%20%20width:%2020em;%5Cn%20%20%20%20%20%20height:%2010em;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20pre%20%7B%5Cn%20%20%20%20%20%20position:%20absolute;%5Cn%20%20%20%20%20%20pointer-events:%20none;%5Cn%20%20%20%20%20%20border:%20var(--input-border-width)%20solid%20transparent;%5Cn%20%20%20%20%20%20overflow:%20auto;%5Cn%20%20%20%20%20%20inset:%200;%5Cn%20%20%20%20%20%20padding:%20var(--size-4-1)%20var(--size-4-2);%5Cn%20%20%20%20%20%20z-index:%201;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20pre::after%20%7B%5Cn%20%20%20%20%20%20content:%20%5C%22%5C%22;%5Cn%20%20%20%20%20%20display:%20block;%5Cn%20%20%20%20%20%20height:%20var(--bottom-gap,%200);%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20pre.is-placeholder%20%7B%5Cn%20%20%20%20%20%20opacity:%200.6;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20code%20%7B%5Cn%20%20%20%20%20%20display:%20block;%5Cn%20%20%20%20%20%20padding:%200;%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20input%5Btype='url'%5D%20%7B%5Cn%20%20%20%20height:%20var(--input-height)%5Cn%20%20%7D%5Cn%5Cn%20%20input%5Btype='month'%5D,%5Cn%20%20input%5Btype='tel'%5D,%5Cn%20%20input%5Btype='time'%5D,%5Cn%20%20input%5Btype='url'%5D,%5Cn%20%20input%5Btype='week'%5D%20%7B%5Cn%20%20%20%20-webkit-app-region:%20no-drag;%5Cn%20%20%20%20background:%20var(--background-modifier-form-field);%5Cn%20%20%20%20border:%20var(--input-border-width)%20solid%20var(--background-modifier-border);%5Cn%20%20%20%20color:%20var(--text-normal);%5Cn%20%20%20%20font-family:%20inherit;%5Cn%20%20%20%20padding:%20var(--size-4-1)%20var(--size-4-2);%5Cn%20%20%20%20font-size:%20var(--font-ui-small);%5Cn%20%20%20%20border-radius:%20var(--input-radius);%5Cn%20%20%20%20outline:%20none;%5Cn%5Cn%20%20%20%20@at-root%20%7B%5Cn%20%20%20%20%20%20@media%20(hover:%20hover)%20%7B%5Cn%20%20%20%20%20%20%20%20&:hover%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20border-color:%20var(--background-modifier-border-hover);%5Cn%20%20%20%20%20%20%20%20%20%20transition:%5Cn%20%20%20%20%20%20%20%20%20%20%20%20box-shadow%200.15s%20ease-in-out,%5Cn%20%20%20%20%20%20%20%20%20%20%20%20border%200.15s%20ease-in-out;%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20&:active,%5Cn%20%20%20%20&:focus%20%7B%5Cn%20%20%20%20%20%20border-color:%20var(--background-modifier-border-focus);%5Cn%20%20%20%20%20%20transition:%5Cn%20%20%20%20%20%20%20%20box-shadow%200.15s%20ease-in-out,%5Cn%20%20%20%20%20%20%20%20border%200.15s%20ease-in-out;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20&:active,%5Cn%20%20%20%20&:focus,%5Cn%20%20%20%20&:focus-visible%20%7B%5Cn%20%20%20%20%20%20box-shadow:%200%200%200%202px%20var(--background-modifier-border-focus);%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20&::placeholder%20%7B%5Cn%20%20%20%20%20%20color:%20var(--text-faint);%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%5Cn%20%20@at-root%20%7B%5Cn%20%20%20%20.mod-rtl,%5Cn%20%20%20%20.is-rtl,%5Cn%20%20%20%20.rtl%20%7B%5Cn%20%20%20%20%20%20&%20%7B%5Cn%20%20%20%20%20%20%20%20input%5Btype='month'%5D,%5Cn%20%20%20%20%20%20%20%20input%5Btype='time'%5D,%5Cn%20%20%20%20%20%20%20%20input%5Btype='week'%5D%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20direction:%20rtl;%5Cn%5Cn%20%20%20%20%20%20%20%20%20%20&::-webkit-calendar-picker-indicator%20%7B%5Cn%20%20%20%20%20%20%20%20%20%20%20%20right:%20var(--size-4-1);%5Cn%20%20%20%20%20%20%20%20%20%20%20%20left:%20auto;%5Cn%20%20%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%20%20%7D%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20input%5Btype='month'%5D,%5Cn%20%20input%5Btype='time'%5D,%5Cn%20%20input%5Btype='week'%5D%20%7B%5Cn%20%20%20%20font-variant-numeric:%20tabular-nums;%5Cn%20%20%20%20position:%20relative;%5Cn%5Cn%20%20%20%20&::-webkit-datetime-edit-text%20%7B%5Cn%20%20%20%20%20%20color:%20var(--text-faint);%5Cn%20%20%20%20%20%20padding-inline-end:%200;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20&::-webkit-calendar-picker-indicator%20%7B%5Cn%20%20%20%20%20%20position:%20absolute;%5Cn%20%20%20%20%20%20left:%20var(--size-4-1);%5Cn%20%20%20%20%20%20right:%20auto;%5Cn%20%20%20%20%20%20opacity:%200.5;%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20&::-webkit-datetime-edit-month-field,%5Cn%20%20%20%20&::-webkit-datetime-edit-day-field,%5Cn%20%20%20%20&::-webkit-datetime-edit-year-field%20%7B%5Cn%20%20%20%20%20%20&:active,%5Cn%20%20%20%20%20%20&:focus%20%7B%5Cn%20%20%20%20%20%20%20%20background-color:%20var(--text-selection);%5Cn%20%20%20%20%20%20%20%20color:%20var(--text-normal);%5Cn%20%20%20%20%20%20%20%20cursor:%20text;%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20@at-root%20.mod-rtl%20&,%5Cn%20%20%20%20%20%20.is-rtl%20&,%5Cn%20%20%20%20%20%20.rtl%20&%20%7B%5Cn%20%20%20%20%20%20direction:%20rtl;%5Cn%5Cn%20%20%20%20%20%20&::-webkit-calendar-picker-indicator%20%7B%5Cn%20%20%20%20%20%20%20%20left:%20auto;%5Cn%20%20%20%20%20%20%20%20right:%20var(--size-4-1);%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%5Cn%20%20%20%20@at-root%20%7B%5Cn%20%20%20%20%20%20body:not(.is-ios):not(.is-android)%20&%20%7B%5Cn%20%20%20%20%20%20%20%20padding-inline-start:%20var(--size-4-6);%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%5Cn%20%20input%5Btype='time'%5D%20%7B%5Cn%20%20%20%20&::-webkit-calendar-picker-indicator%20%7B%5Cn%20%20%20%20%20%20margin-inline-start:%200;%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20&progress.loop%20%7B%5Cn%20%20%20%20min-width:%20200px;%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20&.modal-container%20%7B%5Cn%20%20%20%20.ok-button%20%7B%5Cn%20%20%20%20%20%20margin-right:%2010px;%5Cn%20%20%20%20%20%20margin-top:%2020px;%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20.multiple-dropdown-component%20%7B%5Cn%20%20%20%20select,%5Cn%20%20%20%20select:focus,%5Cn%20%20%20%20.dropdown%20%7B%5Cn%20%20%20%20%20%20height:%20auto;%5Cn%20%20%20%20%20%20padding-top:%203px;%5Cn%5Cn%20%20%20%20%20%20option:checked%20%7B%5Cn%20%20%20%20%20%20%20%20background-color:%20%231967d2;%5Cn%20%20%20%20%20%20%20%20color:%20%23fff;%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20&.plugin-settings-tab%20%7B%5Cn%20%20%20%20a:focus%20%7B%5Cn%20%20%20%20%20%20outline:%202px%20solid%20var(--link-color);%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cn%20%20&.prompt-modal%20%7B%5Cn%20%20%20%20.text-box%20%7B%5Cn%20%20%20%20%20%20width:%20100%25;%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%7D%5Cn%22,%22.obsidian-dev-utils%20%7B%5Cr%5Cn%20%20&.tri-state-checkbox-component%20%7B%5Cr%5Cn%20%20%20%20input%5Btype='checkbox'%5D:indeterminate%20%7B%5Cr%5Cn%20%20%20%20%20%20appearance:%20checkbox;%5Cr%5Cn%20%20%20%20%7D%5Cr%5Cn%20%20%7D%5Cr%5Cn%7D%5Cr%5Cn%22,%22@mixin%20invalid%20%7B%5Cn%20%20box-shadow:%200%200%200%202px%20var(--text-error);%5Cn%7D%5Cn%5Cn.obsidian-dev-utils%20%7B%5Cn%20%20:invalid%20%7B%5Cn%20%20%20%20@include%20invalid;%5Cn%20%20%7D%5Cn%5Cn%20%20input.metadata-input-text,%5Cn%20%20input%5Btype='date'%5D,%5Cn%20%20input%5Btype='datetime-local'%5D,%5Cn%20%20input%5Btype='email'%5D,%5Cn%20%20input%5Btype='number'%5D,%5Cn%20%20input%5Btype='password'%5D,%5Cn%20%20input%5Btype='search'%5D,%5Cn%20%20input%5Btype='text'%5D,%5Cn%20%20textarea%20%7B%5Cn%20%20%20%20&:active,%5Cn%20%20%20%20&:focus-visible,%5Cn%20%20%20%20&:focus%20%7B%5Cn%20%20%20%20%20%20&:invalid%20%7B%5Cn%20%20%20%20%20%20%20%20@include%20invalid;%5Cn%20%20%20%20%20%20%7D%5Cn%20%20%20%20%7D%5Cn%20%20%7D%5Cn%5Cn%20%20&.setting-component-wrapper%20%7B%5Cn%20%20%20%20position:%20relative;%5Cn%20%20%20%20display:%20inline-flex;%5Cn%20%20%7D%5Cn%5Cn%20%20&.overlay-validator%20%7B%5Cn%20%20%20%20caret-color:%20transparent;%5Cn%20%20%20%20cursor:%20default;%5Cn%20%20%20%20position:%20absolute;%5Cn%20%20%20%20background-color:%20transparent;%5Cn%20%20%20%20border:%20none;%5Cn%20%20%20%20outline:%20none;%5Cn%20%20%20%20pointer-events:%20none;%5Cn%20%20%20%20z-index:%209999;%5Cn%20%20%20%20left:%200;%5Cn%20%20%20%20top:%200;%5Cn%20%20%20%20width:%20100%25;%5Cn%20%20%20%20height:%20100%25;%5Cn%20%20%7D%5Cn%5Cn%20%20&.tooltip.tooltip-validator%20%7B%5Cn%20%20%20%20position:%20absolute;%5Cn%20%20%20%20top:%20calc(100%25%20+%208px);%5Cn%20%20%20%20width:%20max-content;%5Cn%20%20%7D%5Cn%7D%5Cn%22%5D%7D */ +`;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Es=class{static{i(this,"ValueWrapper")}constructor(e){this.value=e}};function sf(){let t=globalThis.app;if(t)return t;try{return globalThis.require("obsidian/app")}catch{throw new Error("Obsidian App global instance not found")}}i(sf,"getApp");function Te(t,e,n){let o=t??af()??globalThis;return o.obsidianDevUtilsState??={},o.obsidianDevUtilsState[e]??=new Es(n)}i(Te,"getObsidianDevUtilsState");function af(){return typeof window>"u"?null:sf()}i(af,"getAppOrNull");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Ss="__no-plugin-id-initialized__",Mc=Ss;function Zr(){return Mc}i(Zr,"getPluginId");function Lc(t){t&&(Mc=t)}i(Lc,"setPluginId");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Nc=",",ei="-";function Oc(){return{disable:lf,enable:cf,get:ti,set:cr}}i(Oc,"getDebugController");function xn(t,e=0){let n=`${t}:${String(e)}`,r=Te(null,"debuggers",new Map).value,o=r.get(n);return o||(o=ur()(t),o.log=(s,...a)=>{uf(t,e,s,...a)},r.set(n,o)),o}i(xn,"getDebugger");function Y(t){let e=Zr(),n=e===Ss?"":`${e}:`;return xn(`${n}${Xr}:${t}`)}i(Y,"getLibDebugger");function mt(t,e,n,...r){if(!Dc()){t(n,...r);return}t(n,...r,` + +--- +Context stack trace: +`,Bc(e))}i(mt,"printWithStackTrace");function Rc(t){let e=ur().enabled(t),n=e?"enabled":"disabled",r=e?"disable":"enable",o=ti();cr(t),xn(t)(`Debug messages for plugin ${t} are ${n}. See https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/debugging.md how to ${r} them.`),cr(o)}i(Rc,"showInitialDebugMessage");function lf(t){let e=new Set(ti());for(let n of dr(t)){if(n.startsWith(ei))continue;let r=ei+n;e.has(n)&&e.delete(n),e.add(r)}cr(Array.from(e))}i(lf,"disableNamespaces");function cf(t){let e=new Set(ti());for(let n of dr(t)){if(!n.startsWith(ei)){let r=ei+n;e.has(r)&&e.delete(r)}e.add(n)}cr(Array.from(e))}i(cf,"enableNamespaces");function ti(){return dr(ur().load()??"")}i(ti,"getNamespaces");function ur(){return typeof window>"u"?Ps.default:Te(null,"debug",Ps.default).value}i(ur,"getSharedDebugLibInstance");function Dc(){return typeof window<"u"}i(Dc,"isInObsidian");function uf(t,e,n,...r){if(!ur().enabled(t))return;if(!Dc()){console.debug(n,...r);return}let o=4,s=new Error().stack?.split(` +`)??[];s.splice(0,o+e),console.debug(n,...r,` + +--- +Logger stack trace: +`,Bc(s.join(` +`)))}i(uf,"logWithCaller");function Bc(t){return new rt("Debug mode: intentional placeholder error. See https://github.com/mnaoumov/obsidian-dev-utils/blob/main/docs/debugging.md.",t,void 0)}i(Bc,"makeStackTraceError");function cr(t){ur().enable(dr(t).join(Nc))}i(cr,"setNamespaces");function dr(t){return typeof t=="string"?t.split(Nc).filter(Boolean):t.flatMap(dr)}i(dr,"toArray");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var _c=".",df=[{constructor:ArrayBuffer,equalityComparer:hf},{constructor:Date,equalityComparer:ff},{constructor:RegExp,equalityComparer:gf},{constructor:Map,equalityComparer:mf},{constructor:Set,equalityComparer:bf}];function Je(t,e){if(t===e)return!0;if(typeof t!="object"||typeof e!="object"||t===null||e===null)return!1;let n=t.constructor,r=e.constructor;if(n!==r)return!1;if(n!==Object){let c=wf(t,e);if(c!==void 0)return c}let o=vn(t),s=vn(e);if(o.length!==s.length)return!1;let a=t,l=e;for(let c of o)if(!s.includes(c)||!Je(a[c],l[c]))return!1;return!0}i(Je,"deepEqual");function It(t){return typeof t!="object"||t===null?t:"default"in t?t.default:t}i(It,"extractDefaultExportInterop");function vn(t){let e=[],n=t;for(;n;){let r=Object.getOwnPropertyDescriptors(n);for(let[o,s]of Object.entries(r)){if(o==="__proto__"||typeof s.value=="function")continue;let a=typeof s.get=="function",l=typeof s.set=="function";if(a||l){a&&l&&e.push(o);continue}s.enumerable&&s.writable&&e.push(o)}n=Object.getPrototypeOf(n)}return e.sort()}i(vn,"getAllKeys");function En(t,e){let n=t,r=e.split(_c);for(let o of r){if(n===void 0)return;n=n[o]}return n}i(En,"getNestedPropertyValue");function $c(t,e,n){let r=new Error(`Property path ${e} not found`),o=t,s=e.split(_c);for(let l of s.slice(0,-1)){if(o===void 0)throw r;o=o[l]}let a=ee(s.at(-1));if(o===void 0)throw r;o[a]=n}i($c,"setNestedPropertyValue");function Kt(t,e={}){let n={functionHandlingMode:"exclude",maxDepth:-1,shouldCatchToJSONErrors:!1,shouldHandleCircularReferences:!1,shouldHandleErrors:!1,shouldHandleUndefined:!1,shouldSortKeys:!1,space:2,tokenSubstitutions:{circularReference:Ts("CircularReference"),maxDepthLimitReached:Ts("MaxDepthLimitReached"),toJSONFailed:Ts("ToJSONFailed")}},r={...n,...e,tokenSubstitutions:{...n.tokenSubstitutions,...e.tokenSubstitutions}};r.maxDepth===-1&&(r.maxDepth=1/0);let o=[],a=ni(t,"",0,!0,r,o,new WeakSet),l=ee(JSON.stringify(a,null,r.space));return l=we(l,/"\[\[(?[A-Za-z]+)(?\d*)\]\]"/g,(c,u,d)=>pf({functionTexts:o,index:d?parseInt(d,10):0,key:u,substitutions:r.tokenSubstitutions})),l}i(Kt,"toJson");function pf(t){switch(t.key){case"CircularReference":return t.substitutions.circularReference;case"Function":return ee(t.functionTexts[t.index],`Function with index ${String(t.index)} not found`);case"MaxDepthLimitReached":return t.substitutions.maxDepthLimitReached;case"MaxDepthLimitReachedArray":return`Array(${String(t.index)})`;case"ToJSONFailed":return t.substitutions.toJSONFailed;case"Undefined":return"undefined";default:break}}i(pf,"applySubstitutions");function hf(t,e){if(t.byteLength!==e.byteLength)return!1;let n=new Uint8Array(t),r=new Uint8Array(e);return Je(n,r)}i(hf,"deepEqualArrayBuffer");function ff(t,e){return t.getTime()===e.getTime()}i(ff,"deepEqualDate");function mf(t,e){if(t.size!==e.size)return!1;for(let[n,r]of t.entries())if(!e.has(n)||!Je(r,e.get(n)))return!1;return!0}i(mf,"deepEqualMap");function gf(t,e){return t.source===e.source&&t.flags===e.flags}i(gf,"deepEqualRegExp");function bf(t,e){if(t.size!==e.size)return!1;for(let n of t){if(e.has(n))continue;let r=!1;for(let o of e)if(Je(n,o)){r=!0;break}if(!r)return!1}return!0}i(bf,"deepEqualSet");function wf(t,e){for(let{constructor:n,equalityComparer:r}of df)if(t instanceof n&&e instanceof n)return r(t,e)}i(wf,"deepEqualTyped");function yf(t,e,n,r,o,s){return e>r.maxDepth?Sn("MaxDepthLimitReachedArray",t.length):t.map((a,l)=>ni(a,String(l),e+1,n,r,o,s))}i(yf,"handleArray");function kf(t,e,n){if(n.shouldHandleCircularReferences)return Sn("CircularReference");let r=t.constructor.name||"Object";throw new TypeError(`Converting circular structure to JSON +--> starting at object with constructor '${r}' +--- property '${e}' closes the circle`)}i(kf,"handleCircularReference");function Cf(t,e,n){if(n.functionHandlingMode==="exclude")return;let r=e.length,o=n.functionHandlingMode==="full"?String(t):`function ${t.name||"anonymous"}() { /* ... */ }`;return e.push(o),Sn("Function",r)}i(Cf,"handleFunction");function Af(t,e,n,r,o,s,a){if(a.has(t))return kf(t,e,o);if(a.add(t),r){let l=vf(t,e,n,o,s,a);if(l!==void 0)return l}return Array.isArray(t)?yf(t,n,r,o,s,a):n>o.maxDepth?Sn("MaxDepthLimitReached"):t instanceof Error&&o.shouldHandleErrors?Ur(t):xf(t,n,r,o,s,a)}i(Af,"handleObject");function xf(t,e,n,r,o,s){let a=Object.entries(t);return r.shouldSortKeys&&a.sort(([l],[c])=>l.localeCompare(c)),Object.fromEntries(a.map(([l,c])=>[l,ni(c,l,e+1,n,r,o,s)]))}i(xf,"handlePlainObject");function Ts(t){return`{ "[[${t}]]": null }`}i(Ts,"makeObjectTokenSubstitution");function Sn(t,e){return`[[${t}${e?String(e):""}]]`}i(Sn,"makePlaceholder");function ni(t,e,n,r,o,s,a){return t===void 0?n===0||o.shouldHandleUndefined?Sn("Undefined"):void 0:typeof t=="function"?Cf(t,s,o):typeof t!="object"||t===null?t:Af(t,e,n,r,o,s,a)}i(ni,"toPlainObject");function vf(t,e,n,r,o,s){let a=t.toJSON;if(typeof a=="function")try{let l=a.call(t,e);return ni(l,e,n,!1,r,o,s)}catch(l){if(r.shouldCatchToJSONErrors)return Sn("ToJSONFailed");throw l}}i(vf,"tryHandleToJSON");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function Is(t,e){e??=Pe(1);try{await t()}catch(n){let r=new rt(zr,e,n);if(Ef(r))return;Vr(r)}}i(Is,"addErrorHandler");function Pn(t,e){return e??=Pe(1),(...n)=>{Ge(e);let r=Pe(1);e=`${e} + at --- convertAsyncToSync --- (0) +${r}`,te(()=>t(...n),e)}}i(Pn,"convertAsyncToSync");function Ef(t){let e=t;for(;!(e instanceof mn);){if(!(e instanceof Error))return!1;e=e.cause}return Y("Async:handleSilentError")(t),!0}i(Ef,"handleSilentError");function te(t,e){e??=Pe(1),Is(t,e)}i(te,"invokeAsyncSafely");function zc(t,e=0,n,r){r??=Se(),r.throwIfAborted(),n??=Pe(1),te(async()=>{await Ls(e,r,!0),await t(r)},n)}i(zc,"invokeAsyncSafelyAfterDelay");var Sf=new WeakSet;async function ri(){return new Promise(t=>{requestAnimationFrame(()=>{t()})})}i(ri,"requestAnimationFrameAsync");async function Vc(t){let e=Y("Async:retryWithTimeout"),n=t.stackTrace??Pe(1),o={...{retryDelayInMilliseconds:100,shouldRetryOnError:!1,timeoutInMilliseconds:5e3},...t.retryOptions};o.abortSignal?.throwIfAborted(),await Ms({context:{operationName:t.operationName??"",retryFn:t.operationFn},onTimeout:t.onTimeout,async operationFn(s){let a=nt(o.abortSignal,s);a.throwIfAborted();let l=0;for(;!a.aborted;){l++;let c;try{c=await t.operationFn(a)}catch(u){if(a.aborted||!o.shouldRetryOnError||Sf.has(u))throw new rt("retryWithTimeout failed",n,u);Wt(u),c=!1}if(c){mt(e,n,`Retry completed successfully after ${String(l)} attempts`,{operationFn:t.operationFn,operationName:t.operationName??""});return}mt(e,n,`Retry attempt ${String(l)} completed unsuccessfully. Trying again in ${String(o.retryDelayInMilliseconds)} milliseconds`,{operationFn:t.operationFn,operationName:t.operationName??""}),await Ls(o.retryDelayInMilliseconds,s)}},operationName:t.operationName??"",stackTrace:n,timeoutInMilliseconds:o.timeoutInMilliseconds})}i(Vc,"retryWithTimeout");async function Ms(t){let e=t.stackTrace??Pe(1),n=performance.now(),r=new AbortController,o=new AbortController,s=null,a=!1,l=!1,c=Y("Async:runWithTimeout"),u=t.onTimeout??h;if(await Promise.race([d(),p()]),a)return s;throw new rt("Run with timeout failed",e,r.signal.reason);async function d(){try{s=await t.operationFn(r.signal);let f=Math.trunc(performance.now()-n);mt(c,e,`Execution time: ${String(f)} milliseconds`,{context:t.context,operationFn:t.operationFn,operationName:t.operationName??""}),a=!0}catch(f){r.abort(f)}finally{l=!0,o.abort(new Error("Completed"))}}async function p(){if(await Ls(t.timeoutInMilliseconds,o.signal),l)return;let f=Math.trunc(performance.now()-n);mt(c,e,`Timed out after ${String(f)} milliseconds`,{context:t.context,operationFn:t.operationFn,operationName:t.operationName??""});let b={duration:f,onOperationCompleted(k){o.signal.addEventListener("abort",k)},operationName:t.operationName??"",terminateOperation(){let k=new Error(`Timed out after ${String(f)} milliseconds`);r.abort(k),o.abort(k)}};u(b),await hs(o.signal)}function h(f){f.terminateOperation()}}i(Ms,"runWithTimeout");async function Ls(t,e,n){await hs(nt(e,rc(t))),n&&e?.throwIfAborted()}i(Ls,"sleep");var jc=hn(Wc(),1);i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var M=(t=>(t.AlertModal="alert-modal",t.CancelButton="cancel-button",t.CheckboxComponent="checkbox-component",t.CodeHighlighterComponent="code-highlighter-component",t.ConfirmModal="confirm-modal",t.DateComponent="date-component",t.DateTimeComponent="datetime-component",t.EmailComponent="email-component",t.FileComponent="file-component",t.IsPlaceholder="is-placeholder",t.LibraryName="obsidian-dev-utils",t.MonthComponent="month-component",t.MultipleDropdownComponent="multiple-dropdown-component",t.MultipleEmailComponent="multiple-email-component",t.MultipleFileComponent="multiple-file-component",t.MultipleTextComponent="multiple-text-component",t.NumberComponent="number-component",t.OkButton="ok-button",t.OverlayValidator="overlay-validator",t.PasswordComponent="password-component",t.PluginSettingsTab="plugin-settings-tab",t.PromptModal="prompt-modal",t.SelectItemModal="select-item-modal",t.SettingComponentWrapper="setting-component-wrapper",t.TelephoneComponent="telephone-component",t.TextBox="text-box",t.TimeComponent="time-component",t.Tooltip="tooltip",t.TooltipArrow="tooltip-arrow",t.TooltipValidator="tooltip-validator",t.TriStateCheckboxComponent="tri-state-checkbox-component",t.TypedDropdownComponent="typed-dropdown-component",t.TypedMultipleDropdownComponent="typed-multiple-dropdown-component",t.UrlComponent="url-component",t.WeekComponent="week-component",t))(M||{});i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Hc=`${Xr}-styles`;function q(t,...e){t.addClass(M.LibraryName,Zr(),...e)}i(q,"addPluginCssClasses");function Kc(t){let e=t;e.DEBUG=Oc()}i(Kc,"initDebugController");function qc(t,e){Lc(e),Rc(e);let n=Te(t,"lastLibraryVersion","0.0.0");(0,jc.compareVersions)(vs,n.value)<=0||(n.value=vs,document.head.querySelector(`#${Hc}`)?.remove(),document.head.createEl("style",{attr:{id:Hc},text:Ic}))}i(qc,"initPluginContext");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function gt(t){let n={...{abortSignal:Se(),buildNoticeMessage(){throw new Error("buildNoticeMessage is required")},items:[],noticeBeforeShownTimeoutInMilliseconds:500,noticeMinTimeoutInMilliseconds:2e3,processItem:Me,progressBarTitle:"",shouldContinueOnError:!0,shouldShowNotice:!0,shouldShowProgressBar:!0,uiUpdateThresholdInMilliseconds:100},...t},r=Pe(1),o=n.items,s=0,a=null,l=!1;te(()=>p());let c=sleep(n.noticeMinTimeoutInMilliseconds),u=createEl("progress");q(u,"loop"),u.max=o.length;let d=performance.now();for(let h of o){if(n.abortSignal.aborted){a?.hide();return}s++;let f=`# ${String(s)} / ${String(o.length)}`,b=n.buildNoticeMessage(h,f);n.shouldShowProgressBar||a?.setMessage(b),Y("Loop")(b);try{performance.now()-d>n.uiUpdateThresholdInMilliseconds&&(await ri(),d=performance.now()),await n.processItem(h)}catch(k){if(console.error("Error processing item",h),!n.shouldContinueOnError)throw a?.hide(),new rt("loop failed",r,k);Vr(new rt(zr,r,k))}u.value++}a&&await c,a?.hide(),l=!0;async function p(){if(!n.shouldShowNotice||(await sleep(n.noticeBeforeShownTimeoutInMilliseconds),l)||(a=new Gc.Notice("",0),!n.shouldShowProgressBar))return;let h=createFragment();h.createDiv({text:n.progressBarTitle}),h.appendChild(u),a.setMessage(h)}i(p,"showNotice")}i(gt,"loop");var O=i(t=>typeof t=="string","isString"),pr=i(()=>{let t,e,n=new Promise((r,o)=>{t=r,e=o});return n.resolve=t,n.reject=e,n},"defer"),Yc=i(t=>t==null?"":""+t,"makeString"),Pf=i((t,e,n)=>{t.forEach(r=>{e[r]&&(n[r]=e[r])})},"copy"),Tf=/###/g,Jc=i(t=>t&&t.indexOf("###")>-1?t.replace(Tf,"."):t,"cleanKey"),Qc=i(t=>!t||O(t),"canNotTraverseDeeper"),hr=i((t,e,n)=>{let r=O(e)?e.split("."):e,o=0;for(;o{let{obj:r,k:o}=hr(t,e,Object);if(r!==void 0||e.length===1){r[o]=n;return}let s=e[e.length-1],a=e.slice(0,e.length-1),l=hr(t,a,Object);for(;l.obj===void 0&&a.length;)s=`${a[a.length-1]}.${s}`,a=a.slice(0,a.length-1),l=hr(t,a,Object),l?.obj&&typeof l.obj[`${l.k}.${s}`]<"u"&&(l.obj=void 0);l.obj[`${l.k}.${s}`]=n},"setPath"),Ff=i((t,e,n,r)=>{let{obj:o,k:s}=hr(t,e,Object);o[s]=o[s]||[],o[s].push(n)},"pushPath"),si=i((t,e)=>{let{obj:n,k:r}=hr(t,e);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},"getPath"),If=i((t,e,n)=>{let r=si(t,n);return r!==void 0?r:si(e,n)},"getPathWithDefaults"),ou=i((t,e,n)=>{for(let r in e)r!=="__proto__"&&r!=="constructor"&&(r in t?O(t[r])||t[r]instanceof String||O(e[r])||e[r]instanceof String?n&&(t[r]=e[r]):ou(t[r],e[r],n):t[r]=e[r]);return t},"deepExtend"),qt=i(t=>t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),"regexEscape"),Mf={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"},Lf=i(t=>O(t)?t.replace(/[&<>"'\/]/g,e=>Mf[e]):t,"escape"),Ds=class{static{i(this,"RegExpCache")}constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){let n=this.regExpMap.get(e);if(n!==void 0)return n;let r=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,r),this.regExpQueue.push(e),r}},Nf=[" ",",","?","!",";"],Of=new Ds(20),Rf=i((t,e,n)=>{e=e||"",n=n||"";let r=Nf.filter(a=>e.indexOf(a)<0&&n.indexOf(a)<0);if(r.length===0)return!0;let o=Of.getRegExp(`(${r.map(a=>a==="?"?"\\?":a).join("|")})`),s=!o.test(t);if(!s){let a=t.indexOf(n);a>0&&!o.test(t.substring(0,a))&&(s=!0)}return s},"looksLikeObjectPath"),Bs=i((t,e,n=".")=>{if(!t)return;if(t[e])return Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0;let r=e.split(n),o=t;for(let s=0;s-1&&ct?.replace(/_/g,"-"),"getCleanedCode"),Df={type:"logger",log(t){this.output("log",t)},warn(t){this.output("warn",t)},error(t){this.output("error",t)},output(t,e){console?.[t]?.apply?.(console,e)}},_s=class t{static{i(this,"Logger")}constructor(e,n={}){this.init(e,n)}init(e,n={}){this.prefix=n.prefix||"i18next:",this.logger=e||Df,this.options=n,this.debug=n.debug}log(...e){return this.forward(e,"log","",!0)}warn(...e){return this.forward(e,"warn","",!0)}error(...e){return this.forward(e,"error","")}deprecate(...e){return this.forward(e,"warn","WARNING DEPRECATED: ",!0)}forward(e,n,r,o){return o&&!this.debug?null:(O(e[0])&&(e[0]=`${r}${this.prefix} ${e[0]}`),this.logger[n](e))}create(e){return new t(this.logger,{prefix:`${this.prefix}:${e}:`,...this.options})}clone(e){return e=e||this.options,e.prefix=e.prefix||this.prefix,new t(this.logger,e)}},bt=new _s,Tn=class{static{i(this,"EventEmitter")}constructor(){this.observers={}}on(e,n){return e.split(" ").forEach(r=>{this.observers[r]||(this.observers[r]=new Map);let o=this.observers[r].get(n)||0;this.observers[r].set(n,o+1)}),this}off(e,n){if(this.observers[e]){if(!n){delete this.observers[e];return}this.observers[e].delete(n)}}emit(e,...n){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([o,s])=>{for(let a=0;a{for(let a=0;a-1&&this.options.ns.splice(n,1)}getResource(e,n,r,o={}){let s=o.keySeparator!==void 0?o.keySeparator:this.options.keySeparator,a=o.ignoreJSONStructure!==void 0?o.ignoreJSONStructure:this.options.ignoreJSONStructure,l;e.indexOf(".")>-1?l=e.split("."):(l=[e,n],r&&(Array.isArray(r)?l.push(...r):O(r)&&s?l.push(...r.split(s)):l.push(r)));let c=si(this.data,l);return!c&&!n&&!r&&e.indexOf(".")>-1&&(e=l[0],n=l[1],r=l.slice(2).join(".")),c||!a||!O(r)?c:Bs(this.data?.[e]?.[n],r,s)}addResource(e,n,r,o,s={silent:!1}){let a=s.keySeparator!==void 0?s.keySeparator:this.options.keySeparator,l=[e,n];r&&(l=l.concat(a?r.split(a):r)),e.indexOf(".")>-1&&(l=e.split("."),o=n,n=l[1]),this.addNamespaces(n),Xc(this.data,l,o),s.silent||this.emit("added",e,n,r,o)}addResources(e,n,r,o={silent:!1}){for(let s in r)(O(r[s])||Array.isArray(r[s]))&&this.addResource(e,n,s,r[s],{silent:!0});o.silent||this.emit("added",e,n,r)}addResourceBundle(e,n,r,o,s,a={silent:!1,skipCopy:!1}){let l=[e,n];e.indexOf(".")>-1&&(l=e.split("."),o=r,r=n,n=l[1]),this.addNamespaces(n);let c=si(this.data,l)||{};a.skipCopy||(r=JSON.parse(JSON.stringify(r))),o?ou(c,r,s):c={...c,...r},Xc(this.data,l,c),a.silent||this.emit("added",e,n,r)}removeResourceBundle(e,n){this.hasResourceBundle(e,n)&&delete this.data[e][n],this.removeNamespaces(n),this.emit("removed",e,n)}hasResourceBundle(e,n){return this.getResource(e,n)!==void 0}getResourceBundle(e,n){return n||(n=this.options.defaultNS),this.getResource(e,n)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){let n=this.getDataByLanguage(e);return!!(n&&Object.keys(n)||[]).find(o=>n[o]&&Object.keys(n[o]).length>0)}toJSON(){return this.data}},su={processors:{},addPostProcessor(t){this.processors[t.name]=t},handle(t,e,n,r,o){return t.forEach(s=>{e=this.processors[s]?.process(e,n,r,o)??e}),e}},au=Symbol("i18next/PATH_KEY");function Bf(){let t=[],e=Object.create(null),n;return e.get=(r,o)=>(n?.revoke?.(),o===au?t:(t.push(o),n=Proxy.revocable(r,e),n.proxy)),Proxy.revocable(Object.create(null),e).proxy}i(Bf,"createProxy");function $s(t,e){let{[au]:n}=t(Bf());return n.join(e?.keySeparator??".")}i($s,"keysFromSelector");var Zc={},Ns=i(t=>!O(t)&&typeof t!="boolean"&&typeof t!="number","shouldHandleAsObject"),li=class t extends Tn{static{i(this,"Translator")}constructor(e,n={}){super(),Pf(["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],e,this),this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.logger=bt.create("translator")}changeLanguage(e){e&&(this.language=e)}exists(e,n={interpolation:{}}){let r={...n};if(e==null)return!1;let o=this.resolve(e,r);if(o?.res===void 0)return!1;let s=Ns(o.res);return!(r.returnObjects===!1&&s)}extractFromKey(e,n){let r=n.nsSeparator!==void 0?n.nsSeparator:this.options.nsSeparator;r===void 0&&(r=":");let o=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator,s=n.ns||this.options.defaultNS||[],a=r&&e.indexOf(r)>-1,l=!this.options.userDefinedKeySeparator&&!n.keySeparator&&!this.options.userDefinedNsSeparator&&!n.nsSeparator&&!Rf(e,r,o);if(a&&!l){let c=e.match(this.interpolator.nestingRegexp);if(c&&c.length>0)return{key:e,namespaces:O(s)?[s]:s};let u=e.split(r);(r!==o||r===o&&this.options.ns.indexOf(u[0])>-1)&&(s=u.shift()),e=u.join(o)}return{key:e,namespaces:O(s)?[s]:s}}translate(e,n,r){let o=typeof n=="object"?{...n}:n;if(typeof o!="object"&&this.options.overloadTranslationOptionHandler&&(o=this.options.overloadTranslationOptionHandler(arguments)),typeof o=="object"&&(o={...o}),o||(o={}),e==null)return"";typeof e=="function"&&(e=$s(e,{...this.options,...o})),Array.isArray(e)||(e=[String(e)]);let s=o.returnDetails!==void 0?o.returnDetails:this.options.returnDetails,a=o.keySeparator!==void 0?o.keySeparator:this.options.keySeparator,{key:l,namespaces:c}=this.extractFromKey(e[e.length-1],o),u=c[c.length-1],d=o.nsSeparator!==void 0?o.nsSeparator:this.options.nsSeparator;d===void 0&&(d=":");let p=o.lng||this.language,h=o.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(p?.toLowerCase()==="cimode")return h?s?{res:`${u}${d}${l}`,usedKey:l,exactUsedKey:l,usedLng:p,usedNS:u,usedParams:this.getUsedParamsDetails(o)}:`${u}${d}${l}`:s?{res:l,usedKey:l,exactUsedKey:l,usedLng:p,usedNS:u,usedParams:this.getUsedParamsDetails(o)}:l;let f=this.resolve(e,o),b=f?.res,k=f?.usedKey||l,y=f?.exactUsedKey||l,w=["[object Number]","[object Function]","[object RegExp]"],A=o.joinArrays!==void 0?o.joinArrays:this.options.joinArrays,v=!this.i18nFormat||this.i18nFormat.handleAsObject,P=o.count!==void 0&&!O(o.count),I=t.hasDefaultValue(o),C=P?this.pluralResolver.getSuffix(p,o.count,o):"",$=o.ordinal&&P?this.pluralResolver.getSuffix(p,o.count,{ordinal:!1}):"",H=P&&!o.ordinal&&o.count===0,R=H&&o[`defaultValue${this.options.pluralSeparator}zero`]||o[`defaultValue${C}`]||o[`defaultValue${$}`]||o.defaultValue,V=b;v&&!b&&I&&(V=R);let de=Ns(V),W=Object.prototype.toString.apply(V);if(v&&V&&de&&w.indexOf(W)<0&&!(O(A)&&Array.isArray(V))){if(!o.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn("accessing an object - but returnObjects options is not enabled!");let T=this.options.returnedObjectHandler?this.options.returnedObjectHandler(k,V,{...o,ns:c}):`key '${l} (${this.language})' returned an object instead of string.`;return s?(f.res=T,f.usedParams=this.getUsedParamsDetails(o),f):T}if(a){let T=Array.isArray(V),L=T?[]:{},N=T?y:k;for(let z in V)if(Object.prototype.hasOwnProperty.call(V,z)){let j=`${N}${a}${z}`;I&&!b?L[z]=this.translate(j,{...o,defaultValue:Ns(R)?R[z]:void 0,joinArrays:!1,ns:c}):L[z]=this.translate(j,{...o,joinArrays:!1,ns:c}),L[z]===j&&(L[z]=V[z])}b=L}}else if(v&&O(A)&&Array.isArray(b))b=b.join(A),b&&(b=this.extendTranslation(b,e,o,r));else{let T=!1,L=!1;!this.isValidLookup(b)&&I&&(T=!0,b=R),this.isValidLookup(b)||(L=!0,b=l);let z=(o.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&L?void 0:b,j=I&&R!==b&&this.options.updateMissing;if(L||T||j){if(this.logger.log(j?"updateKey":"missingKey",p,u,l,j?R:b),a){let Q=this.resolve(l,{...o,keySeparator:!1});Q&&Q.res&&this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.")}let pe=[],ve=this.languageUtils.getFallbackCodes(this.options.fallbackLng,o.lng||this.language);if(this.options.saveMissingTo==="fallback"&&ve&&ve[0])for(let Q=0;Q{let be=I&&g!==b?g:z;this.options.missingKeyHandler?this.options.missingKeyHandler(Q,u,he,be,j,o):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(Q,u,he,be,j,o),this.emit("missingKey",Q,u,he,b)},"send");this.options.saveMissing&&(this.options.saveMissingPlurals&&P?pe.forEach(Q=>{let he=this.pluralResolver.getSuffixes(Q,o);H&&o[`defaultValue${this.options.pluralSeparator}zero`]&&he.indexOf(`${this.options.pluralSeparator}zero`)<0&&he.push(`${this.options.pluralSeparator}zero`),he.forEach(g=>{m([Q],l+g,o[`defaultValue${g}`]||R)})}):m(pe,l,R))}b=this.extendTranslation(b,e,o,f,r),L&&b===l&&this.options.appendNamespaceToMissingKey&&(b=`${u}${d}${l}`),(L||T)&&this.options.parseMissingKeyHandler&&(b=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${u}${d}${l}`:l,T?b:void 0,o))}return s?(f.res=b,f.usedParams=this.getUsedParamsDetails(o),f):b}extendTranslation(e,n,r,o,s){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...r},r.lng||this.language||o.usedLng,o.usedNS,o.usedKey,{resolved:o});else if(!r.skipInterpolation){r.interpolation&&this.interpolator.init({...r,interpolation:{...this.options.interpolation,...r.interpolation}});let c=O(e)&&(r?.interpolation?.skipOnVariables!==void 0?r.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables),u;if(c){let p=e.match(this.interpolator.nestingRegexp);u=p&&p.length}let d=r.replace&&!O(r.replace)?r.replace:r;if(this.options.interpolation.defaultVariables&&(d={...this.options.interpolation.defaultVariables,...d}),e=this.interpolator.interpolate(e,d,r.lng||this.language||o.usedLng,r),c){let p=e.match(this.interpolator.nestingRegexp),h=p&&p.length;us?.[0]===p[0]&&!r.context?(this.logger.warn(`It seems you are nesting recursively key: ${p[0]} in key: ${n[0]}`),null):this.translate(...p,n),r)),r.interpolation&&this.interpolator.reset()}let a=r.postProcess||this.options.postProcess,l=O(a)?[a]:a;return e!=null&&l?.length&&r.applyPostProcessor!==!1&&(e=su.handle(l,e,n,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...o,usedParams:this.getUsedParamsDetails(r)},...r}:r,this)),e}resolve(e,n={}){let r,o,s,a,l;return O(e)&&(e=[e]),e.forEach(c=>{if(this.isValidLookup(r))return;let u=this.extractFromKey(c,n),d=u.key;o=d;let p=u.namespaces;this.options.fallbackNS&&(p=p.concat(this.options.fallbackNS));let h=n.count!==void 0&&!O(n.count),f=h&&!n.ordinal&&n.count===0,b=n.context!==void 0&&(O(n.context)||typeof n.context=="number")&&n.context!=="",k=n.lngs?n.lngs:this.languageUtils.toResolveHierarchy(n.lng||this.language,n.fallbackLng);p.forEach(y=>{this.isValidLookup(r)||(l=y,!Zc[`${k[0]}-${y}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(l)&&(Zc[`${k[0]}-${y}`]=!0,this.logger.warn(`key "${o}" for languages "${k.join(", ")}" won't get resolved as namespace "${l}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!")),k.forEach(w=>{if(this.isValidLookup(r))return;a=w;let A=[d];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(A,d,w,y,n);else{let P;h&&(P=this.pluralResolver.getSuffix(w,n.count,n));let I=`${this.options.pluralSeparator}zero`,C=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(h&&(n.ordinal&&P.indexOf(C)===0&&A.push(d+P.replace(C,this.options.pluralSeparator)),A.push(d+P),f&&A.push(d+I)),b){let $=`${d}${this.options.contextSeparator||"_"}${n.context}`;A.push($),h&&(n.ordinal&&P.indexOf(C)===0&&A.push($+P.replace(C,this.options.pluralSeparator)),A.push($+P),f&&A.push($+I))}}let v;for(;v=A.pop();)this.isValidLookup(r)||(s=v,r=this.getResource(w,y,v,n))}))})}),{res:r,usedKey:o,exactUsedKey:s,usedLng:a,usedNS:l}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e==="")}getResource(e,n,r,o={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,n,r,o):this.resourceStore.getResource(e,n,r,o)}getUsedParamsDetails(e={}){let n=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],r=e.replace&&!O(e.replace),o=r?e.replace:e;if(r&&typeof e.count<"u"&&(o.count=e.count),this.options.interpolation.defaultVariables&&(o={...this.options.interpolation.defaultVariables,...o}),!r){o={...o};for(let s of n)delete o[s]}return o}static hasDefaultValue(e){let n="defaultValue";for(let r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&n===r.substring(0,n.length)&&e[r]!==void 0)return!0;return!1}},ci=class{static{i(this,"LanguageUtil")}constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=bt.create("languageUtils")}getScriptPartFromCode(e){if(e=fr(e),!e||e.indexOf("-")<0)return null;let n=e.split("-");return n.length===2||(n.pop(),n[n.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(n.join("-"))}getLanguagePartFromCode(e){if(e=fr(e),!e||e.indexOf("-")<0)return e;let n=e.split("-");return this.formatLanguageCode(n[0])}formatLanguageCode(e){if(O(e)&&e.indexOf("-")>-1){let n;try{n=Intl.getCanonicalLocales(e)[0]}catch{}return n&&this.options.lowerCaseLng&&(n=n.toLowerCase()),n||(this.options.lowerCaseLng?e.toLowerCase():e)}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load==="languageOnly"||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}getBestMatchFromCodes(e){if(!e)return null;let n;return e.forEach(r=>{if(n)return;let o=this.formatLanguageCode(r);(!this.options.supportedLngs||this.isSupportedCode(o))&&(n=o)}),!n&&this.options.supportedLngs&&e.forEach(r=>{if(n)return;let o=this.getScriptPartFromCode(r);if(this.isSupportedCode(o))return n=o;let s=this.getLanguagePartFromCode(r);if(this.isSupportedCode(s))return n=s;n=this.options.supportedLngs.find(a=>{if(a===s)return a;if(!(a.indexOf("-")<0&&s.indexOf("-")<0)&&(a.indexOf("-")>0&&s.indexOf("-")<0&&a.substring(0,a.indexOf("-"))===s||a.indexOf(s)===0&&s.length>1))return a})}),n||(n=this.getFallbackCodes(this.options.fallbackLng)[0]),n}getFallbackCodes(e,n){if(!e)return[];if(typeof e=="function"&&(e=e(n)),O(e)&&(e=[e]),Array.isArray(e))return e;if(!n)return e.default||[];let r=e[n];return r||(r=e[this.getScriptPartFromCode(n)]),r||(r=e[this.formatLanguageCode(n)]),r||(r=e[this.getLanguagePartFromCode(n)]),r||(r=e.default),r||[]}toResolveHierarchy(e,n){let r=this.getFallbackCodes((n===!1?[]:n)||this.options.fallbackLng||[],e),o=[],s=i(a=>{a&&(this.isSupportedCode(a)?o.push(a):this.logger.warn(`rejecting language code not found in supportedLngs: ${a}`))},"addCode");return O(e)&&(e.indexOf("-")>-1||e.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&s(this.formatLanguageCode(e)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&s(this.getScriptPartFromCode(e)),this.options.load!=="currentOnly"&&s(this.getLanguagePartFromCode(e))):O(e)&&s(this.formatLanguageCode(e)),r.forEach(a=>{o.indexOf(a)<0&&s(this.formatLanguageCode(a))}),o}},eu={zero:0,one:1,two:2,few:3,many:4,other:5},tu={select:i(t=>t===1?"one":"other","select"),resolvedOptions:i(()=>({pluralCategories:["one","other"]}),"resolvedOptions")},zs=class{static{i(this,"PluralResolver")}constructor(e,n={}){this.languageUtils=e,this.options=n,this.logger=bt.create("pluralResolver"),this.pluralRulesCache={}}clearCache(){this.pluralRulesCache={}}getRule(e,n={}){let r=fr(e==="dev"?"en":e),o=n.ordinal?"ordinal":"cardinal",s=JSON.stringify({cleanedCode:r,type:o});if(s in this.pluralRulesCache)return this.pluralRulesCache[s];let a;try{a=new Intl.PluralRules(r,{type:o})}catch{if(typeof Intl>"u")return this.logger.error("No Intl support, please use an Intl polyfill!"),tu;if(!e.match(/-|_/))return tu;let c=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(c,n)}return this.pluralRulesCache[s]=a,a}needsPlural(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,n,r={}){return this.getSuffixes(e,r).map(o=>`${n}${o}`)}getSuffixes(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?r.resolvedOptions().pluralCategories.sort((o,s)=>eu[o]-eu[s]).map(o=>`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${o}`):[]}getSuffix(e,n,r={}){let o=this.getRule(e,r);return o?`${this.options.prepend}${r.ordinal?`ordinal${this.options.prepend}`:""}${o.select(n)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix("dev",n,r))}},nu=i((t,e,n,r=".",o=!0)=>{let s=If(t,e,n);return!s&&o&&O(n)&&(s=Bs(t,n,r),s===void 0&&(s=Bs(e,n,r))),s},"deepFindWithDefaults"),Os=i(t=>t.replace(/\$/g,"$$$$"),"regexSafe"),ui=class{static{i(this,"Interpolator")}constructor(e={}){this.logger=bt.create("interpolator"),this.options=e,this.format=e?.interpolation?.format||(n=>n),this.init(e)}init(e={}){e.interpolation||(e.interpolation={escapeValue:!0});let{escape:n,escapeValue:r,useRawValueToEscape:o,prefix:s,prefixEscaped:a,suffix:l,suffixEscaped:c,formatSeparator:u,unescapeSuffix:d,unescapePrefix:p,nestingPrefix:h,nestingPrefixEscaped:f,nestingSuffix:b,nestingSuffixEscaped:k,nestingOptionsSeparator:y,maxReplaces:w,alwaysFormat:A}=e.interpolation;this.escape=n!==void 0?n:Lf,this.escapeValue=r!==void 0?r:!0,this.useRawValueToEscape=o!==void 0?o:!1,this.prefix=s?qt(s):a||"{{",this.suffix=l?qt(l):c||"}}",this.formatSeparator=u||",",this.unescapePrefix=d?"":p||"-",this.unescapeSuffix=this.unescapePrefix?"":d||"",this.nestingPrefix=h?qt(h):f||qt("$t("),this.nestingSuffix=b?qt(b):k||qt(")"),this.nestingOptionsSeparator=y||",",this.maxReplaces=w||1e3,this.alwaysFormat=A!==void 0?A:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){let e=i((n,r)=>n?.source===r?(n.lastIndex=0,n):new RegExp(r,"g"),"getOrResetRegExp");this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`)}interpolate(e,n,r,o){let s,a,l,c=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},u=i(f=>{if(f.indexOf(this.formatSeparator)<0){let w=nu(n,c,f,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(w,void 0,r,{...o,...n,interpolationkey:f}):w}let b=f.split(this.formatSeparator),k=b.shift().trim(),y=b.join(this.formatSeparator).trim();return this.format(nu(n,c,k,this.options.keySeparator,this.options.ignoreJSONStructure),y,r,{...o,...n,interpolationkey:k})},"handleFormat");this.resetRegExp();let d=o?.missingInterpolationHandler||this.options.missingInterpolationHandler,p=o?.interpolation?.skipOnVariables!==void 0?o.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:i(f=>Os(f),"safeValue")},{regex:this.regexp,safeValue:i(f=>this.escapeValue?Os(this.escape(f)):Os(f),"safeValue")}].forEach(f=>{for(l=0;s=f.regex.exec(e);){let b=s[1].trim();if(a=u(b),a===void 0)if(typeof d=="function"){let y=d(e,s,o);a=O(y)?y:""}else if(o&&Object.prototype.hasOwnProperty.call(o,b))a="";else if(p){a=s[0];continue}else this.logger.warn(`missed to pass in variable ${b} for interpolating ${e}`),a="";else!O(a)&&!this.useRawValueToEscape&&(a=Yc(a));let k=f.safeValue(a);if(e=e.replace(s[0],k),p?(f.regex.lastIndex+=a.length,f.regex.lastIndex-=s[0].length):f.regex.lastIndex=0,l++,l>=this.maxReplaces)break}}),e}nest(e,n,r={}){let o,s,a,l=i((c,u)=>{let d=this.nestingOptionsSeparator;if(c.indexOf(d)<0)return c;let p=c.split(new RegExp(`${qt(d)}[ ]*{`)),h=`{${p[1]}`;c=p[0],h=this.interpolate(h,a);let f=h.match(/'/g),b=h.match(/"/g);((f?.length??0)%2===0&&!b||(b?.length??0)%2!==0)&&(h=h.replace(/'/g,'"'));try{a=JSON.parse(h),u&&(a={...u,...a})}catch(k){return this.logger.warn(`failed parsing options string in nesting for key ${c}`,k),`${c}${d}${h}`}return a.defaultValue&&a.defaultValue.indexOf(this.prefix)>-1&&delete a.defaultValue,c},"handleHasOptions");for(;o=this.nestingRegexp.exec(e);){let c=[];a={...r},a=a.replace&&!O(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let u=/{.*}/.test(o[1])?o[1].lastIndexOf("}")+1:o[1].indexOf(this.formatSeparator);if(u!==-1&&(c=o[1].slice(u).split(this.formatSeparator).map(d=>d.trim()).filter(Boolean),o[1]=o[1].slice(0,u)),s=n(l.call(this,o[1].trim(),a),a),s&&o[0]===e&&!O(s))return s;O(s)||(s=Yc(s)),s||(this.logger.warn(`missed to resolve ${o[1]} for nesting ${e}`),s=""),c.length&&(s=c.reduce((d,p)=>this.format(d,p,r.lng,{...r,interpolationkey:o[1].trim()}),s.trim())),e=e.replace(o[0],s),this.regexp.lastIndex=0}return e}},_f=i(t=>{let e=t.toLowerCase().trim(),n={};if(t.indexOf("(")>-1){let r=t.split("(");e=r[0].toLowerCase().trim();let o=r[1].substring(0,r[1].length-1);e==="currency"&&o.indexOf(":")<0?n.currency||(n.currency=o.trim()):e==="relativetime"&&o.indexOf(":")<0?n.range||(n.range=o.trim()):o.split(";").forEach(a=>{if(a){let[l,...c]=a.split(":"),u=c.join(":").trim().replace(/^'+|'+$/g,""),d=l.trim();n[d]||(n[d]=u),u==="false"&&(n[d]=!1),u==="true"&&(n[d]=!0),isNaN(u)||(n[d]=parseInt(u,10))}})}return{formatName:e,formatOptions:n}},"parseFormatStr"),ru=i(t=>{let e={};return(n,r,o)=>{let s=o;o&&o.interpolationkey&&o.formatParams&&o.formatParams[o.interpolationkey]&&o[o.interpolationkey]&&(s={...s,[o.interpolationkey]:void 0});let a=r+JSON.stringify(s),l=e[a];return l||(l=t(fr(r),o),e[a]=l),l(n)}},"createCachedFormatter"),$f=i(t=>(e,n,r)=>t(fr(n),r)(e),"createNonCachedFormatter"),Vs=class{static{i(this,"Formatter")}constructor(e={}){this.logger=bt.create("formatter"),this.options=e,this.init(e)}init(e,n={interpolation:{}}){this.formatSeparator=n.interpolation.formatSeparator||",";let r=n.cacheInBuiltFormats?ru:$f;this.formats={number:r((o,s)=>{let a=new Intl.NumberFormat(o,{...s});return l=>a.format(l)}),currency:r((o,s)=>{let a=new Intl.NumberFormat(o,{...s,style:"currency"});return l=>a.format(l)}),datetime:r((o,s)=>{let a=new Intl.DateTimeFormat(o,{...s});return l=>a.format(l)}),relativetime:r((o,s)=>{let a=new Intl.RelativeTimeFormat(o,{...s});return l=>a.format(l,s.range||"day")}),list:r((o,s)=>{let a=new Intl.ListFormat(o,{...s});return l=>a.format(l)})}}add(e,n){this.formats[e.toLowerCase().trim()]=n}addCached(e,n){this.formats[e.toLowerCase().trim()]=ru(n)}format(e,n,r,o={}){let s=n.split(this.formatSeparator);if(s.length>1&&s[0].indexOf("(")>1&&s[0].indexOf(")")<0&&s.find(l=>l.indexOf(")")>-1)){let l=s.findIndex(c=>c.indexOf(")")>-1);s[0]=[s[0],...s.splice(1,l)].join(this.formatSeparator)}return s.reduce((l,c)=>{let{formatName:u,formatOptions:d}=_f(c);if(this.formats[u]){let p=l;try{let h=o?.formatParams?.[o.interpolationkey]||{},f=h.locale||h.lng||o.locale||o.lng||r;p=this.formats[u](l,f,{...d,...o,...h})}catch(h){this.logger.warn(h)}return p}else this.logger.warn(`there was no format function for ${u}`);return l},e)}},zf=i((t,e)=>{t.pending[e]!==void 0&&(delete t.pending[e],t.pendingCount--)},"removePending"),Us=class extends Tn{static{i(this,"Connector")}constructor(e,n,r,o={}){super(),this.backend=e,this.store=n,this.services=r,this.languageUtils=r.languageUtils,this.options=o,this.logger=bt.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=o.maxParallelReads||10,this.readingCalls=0,this.maxRetries=o.maxRetries>=0?o.maxRetries:5,this.retryTimeout=o.retryTimeout>=1?o.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(r,o.backend,o)}queueLoad(e,n,r,o){let s={},a={},l={},c={};return e.forEach(u=>{let d=!0;n.forEach(p=>{let h=`${u}|${p}`;!r.reload&&this.store.hasResourceBundle(u,p)?this.state[h]=2:this.state[h]<0||(this.state[h]===1?a[h]===void 0&&(a[h]=!0):(this.state[h]=1,d=!1,a[h]===void 0&&(a[h]=!0),s[h]===void 0&&(s[h]=!0),c[p]===void 0&&(c[p]=!0)))}),d||(l[u]=!0)}),(Object.keys(s).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:o}),{toLoad:Object.keys(s),pending:Object.keys(a),toLoadLanguages:Object.keys(l),toLoadNamespaces:Object.keys(c)}}loaded(e,n,r){let o=e.split("|"),s=o[0],a=o[1];n&&this.emit("failedLoading",s,a,n),!n&&r&&this.store.addResourceBundle(s,a,r,void 0,void 0,{skipCopy:!0}),this.state[e]=n?-1:2,n&&r&&(this.state[e]=0);let l={};this.queue.forEach(c=>{Ff(c.loaded,[s],a),zf(c,e),n&&c.errors.push(n),c.pendingCount===0&&!c.done&&(Object.keys(c.loaded).forEach(u=>{l[u]||(l[u]={});let d=c.loaded[u];d.length&&d.forEach(p=>{l[u][p]===void 0&&(l[u][p]=!0)})}),c.done=!0,c.errors.length?c.callback(c.errors):c.callback())}),this.emit("loaded",l),this.queue=this.queue.filter(c=>!c.done)}read(e,n,r,o=0,s=this.retryTimeout,a){if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:n,fcName:r,tried:o,wait:s,callback:a});return}this.readingCalls++;let l=i((u,d)=>{if(this.readingCalls--,this.waitingReads.length>0){let p=this.waitingReads.shift();this.read(p.lng,p.ns,p.fcName,p.tried,p.wait,p.callback)}if(u&&d&&o{this.read.call(this,e,n,r,o+1,s*2,a)},s);return}a(u,d)},"resolver"),c=this.backend[r].bind(this.backend);if(c.length===2){try{let u=c(e,n);u&&typeof u.then=="function"?u.then(d=>l(null,d)).catch(l):l(null,u)}catch(u){l(u)}return}return c(e,n,l)}prepareLoading(e,n,r={},o){if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),o&&o();O(e)&&(e=this.languageUtils.toResolveHierarchy(e)),O(n)&&(n=[n]);let s=this.queueLoad(e,n,r,o);if(!s.toLoad.length)return s.pending.length||o(),null;s.toLoad.forEach(a=>{this.loadOne(a)})}load(e,n,r){this.prepareLoading(e,n,{},r)}reload(e,n,r){this.prepareLoading(e,n,{reload:!0},r)}loadOne(e,n=""){let r=e.split("|"),o=r[0],s=r[1];this.read(o,s,"read",void 0,void 0,(a,l)=>{a&&this.logger.warn(`${n}loading namespace ${s} for language ${o} failed`,a),!a&&l&&this.logger.log(`${n}loaded namespace ${s} for language ${o}`,l),this.loaded(e,a,l)})}saveMissing(e,n,r,o,s,a={},l=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(n)){this.logger.warn(`did not save key "${r}" as the namespace "${n}" was not yet loaded`,"This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");return}if(!(r==null||r==="")){if(this.backend?.create){let c={...a,isUpdate:s},u=this.backend.create.bind(this.backend);if(u.length<6)try{let d;u.length===5?d=u(e,n,r,o,c):d=u(e,n,r,o),d&&typeof d.then=="function"?d.then(p=>l(null,p)).catch(l):l(null,d)}catch(d){l(d)}else u(e,n,r,o,l,c)}!e||!e[0]||this.store.addResource(e[0],n,r,o)}}},Rs=i(()=>({debug:!1,initAsync:!0,ns:["translation"],defaultNS:["translation"],fallbackLng:["dev"],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:"all",preload:!1,simplifyPluralSuffix:!0,keySeparator:".",nsSeparator:":",pluralSeparator:"_",contextSeparator:"_",partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:"fallback",saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:i(t=>{let e={};if(typeof t[1]=="object"&&(e=t[1]),O(t[1])&&(e.defaultValue=t[1]),O(t[2])&&(e.tDescription=t[2]),typeof t[2]=="object"||typeof t[3]=="object"){let n=t[3]||t[2];Object.keys(n).forEach(r=>{e[r]=n[r]})}return e},"overloadTranslationOptionHandler"),interpolation:{escapeValue:!0,format:i(t=>t,"format"),prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),"get"),iu=i(t=>(O(t.ns)&&(t.ns=[t.ns]),O(t.fallbackLng)&&(t.fallbackLng=[t.fallbackLng]),O(t.fallbackNS)&&(t.fallbackNS=[t.fallbackNS]),t.supportedLngs?.indexOf?.("cimode")<0&&(t.supportedLngs=t.supportedLngs.concat(["cimode"])),typeof t.initImmediate=="boolean"&&(t.initAsync=t.initImmediate),t),"transformOptions"),oi=i(()=>{},"noop"),Vf=i(t=>{Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(n=>{typeof t[n]=="function"&&(t[n]=t[n].bind(t))})},"bindMemberFunctions"),lu="__i18next_supportNoticeShown",Uf=i(()=>typeof globalThis<"u"&&!!globalThis[lu],"getSupportNoticeShown"),Wf=i(()=>{typeof globalThis<"u"&&(globalThis[lu]=!0)},"setSupportNoticeShown"),Hf=i(t=>!!(t?.modules?.backend?.name?.indexOf("Locize")>0||t?.modules?.backend?.constructor?.name?.indexOf("Locize")>0||t?.options?.backend?.backends&&t.options.backend.backends.some(e=>e?.name?.indexOf("Locize")>0||e?.constructor?.name?.indexOf("Locize")>0)||t?.options?.backend?.projectId||t?.options?.backend?.backendOptions&&t.options.backend.backendOptions.some(e=>e?.projectId)),"usesLocize"),Ws=class t extends Tn{static{i(this,"I18n")}constructor(e={},n){if(super(),this.options=iu(e),this.services={},this.logger=bt,this.modules={external:[]},Vf(this),n&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,n),this;setTimeout(()=>{this.init(e,n)},0)}}init(e={},n){this.isInitializing=!0,typeof e=="function"&&(n=e,e={}),e.defaultNS==null&&e.ns&&(O(e.ns)?e.defaultNS=e.ns:e.ns.indexOf("translation")<0&&(e.defaultNS=e.ns[0]));let r=Rs();this.options={...r,...this.options,...iu(e)},this.options.interpolation={...r.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator),typeof this.options.overloadTranslationOptionHandler!="function"&&(this.options.overloadTranslationOptionHandler=r.overloadTranslationOptionHandler),this.options.showSupportNotice!==!1&&!Hf(this)&&!Uf()&&(typeof console<"u"&&typeof console.info<"u"&&console.info("\u{1F310} i18next is maintained with support from Locize \u2014 consider powering your project with managed localization (AI, CDN, integrations): https://locize.com \u{1F499}"),Wf());let o=i(u=>u?typeof u=="function"?new u:u:null,"createClassOnDemand");if(!this.options.isClone){this.modules.logger?bt.init(o(this.modules.logger),this.options):bt.init(null,this.options);let u;this.modules.formatter?u=this.modules.formatter:u=Vs;let d=new ci(this.options);this.store=new ai(this.options.resources,this.options);let p=this.services;p.logger=bt,p.resourceStore=this.store,p.languageUtils=d,p.pluralResolver=new zs(d,{prepend:this.options.pluralSeparator,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),this.options.interpolation.format&&this.options.interpolation.format!==r.interpolation.format&&this.logger.deprecate("init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting"),u&&(!this.options.interpolation.format||this.options.interpolation.format===r.interpolation.format)&&(p.formatter=o(u),p.formatter.init&&p.formatter.init(p,this.options),this.options.interpolation.format=p.formatter.format.bind(p.formatter)),p.interpolator=new ui(this.options),p.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},p.backendConnector=new Us(o(this.modules.backend),p.resourceStore,p,this.options),p.backendConnector.on("*",(f,...b)=>{this.emit(f,...b)}),this.modules.languageDetector&&(p.languageDetector=o(this.modules.languageDetector),p.languageDetector.init&&p.languageDetector.init(p,this.options.detection,this.options)),this.modules.i18nFormat&&(p.i18nFormat=o(this.modules.i18nFormat),p.i18nFormat.init&&p.i18nFormat.init(this)),this.translator=new li(this.services,this.options),this.translator.on("*",(f,...b)=>{this.emit(f,...b)}),this.modules.external.forEach(f=>{f.init&&f.init(this)})}if(this.format=this.options.interpolation.format,n||(n=oi),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){let u=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);u.length>0&&u[0]!=="dev"&&(this.options.lng=u[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn("init: no languageDetector is used and no lng is defined"),["getResource","hasResourceBundle","getResourceBundle","getDataByLanguage"].forEach(u=>{this[u]=(...d)=>this.store[u](...d)}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(u=>{this[u]=(...d)=>(this.store[u](...d),this)});let l=pr(),c=i(()=>{let u=i((d,p)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn("init: i18next is already initialized. You should call init just once!"),this.isInitialized=!0,this.options.isClone||this.logger.log("initialized",this.options),this.emit("initialized",this.options),l.resolve(p),n(d,p)},"finish");if(this.languages&&!this.isInitialized)return u(null,this.t.bind(this));this.changeLanguage(this.options.lng,u)},"load");return this.options.resources||!this.options.initAsync?c():setTimeout(c,0),l}loadResources(e,n=oi){let r=n,o=O(e)?e:this.language;if(typeof e=="function"&&(r=e),!this.options.resources||this.options.partialBundledLanguages){if(o?.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return r();let s=[],a=i(l=>{if(!l||l==="cimode")return;this.services.languageUtils.toResolveHierarchy(l).forEach(u=>{u!=="cimode"&&s.indexOf(u)<0&&s.push(u)})},"append");o?a(o):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(c=>a(c)),this.options.preload?.forEach?.(l=>a(l)),this.services.backendConnector.load(s,this.options.ns,l=>{!l&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),r(l)})}else r(null)}reloadResources(e,n,r){let o=pr();return typeof e=="function"&&(r=e,e=void 0),typeof n=="function"&&(r=n,n=void 0),e||(e=this.languages),n||(n=this.options.ns),r||(r=oi),this.services.backendConnector.reload(e,n,s=>{o.resolve(),r(s)}),o}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");return e.type==="backend"&&(this.modules.backend=e),(e.type==="logger"||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type==="languageDetector"&&(this.modules.languageDetector=e),e.type==="i18nFormat"&&(this.modules.i18nFormat=e),e.type==="postProcessor"&&su.addPostProcessor(e),e.type==="formatter"&&(this.modules.formatter=e),e.type==="3rdParty"&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&!(["cimode","dev"].indexOf(e)>-1)){for(let n=0;n-1)&&this.store.hasLanguageSomeTranslations(r)){this.resolvedLanguage=r;break}}!this.resolvedLanguage&&this.languages.indexOf(e)<0&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,n){this.isLanguageChangingTo=e;let r=pr();this.emit("languageChanging",e);let o=i(l=>{this.language=l,this.languages=this.services.languageUtils.toResolveHierarchy(l),this.resolvedLanguage=void 0,this.setResolvedLanguage(l)},"setLngProps"),s=i((l,c)=>{c?this.isLanguageChangingTo===e&&(o(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,r.resolve((...u)=>this.t(...u)),n&&n(l,(...u)=>this.t(...u))},"done"),a=i(l=>{!e&&!l&&this.services.languageDetector&&(l=[]);let c=O(l)?l:l&&l[0],u=this.store.hasLanguageSomeTranslations(c)?c:this.services.languageUtils.getBestMatchFromCodes(O(l)?[l]:l);u&&(this.language||o(u),this.translator.language||this.translator.changeLanguage(u),this.services.languageDetector?.cacheUserLanguage?.(u)),this.loadResources(u,d=>{s(d,u)})},"setLng");return!e&&this.services.languageDetector&&!this.services.languageDetector.async?a(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(a):this.services.languageDetector.detect(a):a(e),r}getFixedT(e,n,r){let o=i((s,a,...l)=>{let c;typeof a!="object"?c=this.options.overloadTranslationOptionHandler([s,a].concat(l)):c={...a},c.lng=c.lng||o.lng,c.lngs=c.lngs||o.lngs,c.ns=c.ns||o.ns,c.keyPrefix!==""&&(c.keyPrefix=c.keyPrefix||r||o.keyPrefix);let u=this.options.keySeparator||".",d;return c.keyPrefix&&Array.isArray(s)?d=s.map(p=>(typeof p=="function"&&(p=$s(p,{...this.options,...a})),`${c.keyPrefix}${u}${p}`)):(typeof s=="function"&&(s=$s(s,{...this.options,...a})),d=c.keyPrefix?`${c.keyPrefix}${u}${s}`:s),this.t(d,c)},"fixedT");return O(e)?o.lng=e:o.lngs=e,o.ns=n,o.keyPrefix=r,o}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,n={}){if(!this.isInitialized)return this.logger.warn("hasLoadedNamespace: i18next was not initialized",this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty",this.languages),!1;let r=n.lng||this.resolvedLanguage||this.languages[0],o=this.options?this.options.fallbackLng:!1,s=this.languages[this.languages.length-1];if(r.toLowerCase()==="cimode")return!0;let a=i((l,c)=>{let u=this.services.backendConnector.state[`${l}|${c}`];return u===-1||u===0||u===2},"loadNotPending");if(n.precheck){let l=n.precheck(this,a);if(l!==void 0)return l}return!!(this.hasResourceBundle(r,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(r,e)&&(!o||a(s,e)))}loadNamespaces(e,n){let r=pr();return this.options.ns?(O(e)&&(e=[e]),e.forEach(o=>{this.options.ns.indexOf(o)<0&&this.options.ns.push(o)}),this.loadResources(o=>{r.resolve(),n&&n(o)}),r):(n&&n(),Promise.resolve())}loadLanguages(e,n){let r=pr();O(e)&&(e=[e]);let o=this.options.preload||[],s=e.filter(a=>o.indexOf(a)<0&&this.services.languageUtils.isSupportedCode(a));return s.length?(this.options.preload=o.concat(s),this.loadResources(a=>{r.resolve(),n&&n(a)}),r):(n&&n(),Promise.resolve())}dir(e){if(e||(e=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language)),!e)return"rtl";try{let o=new Intl.Locale(e);if(o&&o.getTextInfo){let s=o.getTextInfo();if(s&&s.direction)return s.direction}}catch{}let n=["ar","shu","sqr","ssh","xaa","yhd","yud","aao","abh","abv","acm","acq","acw","acx","acy","adf","ads","aeb","aec","afb","ajp","apc","apd","arb","arq","ars","ary","arz","auz","avl","ayh","ayl","ayn","ayp","bbz","pga","he","iw","ps","pbt","pbu","pst","prp","prd","ug","ur","ydd","yds","yih","ji","yi","hbo","men","xmn","fa","jpr","peo","pes","prs","dv","sam","ckb"],r=this.services?.languageUtils||new ci(Rs());return e.toLowerCase().indexOf("-latn")>1?"ltr":n.indexOf(r.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(e={},n){let r=new t(e,n);return r.createInstance=t.createInstance,r}cloneInstance(e={},n=oi){let r=e.forkResourceStore;r&&delete e.forkResourceStore;let o={...this.options,...e,isClone:!0},s=new t(o);if((e.debug!==void 0||e.prefix!==void 0)&&(s.logger=s.logger.clone(e)),["store","services","language"].forEach(l=>{s[l]=this[l]}),s.services={...this.services},s.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},r){let l=Object.keys(this.store.data).reduce((c,u)=>(c[u]={...this.store.data[u]},c[u]=Object.keys(c[u]).reduce((d,p)=>(d[p]={...c[u][p]},d),c[u]),c),{});s.store=new ai(l,o),s.services.resourceStore=s.store}if(e.interpolation){let c={...Rs().interpolation,...this.options.interpolation,...e.interpolation},u={...o,interpolation:c};s.services.interpolator=new ui(u)}return s.translator=new li(s.services,o),s.translator.on("*",(l,...c)=>{s.emit(l,...c)}),s.init(o,n),s.translator.options=o,s.translator.backendConnector.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},s}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}},ke=Ws.createInstance(),a0=ke.createInstance,l0=ke.dir,cu=ke.init,c0=ke.loadResources,u0=ke.reloadResources,d0=ke.use,p0=ke.changeLanguage,h0=ke.getFixedT,wt=ke.t,f0=ke.exists,m0=ke.setDefaultNamespace,g0=ke.hasLoadedNamespace,b0=ke.loadNamespaces,w0=ke.loadLanguages;var du=require("obsidian");var uu=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Fn=class extends uu.Modal{static{i(this,"ModalBase")}constructor(e,n,r){super(e.app),this.resolve=n,q(this.containerEl,r),e.cssClass&&this.containerEl.addClass(e.cssClass)}};async function di(t){return await new Promise(e=>{t(e).open()})}i(di,"showModal");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Hs=class extends Fn{static{i(this,"AlertModal")}params;constructor(e,n){super(e,n,M.AlertModal);let r={app:e.app,cssClass:"",message:e.message,okButtonText:wt(o=>o.obsidianDevUtils.buttons.ok),title:""};this.params={...r,...e}}onClose(){super.onClose(),this.resolve()}onOpen(){super.onOpen(),this.titleEl.setText(this.params.title),this.contentEl.createEl("p",{text:this.params.message});let e=new du.ButtonComponent(this.contentEl);e.setButtonText(this.params.okButtonText),e.setCta(),e.onClick(this.close.bind(this)),e.setClass(M.OkButton)}};async function pi(t){await di(e=>new Hs(t,e))}i(pi,"alert");var wi=require("obsidian");var pu=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var hi=class extends pu.Component{static{i(this,"AsyncEventsComponent")}registerAsyncEvent(e){fi(this,e)}};function fi(t,e){t.register(()=>{e.asyncEvents.offref(e)})}i(fi,"registerAsyncEvent");var fu=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var mi={obsidianDevUtils:{asyncWithNotice:{milliseconds:"milliseconds...",operation:"Operation",runningFor:"Running for",terminateOperation:"You can terminate the operation by clicking the button below, but be aware it might leave the vault in an inconsistent state.",timedOut:"The operation timed out after {{duration}} milliseconds."},buttons:{cancel:"Cancel",ok:"OK"},callout:{loadContent:"Load content for callout"},dataview:{itemsPerPage:"Items per page:",jumpToPage:"Jump to page:",pageHeader:"Page {{pageNumber}} of {{totalPages}}, Total items: {{totalItems}}"},metadataCache:{getBacklinksForFilePath:"Get backlinks for {{filePath}}"},notices:{attachmentIsStillUsed:"Attachment {{attachmentPath}} is still used by other notes. It will not be deleted.",unhandledError:"An unhandled error occurred. Please check the console for more information."},queue:{flushQueue:"Flush queue"},renameDeleteHandler:{handleDelete:"Handle delete: {{filePath}}",handleOrphanedRenames:"Handle orphaned renames",handleRename:"Handle rename: {{oldPath}} -> {{newPath}}",updatedLinks:"Updated {{linksCount}} links in {{filesCount}} files."},vault:{processFile:"Process file {{filePath}}"}}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var js="en",jf={en:mi},gi=jf;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var hu="translation",Ks=!1;async function qs(t,e=!0){Ks||(Ks=!0,await cu({fallbackLng:js,initAsync:e,interpolation:{escapeValue:!1},lng:(0,fu.getLanguage)(),resources:Object.fromEntries(Object.entries(t).map(([n,r])=>[n,{[hu]:r}])),returnEmptyString:!1,returnNull:!1}),ke.addResourceBundle(js,hu,mi,!0,!1))}i(qs,"initI18N");function Kf(t,e){return Ks||(console.warn("I18N was not initialized, initializing default obsidian-dev-utils translations"),te(()=>qs(gi,!1))),e?wt(t,e):wt(t)}i(Kf,"tImpl");var E=Kf;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function qf(t){let e=new Set;return t.workspace.iterateAllLeaves(n=>{e.add(n.getContainer())}),Array.from(e)}i(qf,"getAllContainers");function mu(t){return qf(t).map(e=>e.win)}i(mu,"getAllDomWindows");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var bi=class extends wi.Plugin{static{i(this,"PluginBase")}events=new pt;get abortSignal(){if(!this._abortSignal)throw new Error("Abort signal not defined");return this._abortSignal}get settings(){return this.settingsManager.settingsWrapper.safeSettings}get settingsManager(){if(!this._settingsManager)throw new Error("Settings manager not defined");return this._settingsManager}get settingsTab(){if(!this._settingsTab)throw new Error("Settings tab not defined");return this._settingsTab}_abortSignal;_settingsManager=null;_settingsTab=null;lifecycleEventNames=new Set;notice;consoleDebug(e,...n){xn(this.manifest.id,1)(e,...n)}async onExternalSettingsChange(){await super.onExternalSettingsChange?.(),await this._settingsManager?.loadFromFile(!1)}async onload(){await super.onload(),await this.onloadImpl(),zc(this.afterLoad.bind(this))}onunload(){super.onunload(),te(async()=>{try{await this.onunloadImpl()}finally{await this.triggerLifecycleEvent("unload")}})}registerDomWindowHandler(e){let n=window;e(n),this.app.workspace.onLayoutReady(()=>{for(let r of mu(this.app))r!==n&&e(r);this.registerEvent(this.app.workspace.on("window-open",r=>{e(r.win)}))})}registerForLifecycleEvent(e,n){te(async()=>{await this.waitForLifecycleEvent(e),await n()})}registerPopupDocumentDomEvent(e,n,r){this.registerDomWindowHandler(o=>{this.registerDomEvent(o.document,e,n,r)})}registerPopupWindowDomEvent(e,n,r){this.registerDomWindowHandler(o=>{this.registerDomEvent(o,e,n,r)})}async waitForLifecycleEvent(e){this.lifecycleEventNames.has(e)||await new Promise(n=>{this.events.once(e,()=>{n()})})}createSettingsManager(){return null}createSettingsTab(){return null}createTranslationsMap(){return gi}handleAsyncError(e){this.showNotice(E(n=>n.obsidianDevUtils.notices.unhandledError))}async onLayoutReady(){await ut()}async onloadImpl(){qc(this.app,this.manifest.id),this.registerDomWindowHandler(n=>{Kc(n)}),await qs(this.createTranslationsMap()),this.register(ac(this.handleAsyncError.bind(this))),this._settingsManager=this.createSettingsManager(),this._settingsManager&&(fi(this,this._settingsManager.on("loadSettings",this.onLoadSettings.bind(this))),fi(this,this._settingsManager.on("saveSettings",this.onSaveSettings.bind(this)))),await this._settingsManager?.loadFromFile(!0),this._settingsTab=this.createSettingsTab(),this._settingsTab&&this.addSettingTab(this._settingsTab);let e=new AbortController;this._abortSignal=e.signal,this.register(()=>{e.abort(new mn(`Plugin ${this.manifest.id} had been unloaded`))})}async onLoadSettings(e,n){await ut()}async onSaveSettings(e,n,r){await ut()}async onunloadImpl(){await ut()}showNotice(e){this.notice&&this.notice.hide(),this.notice=new wi.Notice(`${this.manifest.name} +${e}`)}async afterLoad(){this.abortSignal.aborted||(await this.triggerLifecycleEvent("load"),this.app.workspace.onLayoutReady(Pn(this.onLayoutReadyBase.bind(this))))}async onLayoutReadyBase(){try{await this.onLayoutReady()}finally{await this.triggerLifecycleEvent("layoutReady")}}async triggerLifecycleEvent(e){this.lifecycleEventNames.add(e),await this.events.triggerAsync(e)}};var gu=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function yi(t){return Vc({...t,onTimeout:t.shouldShowTimeoutNotice?wu:yu})}i(yi,"retryWithTimeoutNotice");async function bu(t){return Ms({...t,onTimeout:t.shouldShowTimeoutNotice?wu:yu})}i(bu,"runWithTimeoutNotice");function wu(t){let e=Math.trunc(performance.now()-t.duration),n,r,o=1e3,s=new gu.Notice(createFragment(l=>{t.operationName&&(l.appendText(E(u=>u.obsidianDevUtils.asyncWithNotice.operation)),l.appendText(": "),l.appendText(t.operationName),l.createEl("br")),l.appendText(E(u=>u.obsidianDevUtils.asyncWithNotice.timedOut,{duration:t.duration})),l.createEl("br"),l.appendText(E(u=>u.obsidianDevUtils.asyncWithNotice.runningFor)),l.appendText(" "),n=l.createSpan(),l.appendText(" "),l.appendText(E(u=>u.obsidianDevUtils.asyncWithNotice.milliseconds)),l.createEl("br"),l.appendText(E(u=>u.obsidianDevUtils.asyncWithNotice.terminateOperation)),l.createEl("br"),l.createEl("button",{text:E(u=>u.obsidianDevUtils.buttons.cancel)}).addEventListener("click",()=>{t.terminateOperation(),clearInterval(r),s.hide()})}));a(),r=window.setInterval(a,o),t.onOperationCompleted(()=>{clearInterval(r),s.hide()});function a(){let l=Math.max(t.duration,Math.round((performance.now()-e)/o)*o);n.textContent=String(l)}i(a,"updateRunningTime")}i(wu,"onTimeoutNotice");function yu(t){let e=Math.trunc(performance.now()-t.duration);t.onOperationCompleted(()=>{xn("AsyncWithNotice:onTimeoutWithoutNotice")("Operation completed after timeout",{operationName:t.operationName,totalDuration:Math.trunc(performance.now()-e)})})}i(yu,"onTimeoutWithoutNotice");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function ku(t,e,n,r){n.throwIfAborted();let o=Y("Logger:invokeAsyncAndLog"),s=performance.now();r??=Pe(1),mt(o,r,`${t}:start`,{fn:e,timestampStart:s});try{await e(n);let a=performance.now(),l=Math.trunc(a-s);n.aborted&&(mt(o,r,`${t}:aborted`,{abortReason:n.reason,duration:l,fn:e,timestampEnd:a,timestampStart:s}),n.throwIfAborted()),mt(o,r,`${t}:end`,{duration:l,fn:e,timestampEnd:a,timestampStart:s})}catch(a){let l=performance.now();throw mt(o,r,`${t}:error`,{duration:Math.trunc(l-s),error:a,fn:e,timestampEnd:l,timestampStart:s}),a}}i(ku,"invokeAsyncAndLog");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Ue(t){let e=t.stackTrace??Pe(1);te(()=>Gf(t),e)}i(Ue,"addToQueue");async function Gf(t){let e=t.abortSignal??Se();e.throwIfAborted();let r=t.timeoutInMilliseconds??6e4,o=t.stackTrace??Pe(1),s=t.operationName??"",a=Cu(t.app).value;a.items.push({abortSignal:e,operationFn:t.operationFn,operationName:s,shouldShowTimeoutNotice:t.shouldShowTimeoutNotice??!0,stackTrace:o,timeoutInMilliseconds:r}),a.promise=a.promise.then(()=>Au(t.app)),await a.promise}i(Gf,"addToQueueAndWait");function Cu(t){return Te(t,"queue",{items:[],promise:Promise.resolve()})}i(Cu,"getQueue");async function Au(t){let e=Cu(t).value,n=e.items[0];n&&(await Is(()=>bu({context:{queuedFn:n.operationFn},async operationFn(r){await ku(n.operationName||Au.name,n.operationFn,nt(r,n.abortSignal),n.stackTrace)},operationName:n.operationName,shouldShowTimeoutNotice:n.shouldShowTimeoutNotice,stackTrace:n.stackTrace,timeoutInMilliseconds:n.timeoutInMilliseconds})),e.items.shift())}i(Au,"processNextQueueItem");var to=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Mt=(t=>(t.DeleteNote="DeleteNote",t.RenameNote="RenameNote",t.Unknown="Unknown",t))(Mt||{}),vu="__DUMMY__";async function Gt(t){let{app:e,notePathOrFile:n,oldAttachmentPathOrFile:r,shouldSkipDuplicateCheck:o}=t,s=G(e,r),a=it(s),l=Ne(s,a),c=X(e,s),u=e.vault.getAvailablePathForAttachments.extended;return u?u({attachmentFileBaseName:l,attachmentFileContent:c?await e.vault.readBinary(c):void 0,attachmentFileExtension:a.slice(1),attachmentFileStat:c?.stat,context:t.context,notePathOrFile:n,oldAttachmentPathOrFile:t.oldAttachmentPathOrFile,oldNotePathOrFile:t.oldNotePathOrFile,shouldSkipDuplicateCheck:o,shouldSkipMissingAttachmentFolderCreation:!0}):await Yf({app:e,attachmentFileBaseName:l,attachmentFileExtension:a.slice(1),notePathOrFile:n,shouldSkipDuplicateCheck:o,shouldSkipMissingAttachmentFolderCreation:!0})}i(Gt,"getAttachmentFilePath");async function In(t,e,n="Unknown"){return qe(await Gt({app:t,context:n,notePathOrFile:e,oldAttachmentPathOrFile:vu,shouldSkipDuplicateCheck:!0}))}i(In,"getAttachmentFolderPath");async function Yf(t){let{app:e,attachmentFileExtension:n,notePathOrFile:r,shouldSkipDuplicateCheck:o,shouldSkipMissingAttachmentFolderCreation:s}=t,a=e.vault.getConfig("attachmentFolderPath"),l=a==="."||a==="./",c=a.startsWith("./")?Wr(a,"./"):null,u=X(e,r);l?a=u?u.parent?.path??"":"":c&&(a=(u?u.parent?.getParentPrefix()??"":"")+c),a=ar(xu(a));let d=ar(xu(t.attachmentFileBaseName)),p=st(e,a,!0);!p&&c&&(p=s?wn(e,a,!0):await e.vault.createFolder(a));let h=p?.getParentPrefix()??"";return o?pc(h+d,n):e.vault.getAvailablePath(h+d,n)}i(Yf,"getAvailablePathForAttachments");async function Gs(t,e,n="Unknown"){let r=await In(t,e,n),o=await In(t,oe(K(e),`${vu}.${Ht}`),n);return r!==o}i(Gs,"hasOwnAttachmentFolder");function xu(t){return t=we(t,/(?:[\\/])+/g,"/"),t=we(t,/^\/+|\/+$/g,""),t||"/"}i(xu,"normalizeSlashes");var jn=require("obsidian");var Jf={};function Yt(t,e){let n=e||Jf,r=typeof n.includeImageAlt=="boolean"?n.includeImageAlt:!0,o=typeof n.includeHtml=="boolean"?n.includeHtml:!0;return Su(t,r,o)}i(Yt,"toString");function Su(t,e,n){if(Qf(t)){if("value"in t)return t.type==="html"&&!n?"":t.value;if(e&&"alt"in t&&t.alt)return t.alt;if("children"in t)return Eu(t.children,e,n)}return Array.isArray(t)?Eu(t,e,n):""}i(Su,"one");function Eu(t,e,n){let r=[],o=-1;for(;++oo?0:o+e:e=e>o?o:e,n=n>0?n:0,r.length<1e4)a=Array.from(r),a.unshift(e,n),t.splice(...a);else for(n&&t.splice(e,n);s0?(me(t,t.length,0,e),t):e}i(Fe,"push");var Tu={}.hasOwnProperty;function Fu(t){let e={},n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"\uFFFD":String.fromCodePoint(n)}i(ki,"decodeNumericCharacterReference");function Pt(t){return t.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}i(Pt,"normalizeIdentifier");var We=Lt(/[A-Za-z]/),Ie=Lt(/[\dA-Za-z]/),Iu=Lt(/[#-'*+\--9=?A-Z^-~]/);function mr(t){return t!==null&&(t<32||t===127)}i(mr,"asciiControl");var gr=Lt(/\d/),Mu=Lt(/[\dA-Fa-f]/),Lu=Lt(/[!-/:-@[-`{-~]/);function F(t){return t!==null&&t<-2}i(F,"markdownLineEnding");function re(t){return t!==null&&(t<0||t===32)}i(re,"markdownLineEndingOrSpace");function D(t){return t===-2||t===-1||t===32}i(D,"markdownSpace");var Nu=Lt(/\p{P}|\p{S}/u),Ou=Lt(/\s/);function Lt(t){return e;function e(n){return n!==null&&n>-1&&t.test(String.fromCharCode(n))}}i(Lt,"regexCheck");function _(t,e,n,r){let o=r?r-1:Number.POSITIVE_INFINITY,s=0;return a;function a(c){return D(c)?(t.enter(n),l(c)):e(c)}function l(c){return D(c)&&s++a))return;let $=e.events.length,H=$,R,V;for(;H--;)if(e.events[H][0]==="exit"&&e.events[H][1].type==="chunkFlow"){if(R){V=e.events[H][1].end;break}R=!0}for(w(r),C=$;Cv;){let I=n[P];e.containerState=I[1],I[0].exit.call(e,t)}n.length=v}function A(){o.write([null]),s=void 0,o=void 0,e.containerState._closeFlow=void 0}}i(tm,"initializeDocument");function nm(t,e,n){return _(t,t.attempt(this.parser.constructs.document,e,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}i(nm,"tokenizeContainer");function Ln(t){if(t===null||re(t)||Ou(t))return 1;if(Nu(t))return 2}i(Ln,"classifyCharacter");function Nn(t,e,n){let r=[],o=-1;for(;++o1&&t[n][1].end.offset-t[n][1].start.offset>1?2:1;let p={...t[r][1].end},h={...t[n][1].start};_u(p,-c),_u(h,c),a={type:c>1?"strongSequence":"emphasisSequence",start:p,end:{...t[r][1].end}},l={type:c>1?"strongSequence":"emphasisSequence",start:{...t[n][1].start},end:h},s={type:c>1?"strongText":"emphasisText",start:{...t[r][1].end},end:{...t[n][1].start}},o={type:c>1?"strong":"emphasis",start:{...a.start},end:{...l.end}},t[r][1].end={...a.start},t[n][1].start={...l.end},u=[],t[r][1].end.offset-t[r][1].start.offset&&(u=Fe(u,[["enter",t[r][1],e],["exit",t[r][1],e]])),u=Fe(u,[["enter",o,e],["enter",a,e],["exit",a,e],["enter",s,e]]),u=Fe(u,Nn(e.parser.constructs.insideSpan.null,t.slice(r+1,n),e)),u=Fe(u,[["exit",s,e],["enter",l,e],["exit",l,e],["exit",o,e]]),t[n][1].end.offset-t[n][1].start.offset?(d=2,u=Fe(u,[["enter",t[n][1],e],["exit",t[n][1],e]])):d=0,me(t,r-1,n-r+3,u),n=r+u.length-d-2;break}}for(n=-1;++n0&&D(C)?_(t,A,"linePrefix",s+1)(C):A(C)}function A(C){return C===null||F(C)?t.check($u,k,P)(C):(t.enter("codeFlowValue"),v(C))}function v(C){return C===null||F(C)?(t.exit("codeFlowValue"),A(C)):(t.consume(C),v)}function P(C){return t.exit("codeFenced"),e(C)}function I(C,$,H){let R=0;return V;function V(N){return C.enter("lineEnding"),C.consume(N),C.exit("lineEnding"),de}function de(N){return C.enter("codeFencedFence"),D(N)?_(C,W,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(N):W(N)}function W(N){return N===l?(C.enter("codeFencedFenceSequence"),T(N)):H(N)}function T(N){return N===l?(R++,C.consume(N),T):R>=a?(C.exit("codeFencedFenceSequence"),D(N)?_(C,L,"whitespace")(N):L(N)):H(N)}function L(N){return N===null||F(N)?(C.exit("codeFencedFence"),$(N)):H(N)}}}i(pm,"tokenizeCodeFenced");function hm(t,e,n){let r=this;return o;function o(a){return a===null?n(a):(t.enter("lineEnding"),t.consume(a),t.exit("lineEnding"),s)}function s(a){return r.parser.lazy[r.now().line]?n(a):e(a)}}i(hm,"tokenizeNonLazyContinuation");var wr={name:"codeIndented",tokenize:mm},fm={partial:!0,tokenize:gm};function mm(t,e,n){let r=this;return o;function o(u){return t.enter("codeIndented"),_(t,s,"linePrefix",5)(u)}function s(u){let d=r.events[r.events.length-1];return d&&d[1].type==="linePrefix"&&d[2].sliceSerialize(d[1],!0).length>=4?a(u):n(u)}function a(u){return u===null?c(u):F(u)?t.attempt(fm,a,c)(u):(t.enter("codeFlowValue"),l(u))}function l(u){return u===null||F(u)?(t.exit("codeFlowValue"),a(u)):(t.consume(u),l)}function c(u){return t.exit("codeIndented"),e(u)}}i(mm,"tokenizeCodeIndented");function gm(t,e,n){let r=this;return o;function o(a){return r.parser.lazy[r.now().line]?n(a):F(a)?(t.enter("lineEnding"),t.consume(a),t.exit("lineEnding"),o):_(t,s,"linePrefix",5)(a)}function s(a){let l=r.events[r.events.length-1];return l&&l[1].type==="linePrefix"&&l[2].sliceSerialize(l[1],!0).length>=4?e(a):F(a)?o(a):n(a)}}i(gm,"tokenizeFurtherStart");var Js={name:"codeText",previous:wm,resolve:bm,tokenize:ym};function bm(t){let e=t.length-4,n=3,r,o;if((t[n][1].type==="lineEnding"||t[n][1].type==="space")&&(t[e][1].type==="lineEnding"||t[e][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+e+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return ethis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-e+this.left.length).reverse():this.left.slice(e).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(e,n,r){let o=n||0;this.setCursor(Math.trunc(e));let s=this.right.splice(this.right.length-o,Number.POSITIVE_INFINITY);return r&&yr(this.left,r),s.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(e){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(e)}pushMany(e){this.setCursor(Number.POSITIVE_INFINITY),yr(this.left,e)}unshift(e){this.setCursor(0),this.right.push(e)}unshiftMany(e){this.setCursor(0),yr(this.right,e.reverse())}setCursor(e){if(!(e===this.left.length||e>this.left.length&&this.right.length===0||e<0&&this.left.length===0))if(e=4?e(a):t.interrupt(r.parser.constructs.flow,n,e)(a)}}i(vm,"tokenizeContinuation");function Pi(t,e,n,r,o,s,a,l,c){let u=c||Number.POSITIVE_INFINITY,d=0;return p;function p(w){return w===60?(t.enter(r),t.enter(o),t.enter(s),t.consume(w),t.exit(s),h):w===null||w===32||w===41||mr(w)?n(w):(t.enter(r),t.enter(a),t.enter(l),t.enter("chunkString",{contentType:"string"}),k(w))}function h(w){return w===62?(t.enter(s),t.consume(w),t.exit(s),t.exit(o),t.exit(r),e):(t.enter(l),t.enter("chunkString",{contentType:"string"}),f(w))}function f(w){return w===62?(t.exit("chunkString"),t.exit(l),h(w)):w===null||w===60||F(w)?n(w):(t.consume(w),w===92?b:f)}function b(w){return w===60||w===62||w===92?(t.consume(w),f):f(w)}function k(w){return!d&&(w===null||w===41||re(w))?(t.exit("chunkString"),t.exit(l),t.exit(a),t.exit(r),e(w)):d999||f===null||f===91||f===93&&!c||f===94&&!l&&"_hiddenFootnoteSupport"in a.parser.constructs?n(f):f===93?(t.exit(s),t.enter(o),t.consume(f),t.exit(o),t.exit(r),e):F(f)?(t.enter("lineEnding"),t.consume(f),t.exit("lineEnding"),d):(t.enter("chunkString",{contentType:"string"}),p(f))}function p(f){return f===null||f===91||f===93||F(f)||l++>999?(t.exit("chunkString"),d(f)):(t.consume(f),c||(c=!D(f)),f===92?h:p)}function h(f){return f===91||f===92||f===93?(t.consume(f),l++,p):p(f)}}i(Ti,"factoryLabel");function Fi(t,e,n,r,o,s){let a;return l;function l(h){return h===34||h===39||h===40?(t.enter(r),t.enter(o),t.consume(h),t.exit(o),a=h===40?41:h,c):n(h)}function c(h){return h===a?(t.enter(o),t.consume(h),t.exit(o),t.exit(r),e):(t.enter(s),u(h))}function u(h){return h===a?(t.exit(s),c(a)):h===null?n(h):F(h)?(t.enter("lineEnding"),t.consume(h),t.exit("lineEnding"),_(t,u,"linePrefix")):(t.enter("chunkString",{contentType:"string"}),d(h))}function d(h){return h===a||h===null||F(h)?(t.exit("chunkString"),u(h)):(t.consume(h),h===92?p:d)}function p(h){return h===a||h===92?(t.consume(h),d):d(h)}}i(Fi,"factoryTitle");function Jt(t,e){let n;return r;function r(o){return F(o)?(t.enter("lineEnding"),t.consume(o),t.exit("lineEnding"),n=!0,r):D(o)?_(t,r,n?"linePrefix":"lineSuffix")(o):e(o)}}i(Jt,"factoryWhitespace");var Xs={name:"definition",tokenize:Sm},Em={partial:!0,tokenize:Pm};function Sm(t,e,n){let r=this,o;return s;function s(f){return t.enter("definition"),a(f)}function a(f){return Ti.call(r,t,l,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(f)}function l(f){return o=Pt(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),f===58?(t.enter("definitionMarker"),t.consume(f),t.exit("definitionMarker"),c):n(f)}function c(f){return re(f)?Jt(t,u)(f):u(f)}function u(f){return Pi(t,d,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(f)}function d(f){return t.attempt(Em,p,p)(f)}function p(f){return D(f)?_(t,h,"whitespace")(f):h(f)}function h(f){return f===null||F(f)?(t.exit("definition"),r.parser.defined.push(o),e(f)):n(f)}}i(Sm,"tokenizeDefinition");function Pm(t,e,n){return r;function r(l){return re(l)?Jt(t,o)(l):n(l)}function o(l){return Fi(t,s,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(l)}function s(l){return D(l)?_(t,a,"whitespace")(l):a(l)}function a(l){return l===null||F(l)?e(l):n(l)}}i(Pm,"tokenizeTitleBefore");var Zs={name:"hardBreakEscape",tokenize:Tm};function Tm(t,e,n){return r;function r(s){return t.enter("hardBreakEscape"),t.consume(s),o}function o(s){return F(s)?(t.exit("hardBreakEscape"),e(s)):n(s)}}i(Tm,"tokenizeHardBreakEscape");var ea={name:"headingAtx",resolve:Fm,tokenize:Im};function Fm(t,e){let n=t.length-2,r=3,o,s;return t[r][1].type==="whitespace"&&(r+=2),n-2>r&&t[n][1].type==="whitespace"&&(n-=2),t[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&t[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(o={type:"atxHeadingText",start:t[r][1].start,end:t[n][1].end},s={type:"chunkText",start:t[r][1].start,end:t[n][1].end,contentType:"text"},me(t,r,n-r+1,[["enter",o,e],["enter",s,e],["exit",s,e],["exit",o,e]])),t}i(Fm,"resolveHeadingAtx");function Im(t,e,n){let r=0;return o;function o(d){return t.enter("atxHeading"),s(d)}function s(d){return t.enter("atxHeadingSequence"),a(d)}function a(d){return d===35&&r++<6?(t.consume(d),a):d===null||re(d)?(t.exit("atxHeadingSequence"),l(d)):n(d)}function l(d){return d===35?(t.enter("atxHeadingSequence"),c(d)):d===null||F(d)?(t.exit("atxHeading"),e(d)):D(d)?_(t,l,"whitespace")(d):(t.enter("atxHeadingText"),u(d))}function c(d){return d===35?(t.consume(d),c):(t.exit("atxHeadingSequence"),l(d))}function u(d){return d===null||d===35||re(d)?(t.exit("atxHeadingText"),l(d)):(t.consume(d),u)}}i(Im,"tokenizeHeadingAtx");var zu=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],ta=["pre","script","style","textarea"];var na={concrete:!0,name:"htmlFlow",resolveTo:Nm,tokenize:Om},Mm={partial:!0,tokenize:Dm},Lm={partial:!0,tokenize:Rm};function Nm(t){let e=t.length;for(;e--&&!(t[e][0]==="enter"&&t[e][1].type==="htmlFlow"););return e>1&&t[e-2][1].type==="linePrefix"&&(t[e][1].start=t[e-2][1].start,t[e+1][1].start=t[e-2][1].start,t.splice(e-2,2)),t}i(Nm,"resolveToHtmlFlow");function Om(t,e,n){let r=this,o,s,a,l,c;return u;function u(g){return d(g)}function d(g){return t.enter("htmlFlow"),t.enter("htmlFlowData"),t.consume(g),p}function p(g){return g===33?(t.consume(g),h):g===47?(t.consume(g),s=!0,k):g===63?(t.consume(g),o=3,r.interrupt?e:m):We(g)?(t.consume(g),a=String.fromCharCode(g),y):n(g)}function h(g){return g===45?(t.consume(g),o=2,f):g===91?(t.consume(g),o=5,l=0,b):We(g)?(t.consume(g),o=4,r.interrupt?e:m):n(g)}function f(g){return g===45?(t.consume(g),r.interrupt?e:m):n(g)}function b(g){let be="CDATA[";return g===be.charCodeAt(l++)?(t.consume(g),l===be.length?r.interrupt?e:W:b):n(g)}function k(g){return We(g)?(t.consume(g),a=String.fromCharCode(g),y):n(g)}function y(g){if(g===null||g===47||g===62||re(g)){let be=g===47,zt=a.toLowerCase();return!be&&!s&&ta.includes(zt)?(o=1,r.interrupt?e(g):W(g)):zu.includes(a.toLowerCase())?(o=6,be?(t.consume(g),w):r.interrupt?e(g):W(g)):(o=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(g):s?A(g):v(g))}return g===45||Ie(g)?(t.consume(g),a+=String.fromCharCode(g),y):n(g)}function w(g){return g===62?(t.consume(g),r.interrupt?e:W):n(g)}function A(g){return D(g)?(t.consume(g),A):V(g)}function v(g){return g===47?(t.consume(g),V):g===58||g===95||We(g)?(t.consume(g),P):D(g)?(t.consume(g),v):V(g)}function P(g){return g===45||g===46||g===58||g===95||Ie(g)?(t.consume(g),P):I(g)}function I(g){return g===61?(t.consume(g),C):D(g)?(t.consume(g),I):v(g)}function C(g){return g===null||g===60||g===61||g===62||g===96?n(g):g===34||g===39?(t.consume(g),c=g,$):D(g)?(t.consume(g),C):H(g)}function $(g){return g===c?(t.consume(g),c=null,R):g===null||F(g)?n(g):(t.consume(g),$)}function H(g){return g===null||g===34||g===39||g===47||g===60||g===61||g===62||g===96||re(g)?I(g):(t.consume(g),H)}function R(g){return g===47||g===62||D(g)?v(g):n(g)}function V(g){return g===62?(t.consume(g),de):n(g)}function de(g){return g===null||F(g)?W(g):D(g)?(t.consume(g),de):n(g)}function W(g){return g===45&&o===2?(t.consume(g),z):g===60&&o===1?(t.consume(g),j):g===62&&o===4?(t.consume(g),Q):g===63&&o===3?(t.consume(g),m):g===93&&o===5?(t.consume(g),ve):F(g)&&(o===6||o===7)?(t.exit("htmlFlowData"),t.check(Mm,he,T)(g)):g===null||F(g)?(t.exit("htmlFlowData"),T(g)):(t.consume(g),W)}function T(g){return t.check(Lm,L,he)(g)}function L(g){return t.enter("lineEnding"),t.consume(g),t.exit("lineEnding"),N}function N(g){return g===null||F(g)?T(g):(t.enter("htmlFlowData"),W(g))}function z(g){return g===45?(t.consume(g),m):W(g)}function j(g){return g===47?(t.consume(g),a="",pe):W(g)}function pe(g){if(g===62){let be=a.toLowerCase();return ta.includes(be)?(t.consume(g),Q):W(g)}return We(g)&&a.length<8?(t.consume(g),a+=String.fromCharCode(g),pe):W(g)}function ve(g){return g===93?(t.consume(g),m):W(g)}function m(g){return g===62?(t.consume(g),Q):g===45&&o===2?(t.consume(g),m):W(g)}function Q(g){return g===null||F(g)?(t.exit("htmlFlowData"),he(g)):(t.consume(g),Q)}function he(g){return t.exit("htmlFlow"),e(g)}}i(Om,"tokenizeHtmlFlow");function Rm(t,e,n){let r=this;return o;function o(a){return F(a)?(t.enter("lineEnding"),t.consume(a),t.exit("lineEnding"),s):n(a)}function s(a){return r.parser.lazy[r.now().line]?n(a):e(a)}}i(Rm,"tokenizeNonLazyContinuationStart");function Dm(t,e,n){return r;function r(o){return t.enter("lineEnding"),t.consume(o),t.exit("lineEnding"),t.attempt(Nt,e,n)}}i(Dm,"tokenizeBlankLineBefore");var ra={name:"htmlText",tokenize:Bm};function Bm(t,e,n){let r=this,o,s,a;return l;function l(m){return t.enter("htmlText"),t.enter("htmlTextData"),t.consume(m),c}function c(m){return m===33?(t.consume(m),u):m===47?(t.consume(m),I):m===63?(t.consume(m),v):We(m)?(t.consume(m),H):n(m)}function u(m){return m===45?(t.consume(m),d):m===91?(t.consume(m),s=0,b):We(m)?(t.consume(m),A):n(m)}function d(m){return m===45?(t.consume(m),f):n(m)}function p(m){return m===null?n(m):m===45?(t.consume(m),h):F(m)?(a=p,j(m)):(t.consume(m),p)}function h(m){return m===45?(t.consume(m),f):p(m)}function f(m){return m===62?z(m):m===45?h(m):p(m)}function b(m){let Q="CDATA[";return m===Q.charCodeAt(s++)?(t.consume(m),s===Q.length?k:b):n(m)}function k(m){return m===null?n(m):m===93?(t.consume(m),y):F(m)?(a=k,j(m)):(t.consume(m),k)}function y(m){return m===93?(t.consume(m),w):k(m)}function w(m){return m===62?z(m):m===93?(t.consume(m),w):k(m)}function A(m){return m===null||m===62?z(m):F(m)?(a=A,j(m)):(t.consume(m),A)}function v(m){return m===null?n(m):m===63?(t.consume(m),P):F(m)?(a=v,j(m)):(t.consume(m),v)}function P(m){return m===62?z(m):v(m)}function I(m){return We(m)?(t.consume(m),C):n(m)}function C(m){return m===45||Ie(m)?(t.consume(m),C):$(m)}function $(m){return F(m)?(a=$,j(m)):D(m)?(t.consume(m),$):z(m)}function H(m){return m===45||Ie(m)?(t.consume(m),H):m===47||m===62||re(m)?R(m):n(m)}function R(m){return m===47?(t.consume(m),z):m===58||m===95||We(m)?(t.consume(m),V):F(m)?(a=R,j(m)):D(m)?(t.consume(m),R):z(m)}function V(m){return m===45||m===46||m===58||m===95||Ie(m)?(t.consume(m),V):de(m)}function de(m){return m===61?(t.consume(m),W):F(m)?(a=de,j(m)):D(m)?(t.consume(m),de):R(m)}function W(m){return m===null||m===60||m===61||m===62||m===96?n(m):m===34||m===39?(t.consume(m),o=m,T):F(m)?(a=W,j(m)):D(m)?(t.consume(m),W):(t.consume(m),L)}function T(m){return m===o?(t.consume(m),o=void 0,N):m===null?n(m):F(m)?(a=T,j(m)):(t.consume(m),T)}function L(m){return m===null||m===34||m===39||m===60||m===61||m===96?n(m):m===47||m===62||re(m)?R(m):(t.consume(m),L)}function N(m){return m===47||m===62||re(m)?R(m):n(m)}function z(m){return m===62?(t.consume(m),t.exit("htmlTextData"),t.exit("htmlText"),e):n(m)}function j(m){return t.exit("htmlTextData"),t.enter("lineEnding"),t.consume(m),t.exit("lineEnding"),pe}function pe(m){return D(m)?_(t,ve,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(m):ve(m)}function ve(m){return t.enter("htmlTextData"),a(m)}}i(Bm,"tokenizeHtmlText");var Qt={name:"labelEnd",resolveAll:Vm,resolveTo:Um,tokenize:Wm},_m={tokenize:Hm},$m={tokenize:jm},zm={tokenize:Km};function Vm(t){let e=-1,n=[];for(;++e=3&&(u===null||F(u))?(t.exit("thematicBreak"),e(u)):n(u)}function c(u){return u===o?(t.consume(u),r++,c):(t.exit("thematicBreakSequence"),D(u)?_(t,l,"whitespace")(u):l(u))}}i(Jm,"tokenizeThematicBreak");var Ce={continuation:{tokenize:eg},exit:ng,name:"list",tokenize:Zm},Qm={partial:!0,tokenize:rg},Xm={partial:!0,tokenize:tg};function Zm(t,e,n){let r=this,o=r.events[r.events.length-1],s=o&&o[1].type==="linePrefix"?o[2].sliceSerialize(o[1],!0).length:0,a=0;return l;function l(f){let b=r.containerState.type||(f===42||f===43||f===45?"listUnordered":"listOrdered");if(b==="listUnordered"?!r.containerState.marker||f===r.containerState.marker:gr(f)){if(r.containerState.type||(r.containerState.type=b,t.enter(b,{_container:!0})),b==="listUnordered")return t.enter("listItemPrefix"),f===42||f===45?t.check(Xt,n,u)(f):u(f);if(!r.interrupt||f===49)return t.enter("listItemPrefix"),t.enter("listItemValue"),c(f)}return n(f)}function c(f){return gr(f)&&++a<10?(t.consume(f),c):(!r.interrupt||a<2)&&(r.containerState.marker?f===r.containerState.marker:f===41||f===46)?(t.exit("listItemValue"),u(f)):n(f)}function u(f){return t.enter("listItemMarker"),t.consume(f),t.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||f,t.check(Nt,r.interrupt?n:d,t.attempt(Qm,h,p))}function d(f){return r.containerState.initialBlankLine=!0,s++,h(f)}function p(f){return D(f)?(t.enter("listItemPrefixWhitespace"),t.consume(f),t.exit("listItemPrefixWhitespace"),h):n(f)}function h(f){return r.containerState.size=s+r.sliceSerialize(t.exit("listItemPrefix"),!0).length,e(f)}}i(Zm,"tokenizeListStart");function eg(t,e,n){let r=this;return r.containerState._closeFlow=void 0,t.check(Nt,o,s);function o(l){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,_(t,e,"listItemIndent",r.containerState.size+1)(l)}i(o,"onBlank");function s(l){return r.containerState.furtherBlankLines||!D(l)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,a(l)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,t.attempt(Xm,e,a)(l))}i(s,"notBlank");function a(l){return r.containerState._closeFlow=!0,r.interrupt=void 0,_(t,t.attempt(Ce,e,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(l)}i(a,"notInCurrentItem")}i(eg,"tokenizeListContinuation");function tg(t,e,n){let r=this;return _(t,o,"listItemIndent",r.containerState.size+1);function o(s){let a=r.events[r.events.length-1];return a&&a[1].type==="listItemIndent"&&a[2].sliceSerialize(a[1],!0).length===r.containerState.size?e(s):n(s)}}i(tg,"tokenizeIndent");function ng(t){t.exit(this.containerState.type)}i(ng,"tokenizeListEnd");function rg(t,e,n){let r=this;return _(t,o,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function o(s){let a=r.events[r.events.length-1];return!D(s)&&a&&a[1].type==="listItemPrefixWhitespace"?e(s):n(s)}}i(rg,"tokenizeListItemPrefixWhitespace");var Ii={name:"setextUnderline",resolveTo:ig,tokenize:og};function ig(t,e){let n=t.length,r,o,s;for(;n--;)if(t[n][0]==="enter"){if(t[n][1].type==="content"){r=n;break}t[n][1].type==="paragraph"&&(o=n)}else t[n][1].type==="content"&&t.splice(n,1),!s&&t[n][1].type==="definition"&&(s=n);let a={type:"setextHeading",start:{...t[r][1].start},end:{...t[t.length-1][1].end}};return t[o][1].type="setextHeadingText",s?(t.splice(o,0,["enter",a,e]),t.splice(s+1,0,["exit",t[r][1],e]),t[r][1].end={...t[s][1].end}):t[r][1]=a,t.push(["exit",a,e]),t}i(ig,"resolveToSetextUnderline");function og(t,e,n){let r=this,o;return s;function s(u){let d=r.events.length,p;for(;d--;)if(r.events[d][1].type!=="lineEnding"&&r.events[d][1].type!=="linePrefix"&&r.events[d][1].type!=="content"){p=r.events[d][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||p)?(t.enter("setextHeadingLine"),o=u,a(u)):n(u)}function a(u){return t.enter("setextHeadingLineSequence"),l(u)}function l(u){return u===o?(t.consume(u),l):(t.exit("setextHeadingLineSequence"),D(u)?_(t,c,"lineSuffix")(u):c(u))}function c(u){return u===null||F(u)?(t.exit("setextHeadingLine"),e(u)):n(u)}}i(og,"tokenizeSetextUnderline");var Vu={tokenize:sg};function sg(t){let e=this,n=t.attempt(Nt,r,t.attempt(this.parser.constructs.flowInitial,o,_(t,t.attempt(this.parser.constructs.flow,o,t.attempt(Qs,o)),"linePrefix")));return n;function r(s){if(s===null){t.consume(s);return}return t.enter("lineEndingBlank"),t.consume(s),t.exit("lineEndingBlank"),e.currentConstruct=void 0,n}function o(s){if(s===null){t.consume(s);return}return t.enter("lineEnding"),t.consume(s),t.exit("lineEnding"),e.currentConstruct=void 0,n}}i(sg,"initializeFlow");var Uu={resolveAll:Ku()},Wu=ju("string"),Hu=ju("text");function ju(t){return{resolveAll:Ku(t==="text"?ag:void 0),tokenize:e};function e(n){let r=this,o=this.parser.constructs[t],s=n.attempt(o,a,l);return a;function a(d){return u(d)?s(d):l(d)}function l(d){if(d===null){n.consume(d);return}return n.enter("data"),n.consume(d),c}function c(d){return u(d)?(n.exit("data"),s(d)):(n.consume(d),c)}function u(d){if(d===null)return!0;let p=o[d],h=-1;if(p)for(;++hmg,contentInitial:()=>cg,disable:()=>gg,document:()=>lg,flow:()=>dg,flowInitial:()=>ug,insideSpan:()=>fg,string:()=>pg,text:()=>hg});var lg={42:Ce,43:Ce,45:Ce,48:Ce,49:Ce,50:Ce,51:Ce,52:Ce,53:Ce,54:Ce,55:Ce,56:Ce,57:Ce,62:Ci},cg={91:Xs},ug={[-2]:wr,[-1]:wr,32:wr},dg={35:ea,42:Xt,45:[Ii,Xt],60:na,61:Ii,95:Xt,96:vi,126:vi},pg={38:xi,92:Ai},hg={[-5]:kr,[-4]:kr,[-3]:kr,33:ia,38:xi,42:br,60:[Ys,ra],91:oa,92:[Zs,Ai],93:Qt,95:br,96:Js},fg={null:[br,Uu]},mg={null:[42,95]},gg={null:[]};function qu(t,e,n){let r={_bufferIndex:-1,_index:0,line:n&&n.line||1,column:n&&n.column||1,offset:n&&n.offset||0},o={},s=[],a=[],l=[],c=!0,u={attempt:R($),check:R(H),consume:P,enter:I,exit:C,interrupt:R(H,{interrupt:!0})},d={code:null,containerState:{},defineSkip:w,events:[],now:y,parser:t,previous:null,sliceSerialize:b,sliceStream:k,write:f},p=e.tokenize.call(d,u),h;return e.resolveAll&&s.push(e),d;function f(T){return a=Fe(a,T),A(),a[a.length-1]!==null?[]:(V(e,0),d.events=Nn(s,d.events,d),d.events)}i(f,"write");function b(T,L){return wg(k(T),L)}i(b,"sliceSerialize");function k(T){return bg(a,T)}i(k,"sliceStream");function y(){let{_bufferIndex:T,_index:L,line:N,column:z,offset:j}=r;return{_bufferIndex:T,_index:L,line:N,column:z,offset:j}}i(y,"now");function w(T){o[T.line]=T.column,W()}i(w,"defineSkip");function A(){let T;for(;r._index-1){let l=a[0];typeof l=="string"?a[0]=l.slice(r):a.shift()}s>0&&a.push(t[o].slice(0,s))}return a}i(bg,"sliceChunks");function wg(t,e){let n=-1,r=[],o;for(;++n0){let et=B.tokenStack[B.tokenStack.length-1];(et[1]||Qu).call(B,void 0,et[0])}for(S.position={start:Rt(x.length>0?x[0][1].start:{line:1,column:1,offset:0}),end:Rt(x.length>0?x[x.length-2][1].end:{line:1,column:1,offset:0})},J=-1;++J "),s.shift(2);let a=n.indentLines(n.containerFlow(t,s.current()),Eg);return o(),a}i(rd,"blockquote");function Eg(t,e,n){return">"+(n?"":" ")+t}i(Eg,"map");function Li(t,e){return id(t,e.inConstruct,!0)&&!id(t,e.notInConstruct,!1)}i(Li,"patternInScope");function id(t,e,n){if(typeof e=="string"&&(e=[e]),!e||e.length===0)return n;let r=-1;for(;++ra&&(a=s):s=1,o=r+e.length,r=n.indexOf(e,o);return a}i(od,"longestStreak");function Cr(t,e){return!!(e.options.fences===!1&&t.value&&!t.lang&&/[^ \r\n]/.test(t.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(t.value))}i(Cr,"formatCodeAsIndented");function sd(t){let e=t.options.fence||"`";if(e!=="`"&&e!=="~")throw new Error("Cannot serialize code with `"+e+"` for `options.fence`, expected `` ` `` or `~`");return e}i(sd,"checkFence");function ad(t,e,n,r){let o=sd(n),s=t.value||"",a=o==="`"?"GraveAccent":"Tilde";if(Cr(t,n)){let p=n.enter("codeIndented"),h=n.indentLines(s,Sg);return p(),h}let l=n.createTracker(r),c=o.repeat(Math.max(od(s,o)+1,3)),u=n.enter("codeFenced"),d=l.move(c);if(t.lang){let p=n.enter(`codeFencedLang${a}`);d+=l.move(n.safe(t.lang,{before:d,after:" ",encode:["`"],...l.current()})),p()}if(t.lang&&t.meta){let p=n.enter(`codeFencedMeta${a}`);d+=l.move(" "),d+=l.move(n.safe(t.meta,{before:d,after:` +`,encode:["`"],...l.current()})),p()}return d+=l.move(` +`),s&&(d+=l.move(s+` +`)),d+=l.move(c),u(),d}i(ad,"code");function Sg(t,e,n){return(n?"":" ")+t}i(Sg,"map");function Rn(t){let e=t.options.quote||'"';if(e!=='"'&&e!=="'")throw new Error("Cannot serialize title with `"+e+"` for `options.quote`, expected `\"`, or `'`");return e}i(Rn,"checkQuote");function ld(t,e,n,r){let o=Rn(n),s=o==='"'?"Quote":"Apostrophe",a=n.enter("definition"),l=n.enter("label"),c=n.createTracker(r),u=c.move("[");return u+=c.move(n.safe(n.associationId(t),{before:u,after:"]",...c.current()})),u+=c.move("]: "),l(),!t.url||/[\0- \u007F]/.test(t.url)?(l=n.enter("destinationLiteral"),u+=c.move("<"),u+=c.move(n.safe(t.url,{before:u,after:">",...c.current()})),u+=c.move(">")):(l=n.enter("destinationRaw"),u+=c.move(n.safe(t.url,{before:u,after:t.title?" ":` +`,...c.current()}))),l(),t.title&&(l=n.enter(`title${s}`),u+=c.move(" "+o),u+=c.move(n.safe(t.title,{before:u,after:o,...c.current()})),u+=c.move(o),l()),a(),u}i(ld,"definition");function cd(t){let e=t.options.emphasis||"*";if(e!=="*"&&e!=="_")throw new Error("Cannot serialize emphasis with `"+e+"` for `options.emphasis`, expected `*`, or `_`");return e}i(cd,"checkEmphasis");function He(t){return"&#x"+t.toString(16).toUpperCase()+";"}i(He,"encodeCharacterReference");function Dn(t,e,n){let r=Ln(t),o=Ln(e);return r===void 0?o===void 0?n==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:o===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:r===1?o===void 0?{inside:!1,outside:!1}:o===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:o===void 0?{inside:!1,outside:!1}:o===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}i(Dn,"encodeInfo");fa.peek=Pg;function fa(t,e,n,r){let o=cd(n),s=n.enter("emphasis"),a=n.createTracker(r),l=a.move(o),c=a.move(n.containerPhrasing(t,{after:o,before:l,...a.current()})),u=c.charCodeAt(0),d=Dn(r.before.charCodeAt(r.before.length-1),u,o);d.inside&&(c=He(u)+c.slice(1));let p=c.charCodeAt(c.length-1),h=Dn(r.after.charCodeAt(0),p,o);h.inside&&(c=c.slice(0,-1)+He(p));let f=a.move(o);return s(),n.attentionEncodeSurroundingInfo={after:h.outside,before:d.outside},l+c+f}i(fa,"emphasis");function Pg(t,e,n){return n.options.emphasis||"*"}i(Pg,"emphasisPeek");var Bn=i((function(t){if(t==null)return Mg;if(typeof t=="function")return Ni(t);if(typeof t=="object")return Array.isArray(t)?Tg(t):Fg(t);if(typeof t=="string")return Ig(t);throw new Error("Expected function, string, or object as test")}),"convert");function Tg(t){let e=[],n=-1;for(;++n":""))+")"})}return h;function h(){let f=dd,b,k,y;if((!e||s(c,u,d[d.length-1]||void 0))&&(f=Ng(n(c,d)),f[0]===Zt))return f;if("children"in c&&c.children){let w=c;if(w.children&&f[0]!==Ri)for(k=(r?w.children.length:-1)+a,y=d.concat(w);k>-1&&k",...c.current()})),u+=c.move(">")):(l=n.enter("destinationRaw"),u+=c.move(n.safe(t.url,{before:u,after:t.title?" ":")",...c.current()}))),l(),t.title&&(l=n.enter(`title${s}`),u+=c.move(" "+o),u+=c.move(n.safe(t.title,{before:u,after:o,...c.current()})),u+=c.move(o),l()),u+=c.move(")"),a(),u}i(ba,"image");function Rg(){return"!"}i(Rg,"imagePeek");wa.peek=Dg;function wa(t,e,n,r){let o=t.referenceType,s=n.enter("imageReference"),a=n.enter("label"),l=n.createTracker(r),c=l.move("!["),u=n.safe(t.alt,{before:c,after:"]",...l.current()});c+=l.move(u+"]["),a();let d=n.stack;n.stack=[],a=n.enter("reference");let p=n.safe(n.associationId(t),{before:c,after:"]",...l.current()});return a(),n.stack=d,s(),o==="full"||!u||u!==p?c+=l.move(p+"]"):o==="shortcut"?c=c.slice(0,-1):c+=l.move("]"),c}i(wa,"imageReference");function Dg(){return"!"}i(Dg,"imageReferencePeek");ya.peek=Bg;function ya(t,e,n){let r=t.value||"",o="`",s=-1;for(;new RegExp("(^|[^`])"+o+"([^`]|$)").test(r);)o+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++s\u007F]/.test(t.url))}i(ka,"formatLinkAsAutolink");Ca.peek=_g;function Ca(t,e,n,r){let o=Rn(n),s=o==='"'?"Quote":"Apostrophe",a=n.createTracker(r),l,c;if(ka(t,n)){let d=n.stack;n.stack=[],l=n.enter("autolink");let p=a.move("<");return p+=a.move(n.containerPhrasing(t,{before:p,after:">",...a.current()})),p+=a.move(">"),l(),n.stack=d,p}l=n.enter("link"),c=n.enter("label");let u=a.move("[");return u+=a.move(n.containerPhrasing(t,{before:u,after:"](",...a.current()})),u+=a.move("]("),c(),!t.url&&t.title||/[\0- \u007F]/.test(t.url)?(c=n.enter("destinationLiteral"),u+=a.move("<"),u+=a.move(n.safe(t.url,{before:u,after:">",...a.current()})),u+=a.move(">")):(c=n.enter("destinationRaw"),u+=a.move(n.safe(t.url,{before:u,after:t.title?" ":")",...a.current()}))),c(),t.title&&(c=n.enter(`title${s}`),u+=a.move(" "+o),u+=a.move(n.safe(t.title,{before:u,after:o,...a.current()})),u+=a.move(o),c()),u+=a.move(")"),l(),u}i(Ca,"link");function _g(t,e,n){return ka(t,n)?"<":"["}i(_g,"linkPeek");Aa.peek=$g;function Aa(t,e,n,r){let o=t.referenceType,s=n.enter("linkReference"),a=n.enter("label"),l=n.createTracker(r),c=l.move("["),u=n.containerPhrasing(t,{before:c,after:"]",...l.current()});c+=l.move(u+"]["),a();let d=n.stack;n.stack=[],a=n.enter("reference");let p=n.safe(n.associationId(t),{before:c,after:"]",...l.current()});return a(),n.stack=d,s(),o==="full"||!u||u!==p?c+=l.move(p+"]"):o==="shortcut"?c=c.slice(0,-1):c+=l.move("]"),c}i(Aa,"linkReference");function $g(){return"["}i($g,"linkReferencePeek");function _n(t){let e=t.options.bullet||"*";if(e!=="*"&&e!=="+"&&e!=="-")throw new Error("Cannot serialize items with `"+e+"` for `options.bullet`, expected `*`, `+`, or `-`");return e}i(_n,"checkBullet");function hd(t){let e=_n(t),n=t.options.bulletOther;if(!n)return e==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===e)throw new Error("Expected `bullet` (`"+e+"`) and `bulletOther` (`"+n+"`) to be different");return n}i(hd,"checkBulletOther");function fd(t){let e=t.options.bulletOrdered||".";if(e!=="."&&e!==")")throw new Error("Cannot serialize items with `"+e+"` for `options.bulletOrdered`, expected `.` or `)`");return e}i(fd,"checkBulletOrdered");function Bi(t){let e=t.options.rule||"*";if(e!=="*"&&e!=="-"&&e!=="_")throw new Error("Cannot serialize rules with `"+e+"` for `options.rule`, expected `*`, `-`, or `_`");return e}i(Bi,"checkRule");function md(t,e,n,r){let o=n.enter("list"),s=n.bulletCurrent,a=t.ordered?fd(n):_n(n),l=t.ordered?a==="."?")":".":hd(n),c=e&&n.bulletLastUsed?a===n.bulletLastUsed:!1;if(!t.ordered){let d=t.children?t.children[0]:void 0;if((a==="*"||a==="-")&&d&&(!d.children||!d.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(c=!0),Bi(n)===a&&d){let p=-1;for(;++p-1?e.start:1)+(n.options.incrementListMarker===!1?0:e.children.indexOf(t))+s);let a=s.length+1;(o==="tab"||o==="mixed"&&(e&&e.type==="list"&&e.spread||t.spread))&&(a=Math.ceil(a/4)*4);let l=n.createTracker(r);l.move(s+" ".repeat(a-s.length)),l.shift(a);let c=n.enter("listItem"),u=n.indentLines(n.containerFlow(t,l.current()),d);return c(),u;function d(p,h,f){return h?(f?"":" ".repeat(a))+p:(f?s:s+" ".repeat(a-s.length))+p}i(d,"map")}i(bd,"listItem");function wd(t,e,n,r){let o=n.enter("paragraph"),s=n.enter("phrasing"),a=n.containerPhrasing(t,r);return s(),o(),a}i(wd,"paragraph");var xa=Bn(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function yd(t,e,n,r){return(t.children.some(function(a){return xa(a)})?n.containerPhrasing:n.containerFlow).call(n,t,r)}i(yd,"root");function kd(t){let e=t.options.strong||"*";if(e!=="*"&&e!=="_")throw new Error("Cannot serialize strong with `"+e+"` for `options.strong`, expected `*`, or `_`");return e}i(kd,"checkStrong");va.peek=zg;function va(t,e,n,r){let o=kd(n),s=n.enter("strong"),a=n.createTracker(r),l=a.move(o+o),c=a.move(n.containerPhrasing(t,{after:o,before:l,...a.current()})),u=c.charCodeAt(0),d=Dn(r.before.charCodeAt(r.before.length-1),u,o);d.inside&&(c=He(u)+c.slice(1));let p=c.charCodeAt(c.length-1),h=Dn(r.after.charCodeAt(0),p,o);h.inside&&(c=c.slice(0,-1)+He(p));let f=a.move(o+o);return s(),n.attentionEncodeSurroundingInfo={after:h.outside,before:d.outside},l+c+f}i(va,"strong");function zg(t,e,n){return n.options.strong||"*"}i(zg,"strongPeek");function Cd(t,e,n,r){return n.safe(t.value,r)}i(Cd,"text");function Ad(t){let e=t.options.ruleRepetition||3;if(e<3)throw new Error("Cannot serialize rules with repetition `"+e+"` for `options.ruleRepetition`, expected `3` or more");return e}i(Ad,"checkRuleRepetition");function xd(t,e,n){let r=(Bi(n)+(n.options.ruleSpaces?" ":"")).repeat(Ad(n));return n.options.ruleSpaces?r.slice(0,-1):r}i(xd,"thematicBreak");var vd={blockquote:rd,break:ha,code:ad,definition:ld,emphasis:fa,hardBreak:ha,heading:pd,html:ga,image:ba,imageReference:wa,inlineCode:ya,link:Ca,linkReference:Aa,list:md,listItem:bd,paragraph:wd,root:yd,strong:va,text:Cd,thematicBreak:xd};var Ed=[Vg];function Vg(t,e,n,r){if(e.type==="code"&&Cr(e,r)&&(t.type==="list"||t.type===e.type&&Cr(t,r)))return!1;if("spread"in n&&typeof n.spread=="boolean")return t.type==="paragraph"&&(t.type===e.type||e.type==="definition"||e.type==="heading"&&Di(e,r))?void 0:n.spread?1:0}i(Vg,"joinDefaults");var en=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"],Sd=[{character:" ",after:"[\\r\\n]",inConstruct:"phrasing"},{character:" ",before:"[\\r\\n]",inConstruct:"phrasing"},{character:" ",inConstruct:["codeFencedLangGraveAccent","codeFencedLangTilde"]},{character:"\r",inConstruct:["codeFencedLangGraveAccent","codeFencedLangTilde","codeFencedMetaGraveAccent","codeFencedMetaTilde","destinationLiteral","headingAtx"]},{character:` +`,inConstruct:["codeFencedLangGraveAccent","codeFencedLangTilde","codeFencedMetaGraveAccent","codeFencedMetaTilde","destinationLiteral","headingAtx"]},{character:" ",after:"[\\r\\n]",inConstruct:"phrasing"},{character:" ",before:"[\\r\\n]",inConstruct:"phrasing"},{character:" ",inConstruct:["codeFencedLangGraveAccent","codeFencedLangTilde"]},{character:"!",after:"\\[",inConstruct:"phrasing",notInConstruct:en},{character:'"',inConstruct:"titleQuote"},{atBreak:!0,character:"#"},{character:"#",inConstruct:"headingAtx",after:`(?:[\r +]|$)`},{character:"&",after:"[#A-Za-z]",inConstruct:"phrasing"},{character:"'",inConstruct:"titleApostrophe"},{character:"(",inConstruct:"destinationRaw"},{before:"\\]",character:"(",inConstruct:"phrasing",notInConstruct:en},{atBreak:!0,before:"\\d+",character:")"},{character:")",inConstruct:"destinationRaw"},{atBreak:!0,character:"*",after:`(?:[ \r +*])`},{character:"*",inConstruct:"phrasing",notInConstruct:en},{atBreak:!0,character:"+",after:`(?:[ \r +])`},{atBreak:!0,character:"-",after:`(?:[ \r +-])`},{atBreak:!0,before:"\\d+",character:".",after:`(?:[ \r +]|$)`},{atBreak:!0,character:"<",after:"[!/?A-Za-z]"},{character:"<",after:"[!/?A-Za-z]",inConstruct:"phrasing",notInConstruct:en},{character:"<",inConstruct:"destinationLiteral"},{atBreak:!0,character:"="},{atBreak:!0,character:">"},{character:">",inConstruct:"destinationLiteral"},{atBreak:!0,character:"["},{character:"[",inConstruct:"phrasing",notInConstruct:en},{character:"[",inConstruct:["label","reference"]},{character:"\\",after:"[\\r\\n]",inConstruct:"phrasing"},{character:"]",inConstruct:["label","reference"]},{atBreak:!0,character:"_"},{character:"_",inConstruct:"phrasing",notInConstruct:en},{atBreak:!0,character:"`"},{character:"`",inConstruct:["codeFencedLangGraveAccent","codeFencedMetaGraveAccent"]},{character:"`",inConstruct:"phrasing",notInConstruct:en},{atBreak:!0,character:"~"}];function Pd(t){return t.label||!t.identifier?t.label||"":Mi(t.identifier)}i(Pd,"association");function Td(t){if(!t._compiled){let e=(t.atBreak?"[\\r\\n][\\t ]*":"")+(t.before?"(?:"+t.before+")":"");t._compiled=new RegExp((e?"("+e+")":"")+(/[|\\{}()[\]^$+*?.-]/.test(t.character)?"\\":"")+t.character+(t.after?"(?:"+t.after+")":""),"g")}return t._compiled}i(Td,"compilePattern");function Fd(t,e,n){let r=e.indexStack,o=t.children||[],s=[],a=-1,l=n.before,c;r.push(-1);let u=e.createTracker(n);for(;++a0&&(l==="\r"||l===` +`)&&d.type==="html"&&(s[s.length-1]=s[s.length-1].replace(/(\r?\n|\r)$/," "),l=" ",u=e.createTracker(n),u.move(s.join("")));let h=e.handle(d,t,e,{...u.current(),after:p,before:l});c&&c===h.slice(0,1)&&(h=He(c.charCodeAt(0))+h.slice(1));let f=e.attentionEncodeSurroundingInfo;e.attentionEncodeSurroundingInfo=void 0,c=void 0,f&&(s.length>0&&f.before&&l===s[s.length-1].slice(-1)&&(s[s.length-1]=s[s.length-1].slice(0,-1)+He(l.charCodeAt(0))),f.after&&(c=p)),u.move(h),s.push(h),l=h.slice(-1)}return r.pop(),s.join("")}i(Fd,"containerPhrasing");function Id(t,e,n){let r=e.indexStack,o=t.children||[],s=e.createTracker(n),a=[],l=-1;for(r.push(-1);++l + +`}return` + +`}i(Ug,"between");var Wg=/\r?\n|\r/g;function Md(t,e){let n=[],r=0,o=0,s;for(;s=Wg.exec(t);)a(t.slice(r,s.index)),n.push(s[0]),r=s.index+s[0].length,o++;return a(t.slice(r)),n.join("");function a(l){n.push(e(l,o,!l))}i(a,"one")}i(Md,"indentLines");function Nd(t,e,n){let r=(n.before||"")+(e||"")+(n.after||""),o=[],s=[],a={},l=-1;for(;++l=u||d+1a.length,c;l&&a.push(o);try{c=t.apply(this,a)}catch(u){let d=u;if(l&&n)throw d;return o(d)}l||(c&&c.then&&typeof c.then=="function"?c.then(s,o):c instanceof Error?o(c):s(c))}function o(a,...l){n||(n=!0,e(a,...l))}function s(a){o(null,a)}}i(Hd,"wrap");var ce=class extends Error{static{i(this,"VFileMessage")}constructor(e,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let o="",s={},a=!1;if(n&&("line"in n&&"column"in n?s={place:n}:"start"in n&&"end"in n?s={place:n}:"type"in n?s={ancestors:[n],place:n.position}:s={...n}),typeof e=="string"?o=e:!s.cause&&e&&(a=!0,o=e.message,s.cause=e),!s.ruleId&&!s.source&&typeof r=="string"){let c=r.indexOf(":");c===-1?s.ruleId=r:(s.source=r.slice(0,c),s.ruleId=r.slice(c+1))}if(!s.place&&s.ancestors&&s.ancestors){let c=s.ancestors[s.ancestors.length-1];c&&(s.place=c.position)}let l=s.place&&"start"in s.place?s.place.start:s.place;this.ancestors=s.ancestors||void 0,this.cause=s.cause||void 0,this.column=l?l.column:void 0,this.fatal=void 0,this.file="",this.message=o,this.line=l?l.line:void 0,this.name=Ot(s.place)||"1:1",this.place=s.place||void 0,this.reason=this.message,this.ruleId=s.ruleId||void 0,this.source=s.source||void 0,this.stack=a&&s.cause&&typeof s.cause.stack=="string"?s.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}};ce.prototype.file="";ce.prototype.name="";ce.prototype.reason="";ce.prototype.message="";ce.prototype.stack="";ce.prototype.column=void 0;ce.prototype.line=void 0;ce.prototype.ancestors=void 0;ce.prototype.cause=void 0;ce.prototype.fatal=void 0;ce.prototype.place=void 0;ce.prototype.ruleId=void 0;ce.prototype.source=void 0;var Qe=hn(require("node:path"),1);var Ta=hn(require("node:process"),1);var Fa=require("node:url");function zi(t){return!!(t!==null&&typeof t=="object"&&"href"in t&&t.href&&"protocol"in t&&t.protocol&&t.auth===void 0)}i(zi,"isUrl");var Ia=["history","path","basename","stem","extname","dirname"],vr=class{static{i(this,"VFile")}constructor(e){let n;e?zi(e)?n={path:e}:typeof e=="string"||Qg(e)?n={value:e}:n=e:n={},this.cwd="cwd"in n?"":Ta.default.cwd(),this.data={},this.history=[],this.messages=[],this.value,this.map,this.result,this.stored;let r=-1;for(;++r0){let[f,...b]=d,k=r[h][1];xr(k)&&xr(f)&&(f=(0,Ui.default)(!0,k,f)),r[h]=[u,f,...b]}}}},Ba=new Da().freeze();function Na(t,e){if(typeof e!="function")throw new TypeError("Cannot `"+t+"` without `parser`")}i(Na,"assertParser");function Oa(t,e){if(typeof e!="function")throw new TypeError("Cannot `"+t+"` without `compiler`")}i(Oa,"assertCompiler");function Ra(t,e){if(e)throw new Error("Cannot call `"+t+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}i(Ra,"assertUnfrozen");function qd(t){if(!xr(t)||typeof t.type!="string")throw new TypeError("Expected node, got `"+t+"`")}i(qd,"assertNode");function Gd(t,e,n){if(!n)throw new Error("`"+t+"` finished async. Use `"+e+"` instead")}i(Gd,"assertDone");function Vi(t){return Zg(t)?t:new vr(t)}i(Vi,"vfile");function Zg(t){return!!(t&&typeof t=="object"&&"message"in t&&"messages"in t)}i(Zg,"looksLikeAVFile");function eb(t){return typeof t=="string"||tb(t)}i(eb,"looksLikeAValue");function tb(t){return!!(t&&typeof t=="object"&&"byteLength"in t&&"byteOffset"in t)}i(tb,"isUint8Array");var Yd=Ba().use(On).use(_i).freeze();var $a={d:i((t,e)=>{for(var n in e)$a.o(e,n)&&!$a.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},"d"),o:i((t,e)=>Object.prototype.hasOwnProperty.call(t,e),"o")},za={};$a.d(za,{Z:i(()=>ob,"Z"),$:i(()=>Zd,"$")});var $n={horizontalTab:-2,virtualSpace:-1,nul:0,eof:null,space:32};function Jd(t){return t<$n.nul||t===$n.space}i(Jd,"n");function _a(t){return t<$n.horizontalTab}i(_a,"i");var nb={553:t=>{t.exports=function(e){var n,r;return e._compiled||(n=e.before?"(?:"+e.before+")":"",r=e.after?"(?:"+e.after+")":"",e.atBreak&&(n="[\\r\\n][\\t ]*"+n),e._compiled=new RegExp((n?"("+n+")":"")+(/[|\\{}()[\]^$+*?.-]/.test(e.character)?"\\":"")+e.character+(r||""),"g")),e._compiled}},112:t=>{function e(n,r,o){var s;if(!r)return o;for(typeof r=="string"&&(r=[r]),s=-1;++s{t.exports=function(l,c,u){for(var d,p,h,f,b,k,y,w,A=(u.before||"")+(c||"")+(u.after||""),v=[],P=[],I={},C=-1;++C=w||h+1{var e=t&&t.__esModule?()=>t.default:()=>t;return yt.d(e,{a:e}),e},yt.d=(t,e)=>{for(var n in e)yt.o(e,n)&&!yt.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},yt.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var Va={};(()=>{function t(o={}){let s=o.permalinks||[],a=o.pageResolver||(h=>[h.replace(/ /g,"_").toLowerCase()]),l=o.newClassName||"new",c=o.wikiLinkClassName||"internal",u=o.hrefTemplate||(h=>`#/page/${h}`),d;function p(h){return h[h.length-1]}return i(p,"s"),{enter:{wikiLink:i(function(h){d={type:"wikiLink",value:null,data:{alias:null,permalink:null,exists:null}},this.enter(d,h)},"wikiLink")},exit:{wikiLinkTarget:i(function(h){let f=this.sliceSerialize(h);p(this.stack).value=f},"wikiLinkTarget"),wikiLinkAlias:i(function(h){let f=this.sliceSerialize(h);p(this.stack).data.alias=f},"wikiLinkAlias"),wikiLink:i(function(h){this.exit(h);let f=d,b=a(f.value),k=b.find((P=>s.indexOf(P)!==-1)),y=k!==void 0,w;w=y?k:b[0]||"";let A=f.value;f.data.alias&&(A=f.data.alias);let v=c;y||(v+=" "+l),f.data.alias=A,f.data.permalink=w,f.data.exists=y,f.data.hName="a",f.data.hProperties={className:v,href:u(w)},f.data.hChildren=[{type:"text",value:A}]},"wikiLink")}}}i(t,"e"),yt.d(Va,{V:i(()=>t,"V"),x:i(()=>r,"x")});var e=yt(113),n=yt.n(e);function r(o={}){let s=o.aliasDivider||":";return{unsafe:[{character:"[",inConstruct:["phrasing","label","reference"]},{character:"]",inConstruct:["label","reference"]}],handlers:{wikiLink:i(function(a,l,c){let u=c.enter("wikiLink"),d=n()(c,a.value,{before:"[",after:"]"}),p=n()(c,a.data.alias,{before:"[",after:"]"}),h;return h=p!==d?`[[${d}${s}${p}]]`:`[[${d}]]`,u(),h},"wikiLink")}}}i(r,"n")})();var rb=Va.V,ib=Va.x,Xd=!1;function Zd(t={}){let e=this.data();function n(r,o){e[r]?e[r].push(o):e[r]=[o]}i(n,"a"),!Xd&&(this.Parser&&this.Parser.prototype&&this.Parser.prototype.blockTokenizers||this.Compiler&&this.Compiler.prototype&&this.Compiler.prototype.visitors)&&(Xd=!0,console.warn("[remark-wiki-link] Warning: please upgrade to remark 13 to use this plugin")),n("micromarkExtensions",(function(){var r=(arguments.length>0&&arguments[0]!==void 0?arguments[0]:{}).aliasDivider||":",o="]]";return{text:{91:{tokenize:i(function(s,a,l){var c,u,d=0,p=0,h=0;return function(A){return A!=="[[".charCodeAt(p)?l(A):(s.enter("wikiLink"),s.enter("wikiLinkMarker"),f(A))};function f(A){return p===2?(s.exit("wikiLinkMarker"),(function(v){return _a(v)||v===$n.eof?l(v):(s.enter("wikiLinkData"),s.enter("wikiLinkTarget"),b(v))})(A)):A!=="[[".charCodeAt(p)?l(A):(s.consume(A),p++,f)}function b(A){return A===r.charCodeAt(d)?c?(s.exit("wikiLinkTarget"),s.enter("wikiLinkAliasMarker"),k(A)):l(A):A===o.charCodeAt(h)?c?(s.exit("wikiLinkTarget"),s.exit("wikiLinkData"),s.enter("wikiLinkMarker"),w(A)):l(A):_a(A)||A===$n.eof?l(A):(Jd(A)||(c=!0),s.consume(A),b)}function k(A){return d===r.length?(s.exit("wikiLinkAliasMarker"),s.enter("wikiLinkAlias"),y(A)):A!==r.charCodeAt(d)?l(A):(s.consume(A),d++,k)}function y(A){return A===o.charCodeAt(h)?u?(s.exit("wikiLinkAlias"),s.exit("wikiLinkData"),s.enter("wikiLinkMarker"),w(A)):l(A):_a(A)||A===$n.eof?l(A):(Jd(A)||(u=!0),s.consume(A),y)}function w(A){return h===2?(s.exit("wikiLinkMarker"),s.exit("wikiLink"),a(A)):A!==o.charCodeAt(h)?l(A):(s.consume(A),h++,w)}},"tokenize")}}}})(t)),n("fromMarkdownExtensions",rb(t)),n("toMarkdownExtensions",ib(t))}i(Zd,"k");var ob=Zd,uT=za.Z,ep=za.$;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var sb=/^[A-Za-z][A-Za-z0-9+\-.]*:\S+$/;function Ua(t){if(/\s/.test(t))return!1;if(t.includes("://"))try{return new URL(t),!0}catch{return!1}return sb.test(t)}i(Ua,"isUrl");var tn=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Wi(t){let e=(0,tn.getFrontMatterInfo)(t);return(0,tn.parseYaml)(e.frontmatter)??{}}i(Wi,"parseFrontmatter");function tp(t,e){let n=(0,tn.getFrontMatterInfo)(t);if(Object.keys(e).length===0)return t.slice(n.contentStart);let r=(0,tn.stringifyYaml)(e);return n.exists?dc(t,r,n.from,n.to):`--- +${r}--- +${t}`}i(tp,"setFrontmatter");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function De(t){if(!Ee(t))return!1;let e=t;return e.startOffset!==void 0&&e.endOffset!==void 0}i(De,"isFrontmatterLinkCacheWithOffsets");function Hi(t){return De(t)?t:{...t,endOffset:t.original.length,startOffset:0}}i(Hi,"toFrontmatterLinkCacheWithOffsets");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function np(t){return Wa(t)&&t.type==="file"}i(np,"isCanvasFileNodeReference");function Wa(t){return Ee(t)&&!!t.isCanvas}i(Wa,"isCanvasReference");function nn(t,e){return De(t)?{newContent:e,oldContent:t.original.slice(t.startOffset,t.endOffset),reference:t}:{newContent:e,oldContent:t.original,reference:t}}i(nn,"referenceToFileChange");function rp(t){return t.sort((e,n)=>{if(Ee(e)&&Ee(n)){let r=De(e)?e.startOffset:0,o=De(n)?n.startOffset:0;return e.key.localeCompare(n.key)||Number(De(n))-Number(De(e))||r-o}return tt(e)&&tt(n)?e.position.start.offset-n.position.start.offset:Ee(e)?1:-1})}i(rp,"sortReferences");var Sr=require("obsidian");var Er=require("@codemirror/state"),Ha=require("@codemirror/view");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ip=new WeakMap;function ja(t){let e=sp(t);t.cm.dispatch({effects:e.reconfigure([Er.EditorState.readOnly.of(!0),Ha.EditorView.editable.of(!1)])})}i(ja,"lockEditor");function op(t){let e=sp(t);t.cm.dispatch({effects:e.reconfigure([Er.EditorState.readOnly.of(!1),Ha.EditorView.editable.of(!0)])})}i(op,"unlockEditor");function sp(t){let e=ip.get(t);return e||(e=new Er.Compartment,ip.set(t,e)),e}i(sp,"ensureCompartment");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function zn(t,e,n){let r=ae(t,e);if(r.path===n)return n;let o=qe(n);await Vn(t,o);let s=ji(t,n);try{await t.vault.copy(r,s)}catch(a){if(!await t.vault.exists(s))throw a}return s}i(zn,"copySafe");async function Vn(t,e){if(await t.vault.adapter.exists(e))return!1;try{return await t.vault.createFolder(e),!0}catch(n){if(!await t.vault.exists(e))throw n;return!0}}i(Vn,"createFolderSafe");async function Ka(t,e){let n=st(t,e);n&&await Ki(t,n)&&await Tt(t,n)}i(Ka,"deleteEmptyFolder");async function Pr(t,e){let n=st(t,e);for(;n;){if(!await Ki(t,n))return;let r=n.parent;await Ka(t,n),n=r}}i(Pr,"deleteEmptyFolderHierarchy");function ji(t,e){let n=it(e);return t.vault.getAvailablePath(oe(K(e),Ne(e,n)),n.slice(1))}i(ji,"getAvailablePath");function Un(t){return t.vault.getMarkdownFiles().sort((e,n)=>e.path.localeCompare(n.path))}i(Un,"getMarkdownFilesSorted");function qa(t,e,n){let r=G(t,e);if(t.vault.adapter.insensitive){let o=K(n),s=Ne(n),a;for(;a=st(t,o,!0),!a;)s=oe(Ne(o),s),o=K(o);n=oe(a.getParentPrefix(),s)}return r.toLowerCase()===n.toLowerCase()?n:ji(t,n)}i(qa,"getSafeRenamePath");async function Ki(t,e){let n=await Wn(t,G(t,e));return n.files.length===0&&n.folders.length===0}i(Ki,"isEmptyFolder");async function Wn(t,e){let n=G(t,e),r={files:[],folders:[]};if((await t.vault.adapter.stat(n))?.type!=="folder")return r;try{return await t.vault.adapter.list(n)}catch(o){if(await t.vault.exists(n))throw o;return r}}i(Wn,"listSafe");async function ap(t,e,n,r={}){let s={...{shouldFailOnMissingFile:!0,shouldLockEditorWhileProcessing:!0,shouldShowTimeoutNotice:!0,timeoutInMilliseconds:500},...r},a=new AbortController;s.abortSignal=nt(s.abortSignal,a.signal);let l=G(t,e),c=null;if(s.shouldLockEditorWhileProcessing){for(let u of t.workspace.getLeavesOfType(Br.Markdown))u.view instanceof Sr.MarkdownView&&u.view.file?.path===l&&ja(u.view.editor);c=t.workspace.on("active-leaf-change",u=>{u?.view instanceof Sr.MarkdownView&&u.view.file?.path===l&&ja(u.view.editor)})}try{await yi({async operationFn(u){u.throwIfAborted();let d=await Ga(t,e);if(u.throwIfAborted(),d===null)return b();let p=await gn(n,u,d);if(u.throwIfAborted(),p===null)return!1;let h=!0;if(!await lp(t,e,async k=>{u.throwIfAborted(),await t.vault.process(k,y=>(u.throwIfAborted(),y!==d?(Y("Vault:process")("Content has changed since it was read. Retrying...",{actualContent:y,expectedContent:d,path:k.path}),h=!1,y):p)),u.throwIfAborted()}))return b();return h;function b(){if(s.shouldFailOnMissingFile)throw new Error(`File '${l}' not found`);return!0}},operationName:E(u=>u.obsidianDevUtils.vault.processFile,{filePath:l}),retryOptions:s,shouldShowTimeoutNotice:s.shouldShowTimeoutNotice})}finally{c?.e.offref(c);for(let u of t.workspace.getLeavesOfType(Br.Markdown))u.view instanceof Sr.MarkdownView&&u.view.file?.path===l&&op(u.view.editor)}}i(ap,"process");async function Ga(t,e){let n=null;return await lp(t,e,async r=>{await qi(t,r),n=await t.vault.read(r)}),n}i(Ga,"readSafe");async function Hn(t,e,n){let r=mc(t,e),o=qa(t,e,n);if(r.path.toLowerCase()===o.toLowerCase())return r.path!==n&&await t.fileManager.renameFile(r,o),o;let s=qe(o);await Vn(t,s);try{await t.fileManager.renameFile(r,o)}catch(a){if(!await t.vault.exists(o)||await t.vault.exists(r.path))throw a}return o}i(Hn,"renameSafe");async function qi(t,e){if(!Ye(t,e))return;let n=G(t,e);for(let r of t.workspace.getLeavesOfType(Br.Markdown))r.view instanceof Sr.MarkdownView&&r.view.file?.path===n&&r.view.dirty&&await r.view.save()}i(qi,"saveNote");async function Tt(t,e){let n=ft(t,e);if(n)try{await t.fileManager.trashFile(n)}catch(r){if(await t.vault.exists(n.path))throw r;Y("Vault:trashSafe")(`An error occurred while trashing ${n.path}, but the file no longer exists.`,{error:r,path:n.path})}}i(Tt,"trashSafe");async function lp(t,e,n){let r=G(t,e),o=X(t,r);if(!o||o.deleted)return!1;try{return await n(o),!0}catch(s){if(o=X(t,r),!o||o.deleted)return!1;throw s}}i(lp,"invokeFileActionSafe");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function Ji(t,e,n,r,o=!0){t.throwIfAborted();let s=await gn(r,t,e);if(t.throwIfAborted(),s===null)return null;let{frontmatter:a,hasFrontmatterError:l}=fb(e,n);if(!bb(s,e,a,n))return o?null:e;s=gb(s);let{frontmatterChanged:c,newContent:u}=db(s,e,l,n);return await pb(t,a,c,n),t.throwIfAborted(),hb(u,a,c)}i(Ji,"applyContentChanges");async function Tr(t,e,n,r={},o=!0){await ap(t,e,async(s,a)=>St(t,e)?await ub(s,a,G(t,e),n,o):await Ji(s,a,G(t,e),n,o),r)}i(Tr,"applyFileChanges");function Fr(t){return Wa(t.reference)}i(Fr,"isCanvasChange");function ab(t){return Fr(t)&&t.reference.type==="file"}i(ab,"isCanvasFileNodeChange");function lb(t){return Fr(t)&&t.reference.type==="text"}i(lb,"isCanvasTextNodeChange");function rn(t){return tt(t.reference)}i(rn,"isContentChange");function Gi(t){return Ee(t.reference)}i(Gi,"isFrontmatterChange");function Yi(t){return De(t.reference)}i(Yi,"isFrontmatterChangeWithOffsets");function cb(t){return Yi(t)?t:{...t,reference:Hi(t.reference)}}i(cb,"toFrontmatterChangeWithOffsets");async function ub(t,e,n,r,o=!0){let s=await gn(r,t,e);if(t.throwIfAborted(),s===null)return null;let a=mb(e),l=new Map;for(let c of s){if(!Fr(c)){console.error("Only canvas changes are supported for canvas files",{change:c,path:n});continue}let u=a.nodes[c.reference.nodeIndex];if(!u)return console.error("Node not found",{nodeIndex:c.reference.nodeIndex,path:n}),null;if(ab(c)){if(u.file!==c.oldContent)return Y("FileChange:applyCanvasChanges")("Content mismatch",{actualContent:u.file,expectedContent:c.oldContent,nodeIndex:c.reference.nodeIndex,path:n,type:"file"}),null;u.file=c.newContent}else if(lb(c)){let d=l.get(c.reference.nodeIndex);d||(d=[],l.set(c.reference.nodeIndex,d)),d.push(c)}}for(let[c,u]of l.entries()){let d=a.nodes[c];if(!d)return console.error("Node not found",{nodeIndex:c,path:n}),null;if(typeof d.text!="string")return console.error("Node text is not a string",{nodeIndex:c,path:n}),null;let p=u.map(h=>nn(h.reference.originalReference,h.newContent));d.text=await Ji(t,d.text,`${n}.node${String(c)}.VIRTUAL_FILE.md`,p,o)}return JSON.stringify(a,null," ")}i(ub,"applyCanvasChanges");function db(t,e,n,r){let o="",s=0,a={newContent:"",oldContent:"",reference:{link:"",original:"",position:{end:{col:0,line:0,offset:0},start:{col:0,line:0,offset:0}}}},l=new Map;for(let c of t)if(rn(c))if(s<=c.reference.position.start.offset)o+=e.slice(s,c.reference.position.start.offset),o+=c.newContent,s=c.reference.position.end.offset,a=c;else{let u=c.reference.position.start.offset-a.reference.position.start.offset,d=c.reference.position.end.offset-a.reference.position.start.offset;if(a.newContent.slice(u,d)!==c.oldContent){let h="Overlapping changes";throw console.error(h,{change:c,lastContentChange:a}),new Error(h)}o=o.slice(0,o.length-a.newContent.length)+a.newContent.slice(0,u)+c.newContent+a.newContent.slice(d)}else if(Gi(c))if(n)console.error(`Cannot apply frontmatter change in ${r}, because frontmatter parsing failed`,{change:c});else{let u=l.get(c.reference.key);u||(u=[],l.set(c.reference.key,u)),u.push(cb(c))}return o+=e.slice(s),{frontmatterChanged:l,newContent:o}}i(db,"applyContentChangesToText");async function pb(t,e,n,r){for(let[o,s]of n.entries()){let a=En(e,o);if(typeof a!="string")return;let l=s.map(u=>({newContent:u.newContent,oldContent:u.oldContent,reference:{link:"",original:"",position:{end:{col:u.reference.endOffset,line:0,offset:u.reference.endOffset},start:{col:u.reference.startOffset,line:0,offset:u.reference.startOffset}}}})),c=await Ji(t,a,`${r}.frontmatter.${o}.VIRTUAL_FILE.md`,l);if(c===null)return;$c(e,o,c)}}i(pb,"applyFrontmatterChangesWithOffsets");function hb(t,e,n){return n.size>0?tp(t,e):t}i(hb,"buildFinalContent");function fb(t,e){let n={},r=!1;try{n=Wi(t)}catch(o){Wt(new Error(`Frontmatter parsing failed in ${e}`,{cause:o})),r=!0}return{frontmatter:n,hasFrontmatterError:r}}i(fb,"parseFrontmatterSafely");function mb(t){let e;try{e=JSON.parse(t)}catch{e=null}return(e===null||typeof e!="object")&&(e={}),e}i(mb,"parseJsonSafe");function gb(t){return t.sort((e,n)=>rn(e)&&rn(n)?e.reference.position.start.offset-n.reference.position.start.offset:Yi(e)&&Yi(n)?e.reference.key.localeCompare(n.reference.key)||e.reference.startOffset-n.reference.startOffset:Gi(e)&&Gi(n)?e.reference.key.localeCompare(n.reference.key):rn(e)?-1:1),t.filter((e,n)=>e.oldContent===e.newContent?!1:n===0?!0:!Je(e,t[n-1]))}i(gb,"sortAndFilterChanges");function bb(t,e,n,r){let o=Y("FileChange:validateChanges");for(let s of t)if(rn(s)){let a=s.reference.position.start.offset,l=s.reference.position.end.offset,c=e.slice(a,l);if(c!==s.oldContent)return o("Content mismatch",{actualContent:c,endOffset:l,expectedContent:s.oldContent,path:r,startOffset:a}),!1}else if(Yi(s)){let a=En(n,s.reference.key);if(typeof a!="string")return o("Property value is not a string",{frontmatterKey:s.reference.key,path:r,propertyValue:a}),!1;let l=a.slice(s.reference.startOffset,s.reference.endOffset);if(l!==s.oldContent)return o("Content mismatch",{actualContent:l,expectedContent:s.oldContent,frontmatterKey:s.reference.key,path:r,startOffset:s.reference.startOffset}),!1}else if(Gi(s)){let a=En(n,s.reference.key);if(a!==s.oldContent)return o("Content mismatch",{actualContent:a,expectedContent:s.oldContent,frontmatterKey:s.reference.key,path:r}),!1}return!0}i(bb,"validateChanges");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function cp(t){await new Promise(e=>{t.metadataCache.onCleanCache(e)})}i(cp,"ensureMetadataCacheReady");function je(t){let e=[];return t.links&&e.push(...t.links),t.embeds&&e.push(...t.embeds),t.frontmatterLinks&&e.push(...t.frontmatterLinks),rp(e),e=e.filter((n,r)=>{if(r===0)return!0;let o=ee(e[r-1]);if(tt(n)&&tt(o))return n.position.start.offset!==o.position.start.offset;if(Ee(n)&&Ee(o)){let s=De(n)?n.startOffset:0,a=De(o)?o.startOffset:0;return n.key!==o.key||De(n)!==De(o)||s!==a}return!0}),e}i(je,"getAllLinks");function Ya(t,e){let n=ae(t,e,!0);return Ir(t,[n],()=>t.metadataCache.getBacklinksForFile(n))}i(Ya,"getBacklinksForFileOrPath");async function Be(t,e,n={}){let r=t.metadataCache.getBacklinksForFile.safe;if(r)return r(e);let o=new Gl;return await yi({async operationFn(s){s.throwIfAborted();let a=ae(t,e);await cp(t),s.throwIfAborted(),o=Ya(t,a);for(let l of o.keys()){s.throwIfAborted();let c=X(t,l);if(!c)return!1;await qi(t,c),s.throwIfAborted();let u=await Ga(t,c);if(s.throwIfAborted(),!u)return!1;let d=Wi(u),p=o.get(l);if(!p)return!1;for(let h of p){let f;if(tt(h))f=u.slice(h.position.start.offset,h.position.end.offset);else if(Ee(h)){let b=En(d,h.key);if(typeof b!="string")return!1;let k=Hi(h);f=b.slice(k.startOffset,k.endOffset)}else return!0;if(f!==h.original)return!1}}return!0},operationName:E(s=>s.obsidianDevUtils.metadataCache.getBacklinksForFilePath,{filePath:G(t,e)}),retryOptions:n,shouldShowTimeoutNotice:n.shouldShowTimeoutNotice??!0}),o}i(Be,"getBacklinksForFileSafe");async function Xe(t,e){let n=X(t,e);try{if(!n)return null;if(n.deleted)return t.metadataCache.getFileCache(n);await qi(t,n);let r=t.metadataCache.fileCache[n.path];return r?.mtime===n.stat.mtime&&r.size===n.stat.size&&t.metadataCache.metadataCache[r.hash]||(await t.metadataCache.computeFileMetadataAsync(n),await cp(t)),t.metadataCache.getFileCache(n)}catch(r){if(!n||n.deleted)return null;throw r}}i(Xe,"getCacheSafe");function up(t,e,n){let r=ae(t,e,!0);if(!r.deleted)throw new Error("File is existing");t.metadataCache.fileCache[r.path]={hash:r.path,mtime:0,size:0},t.metadataCache.metadataCache[r.path]=n}i(up,"registerFileCacheForNonExistingFile");function dp(t,e){let n=mp(t);for(let r of e)for(;r.deleted;){let o=n.get(r.path)??0;o++,n.set(r.path,o),t.vault.fileMap[r.path]=r,Z(r)&&t.metadataCache.uniqueFileLookup.add(r.name.toLowerCase(),r),r=wn(t,qe(r.path),!0)}}i(dp,"registerFiles");function Ir(t,e,n){try{return dp(t,e),n()}finally{fp(t,e)}}i(Ir,"tempRegisterFilesAndRun");async function pp(t,e,n){try{return dp(t,e),await n()}finally{fp(t,e)}}i(pp,"tempRegisterFilesAndRunAsync");function hp(t,e){let n=ae(t,e,!0);if(!n.deleted)throw new Error("File is existing");delete t.metadataCache.fileCache[n.path],delete t.metadataCache.metadataCache[n.path]}i(hp,"unregisterFileCacheForNonExistingFile");function fp(t,e){let n=mp(t);for(let r of e)for(;r.deleted;){let o=n.get(r.path)??1;o--,n.set(r.path,o),o===0&&(n.delete(r.path),delete t.vault.fileMap[r.path],Z(r)&&t.metadataCache.uniqueFileLookup.remove(r.name.toLowerCase(),r)),r=wn(t,qe(r.path),!0)}}i(fp,"unregisterFiles");function mp(t){return Te(t,"registeredFilesCounts",new Map).value}i(mp,"getRegisteredFilesCounts");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function gp(t){return t.vault.getConfig("newLinkFormat")}i(gp,"getNewLinkFormat");function Ja(t){return!t.vault.getConfig("useMarkdownLinks")}i(Ja,"shouldUseWikilinks");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var wb="\\|",yb=/[\\\x00\x08\x0B\x0C\x0E-\x1F ]/g,kb=/[\\[\]<>_*~=`$]/g,wp=/(?(t.AbsolutePathInVault="AbsolutePathInVault",t.ObsidianSettingsDefault="ObsidianSettingsDefault",t.RelativePathToTheSource="RelativePathToTheSource",t.ShortestPathWhenPossible="ShortestPathWhenPossible",t))(Qi||{}),Xa=(t=>(t.Markdown="Markdown",t.ObsidianSettingsDefault="ObsidianSettingsDefault",t.PreserveExisting="PreserveExisting",t.Wikilink="Wikilink",t))(Xa||{});function Cb(t){let e=Ke(t.app,t.link,t.oldSourcePathOrFile??t.newSourcePathOrFile);return e?sn({app:t.app,link:t.link,linkStyle:t.linkStyle,newSourcePathOrFile:t.newSourcePathOrFile,newTargetPathOrFile:e,oldSourcePathOrFile:t.oldSourcePathOrFile,shouldUpdateFileNameAlias:t.shouldUpdateFileNameAlias}):t.link.original}i(Cb,"convertLink");async function on(t,e,n,r={}){await Tr(t,e,async(o,s)=>{let a=await Xe(t,e);o.throwIfAborted();let l=ae(t,e),c=await t.vault.cachedRead(l);return o.throwIfAborted(),s!==c?null:await Rb(a,St(t,e),n,o)},r)}i(on,"editLinks");function Za(t){return we(t,yb,({substring:e})=>encodeURIComponent(e))}i(Za,"encodeUrl");function Ab(t){return we(t,kb,"\\$&")}i(Ab,"escapeAlias");function Ke(t,e,n,r=!1){let{linkPath:o}=Dt(e.link),s=G(t,n),a=t.metadataCache.getFirstLinkpathDest(o,s);if(a)return a;if(!r)return null;if(o.startsWith("/"))return ae(t,o,!0);let l=oe(K(s),`./${o}`);return l.startsWith("../")?null:ae(t,l,!0)}i(Ke,"extractLinkFile");function Xi(t){let{app:e}=t,n={isEmptyEmbedAliasAllowed:!0},r=Bb(e).map(s=>s());t=Object.assign({},n,...r,t);let o=ae(e,t.targetPathOrFile,t.isNonExistingFileAllowed);return Ir(e,[o],()=>Lb(t))}i(Xi,"generateMarkdownLink");function Qa(t){let e=t.isEmbed?"!":"";if(t.isWikilink){let l=t.alias?`|${t.alias}`:"";return`${e}[[${t.url}${l}]]`}let n=t.alias??"",o=t.shouldEscapeAlias??!1?Ab(n):n,s=t.shouldUseAngleBrackets?`<${t.url}>`:Za(t.url),a=t.title?` ${JSON.stringify(t.title)}`:"";return`${e}[${o}](${s}${a})`}i(Qa,"generateRawMarkdownLink");function Kn(t){let e=xb(t);return e[0]?.raw===t?e[0]:null}i(Kn,"parseLink");function xb(t){let e=new Set,n="![",r="@[",o="@",a=we(t,/\[(?!\[.*?\]\(.+?\))\]\((?.+?)\)/g,(f,b,k)=>`[${o.repeat(b.length)}](${k})`),l=we(a,n,f=>(e.add(f.offset),r)),u=Yd().use(On).use(ep,{aliasDivider:yp}).parse(l),d=[],p=[];Ar(u,f=>{let b;switch(f.type){case"link":b=zb(f,t);break;case"wikiLink":b=Vb(f,t);break;default:return}e.has(b.startOffset-1)&&(b.isEmbed=!0,b.startOffset--,b.raw=`!${b.raw}`),d.push(b)}),d.sort((f,b)=>f.startOffset-b.startOffset);let h=0;for(let f of d)bp(t,h,f.startOffset-1,p),h=f.endOffset+1;return bp(t,h,t.length-1,p),d.push(...p),d.sort((f,b)=>f.startOffset-b.startOffset),d}i(xb,"parseLinks");function vb(t){let{app:e,displayText:n,isWikilink:r,newSourcePathOrFile:o,oldSourcePathOrFile:s,oldTargetPath:a,targetPathOrFile:l}=t;if(r===!1)return!1;if(!n)return!0;let c=ae(e,l,!0),u=G(e,o),d=G(e,s??o),p=K(u),h=K(d),f=new Set;for(let k of[c.path,a]){if(!k)continue;let y=G(e,k);f.add(y),f.add(Ne(y)),f.add(bn(p,y)),f.add(bn(h,y))}for(let k of[d,u])f.add(e.metadataCache.fileToLinktext(c,k,!1));let b=we((0,jn.normalizePath)(ee(n.split(" > ")[0])),/^\.\//g,"").toLowerCase();for(let k of f){if(k.toLowerCase()===b)return!0;let y=K(k),w=Ne(k,it(k));if(oe(y,w).toLowerCase()===b)return!0}return!1}i(vb,"shouldResetAlias");function Dt(t){let e=(0,jn.parseLinktext)(ar(t));return{linkPath:e.path,subpath:e.subpath}}i(Dt,"splitSubpath");function Eb(t){return Kn(t)?.hasAngleBrackets??!1}i(Eb,"testAngleBrackets");function Zi(t){return Kn(t)?.isEmbed??!1}i(Zi,"testEmbed");function Sb(t){return Kn(t)?.url.startsWith("./")??!1}i(Sb,"testLeadingDot");function Pb(t){return Kn(t)?.url.startsWith("/")??!1}i(Pb,"testLeadingSlash");function Mr(t){return Kn(t)?.isWikilink??!1}i(Mr,"testWikilink");function Tb(t){return we(t,/(?\\+)(?[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~])/g,(e,n,r)=>{let s=n.length,a=Math.floor(s/2);return"\\".repeat(a)+r})}i(Tb,"unescapeAlias");function sn(t){let{app:e,link:n,linkStyle:r,newSourcePathOrFile:o,newTargetPathOrFile:s,oldSourcePathOrFile:a,oldTargetPathOrFile:l,shouldUpdateFileNameAlias:c}=t;if(!s)return n.original;let u=ae(e,s,!0),d=G(e,a??o),p=G(e,l??s),h=Cp(e,n.original,r),{subpath:f}=Dt(n.link),b=!c;if(St(e,o)&&np(n))return u.path+f;let k=Kn(n.original),y;return h&&k?.alias&&(y=k.alias,b=!0),y??=vb({app:e,displayText:n.displayText,isWikilink:h,newSourcePathOrFile:o,oldSourcePathOrFile:a,oldTargetPath:p,targetPathOrFile:u})?void 0:k?.alias,b||(y===Ne(p,it(p))?y=u.basename:y===Ne(p)&&(y=u.name)),Xi({alias:y,app:e,isSingleSubpathAllowed:d===p&&!!k?.alias,linkStyle:r,originalLink:n.original,sourcePathOrFile:o,subpath:f,targetPathOrFile:u})}i(sn,"updateLink");async function eo(t){let{app:e,linkStyle:n,newSourcePathOrFile:r,oldSourcePathOrFile:o,shouldUpdateEmbedOnlyLinks:s,shouldUpdateFileNameAlias:a}=t;St(e,r)&&!e.internalPlugins.getEnabledPluginById(Le.Canvas)||await on(e,r,l=>{let c=Zi(l.original);if(!(s!==void 0&&s!==c))return Cb({app:e,link:l,linkStyle:n,newSourcePathOrFile:r,oldSourcePathOrFile:o,shouldUpdateFileNameAlias:a})},t)}i(eo,"updateLinksInFile");function Fb(t,e,n){if(e||n)return t;try{return decodeURIComponent(t)}catch(r){return console.error(`Failed to decode URL ${t}`,r),t}}i(Fb,"decodeUrlSafely");function Ib(t,e,n){return en)return;let o=t.slice(e,n+1);we(o,/(?\S+)/g,(s,a)=>{Ua(a)&&r.push({encodedUrl:Za(a),endOffset:e+s.offset+a.length,hasAngleBrackets:!1,isEmbed:!1,isExternal:!0,isWikilink:!1,raw:a,startOffset:e+s.offset,url:a})})}i(bp,"extractTextLinks");function Mb(t,e,n,r,o){n==="/"&&(n="");let s;if(e.path===n&&r&&o.isSingleSubpathAllowed)s="";else switch(o.linkPathStyle){case"AbsolutePathInVault":s=e.path,o.shouldUseLeadingSlashForAbsolutePaths&&!s.startsWith("/")&&(s=`/${s}`);break;case"RelativePathToTheNote":s=bn(K(n),e.path),o.shouldUseLeadingDotForRelativePaths&&!s.startsWith(".")&&(s=`./${s}`);break;case"ShortestPathWhenPossible":{let a=Ye(t,e)?e.basename:e.name,l=t.metadataCache.getLinkpathDest(a,n);s=l.length===1&&l[0]===e?e.name:e.path;break}default:throw new Error(`Invalid link path style: ${o.linkPathStyle}.`)}return s=o.isWikilink?lr(s,`.${Ht}`):s,s+=r,s}i(Mb,"generateLinkText");function Lb(t){let{app:e}=t,n=ae(e,t.targetPathOrFile,t.isNonExistingFileAllowed),r=G(e,t.sourcePathOrFile),o=t.subpath??"",s=_b(t,n),a=Mb(e,n,r,o,s);return s.isWikilink?Ob(a,t.alias,s.isEmbed):Nb(a,n,t,s)}i(Lb,"generateMarkdownLinkImpl");function Nb(t,e,n,r){let{app:o}=n,s=n.alias??"",a=n.shouldEscapeAlias??!1;return!s&&(Ye(o,e)||!n.isEmptyEmbedAliasAllowed)&&(s=!n.shouldIncludeAttachmentExtensionToEmbedAlias||Ye(o,e)?e.basename:e.name,a=!0),Qa({alias:s,isEmbed:r.isEmbed,isWikilink:!1,shouldEscapeAlias:a,shouldUseAngleBrackets:r.shouldUseAngleBrackets,url:t})}i(Nb,"generateMarkdownStyleLink");function Ob(t,e,n){return e?.toLowerCase()===t.toLowerCase()?Qa({isEmbed:n,isWikilink:!0,url:e}):Qa({alias:e,isEmbed:n,isWikilink:!0,url:t})}i(Ob,"generateWikiLink");async function Rb(t,e,n,r){if(r??=Se(),r.throwIfAborted(),!t)return[];let o=[],s=(t.sections??[]).filter(a=>a.type==="table").map(a=>({end:a.position.end.offset,start:a.position.start.offset}));for(let a of je(t)){r.throwIfAborted();let l=await n(a,r);if(r.throwIfAborted(),l===void 0)continue;let c=nn(a,l);if(e)if(Fr(c))o.push(c);else{console.error("Unsupported file change",c);continue}else Ub(c,s)&&(c.newContent=c.newContent.replaceAll(wp,wb)),o.push(c)}return o}i(Rb,"getFileChanges");function Db(t,e){switch(e??"ObsidianSettingsDefault"){case"AbsolutePathInVault":return"AbsolutePathInVault";case"RelativePathToTheSource":return"RelativePathToTheNote";case"ShortestPathWhenPossible":return"ShortestPathWhenPossible";case"ObsidianSettingsDefault":{let n=gp(t);switch(n){case"absolute":return"AbsolutePathInVault";case"relative":return"RelativePathToTheNote";case"shortest":return"ShortestPathWhenPossible";default:throw new Error(`Invalid link format: ${n}.`)}}default:throw new Error(`Invalid link path style: ${e}.`)}}i(Db,"getFinalLinkPathStyle");function Bb(t){return Te(t,"generateMarkdownLinkDefaultOptionsFns",[]).value}i(Bb,"getGenerateMarkdownLinkDefaultOptionsFns");function _b(t,e){let{app:n}=t;return{isEmbed:t.isEmbed??(t.originalLink?Zi(t.originalLink):void 0)??(!(0,jn.requireApiVersion)("1.10.0")&&!Ye(n,e)),isSingleSubpathAllowed:t.isSingleSubpathAllowed??!0,isWikilink:Cp(n,t.originalLink,t.linkStyle),linkPathStyle:Db(n,t.linkPathStyle),shouldUseAngleBrackets:t.shouldUseAngleBrackets??(t.originalLink?Eb(t.originalLink):void 0)??!1,shouldUseLeadingDotForRelativePaths:t.shouldUseLeadingDotForRelativePaths??(t.originalLink?Sb(t.originalLink):void 0)??!1,shouldUseLeadingSlashForAbsolutePaths:t.shouldUseLeadingSlashForAbsolutePaths??(t.originalLink?Pb(t.originalLink):void 0)??!1}}i(_b,"getLinkConfig");function kp(t,e){let n=ee(t.position);return e.slice(n.start.offset,n.end.offset)}i(kp,"getRawLink");function $b(t,e){return t.startsWith("<")||e.startsWith("<")}i($b,"hasAngleBracketsInLink");function zb(t,e){let o=kp(t,e),s=t.children[0]?.position?.start.offset??1,a=t.children.at(-1)?.position?.end.offset??1,l=ee(t.position),c=ee(l.end.offset),u=ee(l.start.offset),d=e.slice(a+2,c-1),p=$b(o,d),h=Ua(t.url),f=Fb(t.url,h,p),b=Ib(e,s,a);return{alias:b,encodedUrl:h?Za(f):void 0,endOffset:c,hasAngleBrackets:p,isEmbed:!1,isExternal:h,isWikilink:!1,raw:o,startOffset:u,title:t.title??void 0,unescapedAlias:b===void 0?void 0:Tb(b),url:f}}i(zb,"parseLinkNode");function Vb(t,e){let n=ee(t.position);return{alias:e.includes(yp)?t.data.alias:void 0,endOffset:ee(n.end.offset),isEmbed:!1,isExternal:!1,isWikilink:!0,raw:kp(t,e),startOffset:ee(n.start.offset),url:t.value}}i(Vb,"parseWikilinkNode");function Ub(t,e){return!rn(t)||!wp.test(t.newContent)?!1:e.some(n=>n.start<=t.reference.position.start.offset&&t.reference.position.end.offset<=n.end)}i(Ub,"shouldEscapeWikilinkDivider");function Cp(t,e,n){switch(n??"PreserveExisting"){case"Markdown":return!1;case"ObsidianSettingsDefault":return Ja(t);case"PreserveExisting":return e===void 0?Ja(t):Mr(e);case"Wikilink":return!0;default:throw new Error(`Invalid link style: ${n}.`)}}i(Cp,"shouldUseWikilinkStyle");function Ap(t,e){let n=Object.keys(e).map(r=>Wb(t,r,e[r]));return n.length===1?n[0]:function(){n.forEach(r=>r())}}i(Ap,"around");function Wb(t,e,n){let r=t[e],o=t.hasOwnProperty(e),s=o?r:function(){return Object.getPrototypeOf(t)[e].apply(this,arguments)},a=n(s);return r&&Object.setPrototypeOf(a,r),Object.setPrototypeOf(l,a),t[e]=l,c;function l(...u){return a===s&&t[e]===l&&c(),a.apply(this,u)}i(l,"wrapper");function c(){t[e]===l&&(o?t[e]=s:delete t[e]),a!==s&&(a=s,Object.setPrototypeOf(l,r||Function))}i(c,"remove")}i(Wb,"around1");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function xp(t,e){return Ap(t,e)}i(xp,"around");async function el(t,e,n){let r=xp(t,e);try{return await n()}finally{r()}}i(el,"invokeWithPatchAsync");function vp(t,e,n){let r=xp(e,n),o=!1;function s(){if(!o)try{r()}finally{o=!0}}return i(s,"uninstallerWrapper"),t.register(s),r}i(vp,"registerPatch");var Ep=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();async function Ft(t,e,n,r,o){let s=ft(t,e);if(!s)return!1;let a=Z(s)||(o??!0);if(Z(s)){let l=await Be(t,s);n&&l.clear(n),l.count()!==0&&(r&&new Ep.Notice(E(c=>c.obsidianDevUtils.notices.attachmentIsStillUsed,{attachmentPath:s.path})),a=!1)}else if(Ve(s)){let l=await Wn(t,s);for(let c of[...l.files,...l.folders])a&&=await Ft(t,c,n,r);a&&=await Ki(t,s)}if(a)try{await Tt(t,s)}catch(l){Wt(new Error(`Failed to delete ${s.path}`,{cause:l})),a=!1}return a}i(Ft,"deleteIfNotUsed");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Ae=(t=>(t.Delete="Delete",t.DeleteWithEmptyParents="DeleteWithEmptyParents",t.Keep="Keep",t))(Ae||{}),tl=class{static{i(this,"DeleteHandler")}constructor(e,n,r,o,s){this.app=e,this.file=n,this.abortSignal=r,this.settingsManager=o,this.deletedMetadataCacheMap=s}async handle(){if(this.abortSignal.throwIfAborted(),Y("RenameDeleteHandler:handleDelete")(`Handle Delete ${this.file.path}`),!Oe(this.app,this.file))return;let e=this.settingsManager.getSettings();if(e.isPathIgnored?.(this.file.path)){Y("RenameDeleteHandler:handleDelete")(`Skipping delete handler of ${this.file.path} as the path is ignored.`);return}let n=new Set([K(this.file.path)]);if(e.shouldHandleDeletions){let s=this.deletedMetadataCacheMap.get(this.file.path);if(this.deletedMetadataCacheMap.delete(this.file.path),s){let a=je(s);for(let l of a){let c=Ke(this.app,l,this.file.path);c&&(this.settingsManager.isNoteEx(c.path)||(n.add(c.parent?.path??""),await Ft(this.app,c,this.file.path,!1,e.emptyFolderBehavior!=="Keep"),this.abortSignal.throwIfAborted()))}}}if(n.delete(""),await Pp(this.app,this.settingsManager.getSettings(),Array.from(n)),this.abortSignal.throwIfAborted(),!e.shouldHandleDeletions)return;let r=await In(this.app,this.file.path,Mt.DeleteNote),o=st(this.app,r);o&&await Gs(this.app,this.file.path,Mt.DeleteNote)&&(this.abortSignal.throwIfAborted(),await Ft(this.app,o,this.file.path,!1,e.emptyFolderBehavior!=="Keep"),this.abortSignal.throwIfAborted())}},nl=class{static{i(this,"HandledRenames")}map=new Map;add(e,n){this.map.set(this.keyToString(e,n),{newPath:n,oldPath:e})}delete(e,n){this.map.delete(this.keyToString(e,n))}has(e,n){return this.map.has(this.keyToString(e,n))}keys(){return this.map.values()}keyToString(e,n){return`${e} -> ${n}`}},rl=class{static{i(this,"MetadataDeletedHandler")}constructor(e,n,r,o,s){this.app=e,this.file=n,this.prevCache=r,this.settingsManager=o,this.deletedMetadataCacheMap=s}handle(){let e=this.settingsManager.getSettings();if(e.shouldHandleDeletions){if(e.isPathIgnored?.(this.file.path)){Y("RenameDeleteHandler:handleMetadataDeleted")(`Skipping metadata delete handler of ${this.file.path} as the path is ignored.`);return}Ye(this.app,this.file)&&this.prevCache&&this.deletedMetadataCacheMap.set(this.file.path,this.prevCache)}}},il=class{static{i(this,"Registry")}constructor(e,n,r){this.plugin=e,this.settingsBuilder=n,this.settingsManager=r,this.app=e.app,this.pluginId=e.manifest.id,this.abortSignal=e.abortSignal??Se()}abortSignal;app;deletedMetadataCacheMap=new Map;handledRenames=new nl;interruptedRenamesMap=new Map;pluginId;register(){let e=this.settingsManager.renameDeleteHandlersMap;e.set(this.pluginId,this.settingsBuilder),this.logRegisteredHandlers(),this.plugin.register(()=>{e.delete(this.pluginId),this.logRegisteredHandlers()}),this.plugin.registerEvent(this.app.vault.on("delete",this.handleDelete.bind(this))),this.plugin.registerEvent(this.app.vault.on("rename",this.handleRename.bind(this))),this.plugin.registerEvent(this.app.metadataCache.on("deleted",this.handleMetadataDeleted.bind(this))),vp(this.plugin,this.app.fileManager,{runAsyncLinkUpdate:i(n=>Object.assign(r=>this.runAsyncLinkUpdate(n,r),{renameDeleteHandlerPatched:!0}),"runAsyncLinkUpdate")})}handleDelete(e){this.shouldInvokeHandler()&&Ue({app:this.app,operationFn:i(n=>new tl(this.app,e,n,this.settingsManager,this.deletedMetadataCacheMap).handle(),"operationFn"),operationName:wt(n=>n.obsidianDevUtils.renameDeleteHandler.handleDelete,{filePath:e.path})})}handleMetadataDeleted(e,n){this.shouldInvokeHandler()&&new rl(this.app,e,n,this.settingsManager,this.deletedMetadataCacheMap).handle()}handleRename(e,n){if(!this.shouldInvokeHandler()||!Z(e))return;let r=e.path;if(Y("RenameDeleteHandler:handleRename")(`Handle Rename ${n} -> ${r}`),this.handledRenames.has(n,r)){this.handledRenames.delete(n,r);return}let o=this.settingsManager.getSettings();if(!o.shouldHandleRenames)return;if(o.isPathIgnored?.(n)){Y("RenameDeleteHandler:handleRename")(`Skipping rename handler of old path ${n} as the path is ignored.`);return}if(o.isPathIgnored?.(r)){Y("RenameDeleteHandler:handleRename")(`Skipping rename handler of new path ${r} as the path is ignored.`);return}let s=this.app.metadataCache.getCache(n)??this.app.metadataCache.getCache(r),a=Ya(this.app,n).data;Ue({abortSignal:this.abortSignal,app:this.app,operationFn:i(l=>new sl({abortSignal:l,app:this.app,handledRenames:this.handledRenames,interruptedRenamesMap:this.interruptedRenamesMap,newPath:r,oldCache:s,oldPath:n,oldPathBacklinksMap:a,settingsManager:this.settingsManager}).handle(),"operationFn"),operationName:wt(l=>l.obsidianDevUtils.renameDeleteHandler.handleRename,{newPath:r,oldPath:n})})}logRegisteredHandlers(){let e=this.settingsManager.renameDeleteHandlersMap;Y("RenameDeleteHandler:logRegisteredHandlers")(`Plugins with registered rename/delete handlers: ${JSON.stringify(Array.from(e.keys()))}`)}async runAsyncLinkUpdate(e,n){if(e.renameDeleteHandlerPatched){await e.call(this.app.fileManager,n);return}await e.call(this.app.fileManager,r=>this.wrapLinkUpdatesHandler(r,n))}shouldInvokeHandler(){let e=this.plugin.manifest.id,n=this.settingsManager.renameDeleteHandlersMap;return Array.from(n.keys())[0]===e}async wrapLinkUpdatesHandler(e,n){let r=!1,o=this.app.vault.on("rename",()=>{r=!0});try{await n(e)}finally{this.app.vault.offref(o)}let s=this.settingsManager.getSettings();!r||!s.shouldHandleRenames||sr(e,a=>s.isPathIgnored?.(a.sourceFile.path)?(Y("RenameDeleteHandler:runAsyncLinkUpdate")(`Roll back to default link update of source file ${a.sourceFile.path} as the path is ignored.`),!0):s.isPathIgnored?.(a.resolvedFile.path)?(Y("RenameDeleteHandler:runAsyncLinkUpdate")(`Roll back to default link update of resolved file ${a.resolvedFile.path} as the path is ignored.`),!0):!this.app.internalPlugins.getEnabledPluginById(Le.Canvas)||this.app.plugins.getPlugin("backlink-cache")?!1:a.sourceFile.extension===Hr||a.resolvedFile.extension===Hr)}},ol=class{static{i(this,"SettingsManager")}constructor(e){this.app=e,this.renameDeleteHandlersMap=Te(e,"renameDeleteHandlersMap",new Map).value}renameDeleteHandlersMap;getSettings(){let e=Array.from(this.renameDeleteHandlersMap.values()).reverse(),n={};n.isNote=r=>Oe(this.app,r),n.isPathIgnored=()=>!1;for(let r of e){let o=r();n.shouldDeleteConflictingAttachments||=o.shouldDeleteConflictingAttachments??!1,o.emptyFolderBehavior&&(n.emptyFolderBehavior??=o.emptyFolderBehavior),n.shouldHandleDeletions||=o.shouldHandleDeletions??!1,n.shouldHandleRenames||=o.shouldHandleRenames??!1,n.shouldRenameAttachmentFiles||=o.shouldRenameAttachmentFiles??!1,n.shouldRenameAttachmentFolder||=o.shouldRenameAttachmentFolder??!1,n.shouldUpdateFileNameAliases||=o.shouldUpdateFileNameAliases??!1;let s=n.isPathIgnored;n.isPathIgnored=l=>s(l)||(o.isPathIgnored?.(l)??!1);let a=n.isNote;n.isNote=l=>a(l)&&(o.isNote?.(l)??!0)}return n.emptyFolderBehavior??="Keep",n}isNoteEx(e){return this.getSettings().isNote?.(e)??!1}},sl=class t{static{i(this,"RenameHandler")}abortSignal;app;handledRenames;interruptedCombinedBacklinksMap;interruptedRenamesMap;newPath;oldCache;oldPath;oldPathBacklinksMap;oldPathLinks;settingsManager;constructor(e){this.app=e.app,this.oldPath=e.oldPath,this.newPath=e.newPath,this.oldPathBacklinksMap=e.oldPathBacklinksMap,this.oldCache=e.oldCache,this.abortSignal=e.abortSignal,this.settingsManager=e.settingsManager,this.interruptedRenamesMap=e.interruptedRenamesMap,this.oldPathLinks=this.oldCache?je(this.oldCache):[],this.handledRenames=e.handledRenames,this.interruptedCombinedBacklinksMap=e.interruptedCombinedBacklinksMap??new Map}async handle(){if(this.oldPath===this.newPath||(this.abortSignal.throwIfAborted(),await this.continueInterruptedRenames(),this.abortSignal.throwIfAborted(),await this.refreshLinks(),this.abortSignal.throwIfAborted(),await this.handleCaseCollision()))return;this.abortSignal.throwIfAborted();let e=Te(this.app,"renamedFilePaths",new Set).value,n=Te(this.app,"renamedLinkPaths",new Set).value;try{let r=new al({abortSignal:this.abortSignal,app:this.app,newPath:this.newPath,oldCache:this.oldCache,oldPath:this.oldPath,settingsManager:this.settingsManager});await r.fill(),this.abortSignal.throwIfAborted();let o=new Map;r.initOriginalLinksMap(o),r.initBacklinksMap(this.oldPathBacklinksMap,o,this.oldPath);for(let l of r.keys()){if(l===this.oldPath)continue;let c=(await Be(this.app,l)).data;this.abortSignal.throwIfAborted(),r.initBacklinksMap(c,o,l)}let s=new Set;for(let[l,c]of r.entries()){if(l!==this.oldPath){let u=await this.renameHandled(l,c);this.abortSignal.throwIfAborted(),r.set(l,u)}this.settingsManager.isNoteEx(l)||s.add(K(l))}await Pp(this.app,this.settingsManager.getSettings(),Array.from(s)),this.abortSignal.throwIfAborted();let a=this.settingsManager.getSettings();for(let[l,c]of Array.from(o.entries()).concat(Array.from(this.interruptedCombinedBacklinksMap.entries()))){let u=0;await on(this.app,l,d=>{u++;let p=c.get(Kt(d));if(!p)return;let h=r.get(p)??p;return e.add(l),n.add(`${l}//${String(u)}`),sn({app:this.app,link:d,newSourcePathOrFile:l,newTargetPathOrFile:h,oldTargetPathOrFile:p,shouldUpdateFileNameAlias:a.shouldUpdateFileNameAliases})},{shouldFailOnMissingFile:!1}),this.abortSignal.throwIfAborted()}if(Oe(this.app,this.newPath)&&(await eo({app:this.app,newSourcePathOrFile:this.newPath,oldSourcePathOrFile:this.oldPath,shouldFailOnMissingFile:!1,shouldUpdateFileNameAlias:a.shouldUpdateFileNameAliases}),this.abortSignal.throwIfAborted()),!X(this.app,this.newPath)){let l=this.interruptedRenamesMap.get(this.newPath);l||(l=[],this.interruptedRenamesMap.set(this.newPath,l)),l.push({combinedBacklinksMap:o,oldPath:this.oldPath})}}finally{let r=Array.from(this.handledRenames.keys());Ue({abortSignal:this.abortSignal,app:this.app,operationFn:i(()=>{for(let o of r)this.handledRenames.delete(o.oldPath,o.newPath);n.size!==0&&(new to.Notice(wt(o=>o.obsidianDevUtils.renameDeleteHandler.updatedLinks,{filesCount:e.size,linksCount:n.size})),e.clear(),n.clear())},"operationFn"),operationName:wt(o=>o.obsidianDevUtils.renameDeleteHandler.handleOrphanedRenames)})}}async continueInterruptedRenames(){let e=this.interruptedRenamesMap.get(this.oldPath);if(e){this.interruptedRenamesMap.delete(this.oldPath);for(let n of e)await new t({abortSignal:this.abortSignal,app:this.app,handledRenames:this.handledRenames,interruptedCombinedBacklinksMap:n.combinedBacklinksMap,interruptedRenamesMap:this.interruptedRenamesMap,newPath:this.newPath,oldCache:this.oldCache,oldPath:n.oldPath,oldPathBacklinksMap:this.oldPathBacklinksMap,settingsManager:this.settingsManager}).handle()}}async handleCaseCollision(){if(!this.app.vault.adapter.insensitive||this.oldPath.toLowerCase()!==this.newPath.toLowerCase())return!1;let e=oe(K(this.newPath),`__temp__${Ne(this.newPath)}`);return await this.renameHandled(this.newPath,e),await new t({abortSignal:this.abortSignal,app:this.app,handledRenames:this.handledRenames,interruptedRenamesMap:this.interruptedRenamesMap,newPath:e,oldCache:this.oldCache,oldPath:this.oldPath,oldPathBacklinksMap:this.oldPathBacklinksMap,settingsManager:this.settingsManager}).handle(),await this.app.fileManager.renameFile(ae(this.app,e),this.newPath),!0}async refreshLinks(){let e=this.app.metadataCache.getCache(this.oldPath)??this.app.metadataCache.getCache(this.newPath),n=e?je(e):[],r=ae(this.app,this.oldPath,!0),o=new Map;await Ir(this.app,[r],async()=>{o=(await Be(this.app,r)).data});for(let s of n)this.oldPathLinks.includes(s)||this.oldPathLinks.push(s);for(let[s,a]of o.entries()){let l=this.oldPathBacklinksMap.get(s);l||(l=[],this.oldPathBacklinksMap.set(s,l));for(let c of a)l.includes(c)||l.push(c)}}async renameHandled(e,n){return n=qa(this.app,e,n),e===n||(this.handledRenames.add(e,n),n=await Hn(this.app,e,n)),n}},al=class{static{i(this,"RenameMap")}abortSignal;app;map=new Map;newPath;oldCache;oldPath;oldPathLinks;settingsManager;constructor(e){this.abortSignal=e.abortSignal,this.app=e.app,this.settingsManager=e.settingsManager,this.oldCache=e.oldCache,this.oldPath=e.oldPath,this.newPath=e.newPath,this.oldPathLinks=this.oldCache?je(this.oldCache):[]}entries(){return this.map.entries()}async fill(){if(this.abortSignal.throwIfAborted(),this.map.set(this.oldPath,this.newPath),!Oe(this.app,this.oldPath))return;let e=this.settingsManager.getSettings(),n=ae(this.app,this.oldPath,!0),r="";await pp(this.app,[n],async()=>{let c=this.oldCache&&n.deleted;c&&up(this.app,n,this.oldCache);try{r=await In(this.app,this.oldPath,Mt.RenameNote)}finally{c&&hp(this.app,n)}});let o=e.shouldRenameAttachmentFolder?await In(this.app,this.newPath,Mt.RenameNote):r,s=r==="/",a=st(this.app,r);if(!a||r===o&&!e.shouldRenameAttachmentFiles)return;let l=[];if(await Gs(this.app,this.oldPath,Mt.RenameNote))to.Vault.recurseChildren(a,c=>{this.abortSignal.throwIfAborted(),Z(c)&&l.push(c)});else for(let c of this.oldPathLinks){this.abortSignal.throwIfAborted();let u=Ke(this.app,c,this.oldPath);if(u&&(s||u.path.startsWith(r))){let d=await Be(this.app,u);this.abortSignal.throwIfAborted();let p=new Set(d.keys());p.delete(this.oldPath),p.delete(this.newPath),p.size===0&&l.push(u)}}for(let c of l){if(this.abortSignal.throwIfAborted(),this.settingsManager.isNoteEx(c.path))continue;let u;if(e.shouldRenameAttachmentFiles)u=await Gt({app:this.app,context:Mt.RenameNote,notePathOrFile:this.newPath,oldAttachmentPathOrFile:c,oldNotePathOrFile:this.oldPath,shouldSkipDuplicateCheck:!0}),this.abortSignal.throwIfAborted();else{let d=s?c.path:bn(r,c.path),p=oe(o,K(d));u=oe(p,c.name)}if(c.path!==u){if(e.shouldDeleteConflictingAttachments){let d=X(this.app,u);d&&(Y("RenameDeleteHandler:fillRenameMap")(`Removing conflicting attachment ${d.path}.`),await Tt(this.app,d),this.abortSignal.throwIfAborted())}else{let d=K(u),p=it(u),h=Ne(u,p);u=this.app.vault.getAvailablePath(oe(d,h),p.slice(1))}this.map.set(c.path,u)}}}get(e){return this.map.get(e)}initBacklinksMap(e,n,r){for(let[o,s]of e.entries()){let a=this.map.get(o)??o,l=n.get(a)??new Map;n.set(a,l);for(let c of s)l.set(Kt(c),r)}}initOriginalLinksMap(e){for(let n of this.oldPathLinks){let r=Ke(this.app,n,this.oldPath);if(!r)continue;let o=new Map;o.set(this.newPath,[n]),this.initBacklinksMap(o,e,r.path)}}keys(){return this.map.keys()}set(e,n){this.map.set(e,n)}};function Sp(t,e){new il(t,e,new ol(t.app)).register()}i(Sp,"registerRenameDeleteHandlers");async function Pp(t,e,n){if(e.emptyFolderBehavior!=="Keep")for(let r of n)switch(e.emptyFolderBehavior){case"Delete":await Ka(t,r);break;case"DeleteWithEmptyParents":await Pr(t,r);break;default:break}}i(Pp,"cleanupParentFolders");var ln=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function ne(t,e){t.createEl("strong",{cls:"markdown-rendered code"},n=>{n.createEl("code",{text:e})})}i(ne,"appendCodeBlock");async function ll(t,e,n){let r=createEl(t,e);return await n?.(r),r}i(ll,"createElAsync");async function no(t){let e=createFragment();return await t?.(e),e}i(no,"createFragmentAsync");function Tp(t){let e=t;for(;e;){let n=getComputedStyle(e).zIndex,r=Number.parseInt(n,10);if(!Number.isNaN(r))return r;e=e.parentElement}return 0}i(Tp,"getZIndex");function Fp(t){return`${String(t)}px`}i(Fp,"toPx");var cl=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ul=class extends Fn{static{i(this,"ConfirmModal")}isConfirmed=!1;params;constructor(e,n){super(e,n,M.ConfirmModal);let r={app:e.app,cancelButtonText:E(o=>o.obsidianDevUtils.buttons.cancel),cssClass:"",message:e.message,okButtonText:E(o=>o.obsidianDevUtils.buttons.ok),title:""};this.params={...r,...e}}onClose(){super.onClose(),this.resolve(this.isConfirmed)}onOpen(){super.onOpen(),this.titleEl.setText(this.params.title),this.contentEl.createEl("p",{text:this.params.message});let e=new cl.ButtonComponent(this.contentEl);e.setButtonText(this.params.okButtonText),e.setCta(),e.onClick(()=>{this.isConfirmed=!0,this.close()}),e.setClass(M.OkButton);let n=new cl.ButtonComponent(this.contentEl);n.setButtonText(this.params.cancelButtonText),n.onClick(this.close.bind(this)),n.setClass(M.CancelButton)}};async function Ip(t){return await di(e=>new ul(t,e))}i(Ip,"confirm");var Gn=require("obsidian");var an=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Mp=null,dl=class{static{i(this,"FixedZIndexDomEventsHandlersInfo")}constructor(e,n,r){this.app=e,this.path=n,r.isConnected?this.updateZIndex(r):r.onNodeInserted(()=>{this.updateZIndex(r)})}get hoverPopover(){return this._hoverPopover}set hoverPopover(e){this._hoverPopover=e,e&&this.zIndex!==void 0&&e.hoverEl.setCssStyles({zIndex:String(this.zIndex)})}_hoverPopover=null;zIndex;updateZIndex(e){this.zIndex=Tp(e)+1}};async function Hb(t){let e=t.sourcePath??"/",n=!1,r;t.component?r=t.component:(r=new an.Component,r.load(),n=!0),await el(t.app.embedRegistry.embedByExtension,{md:i(o=>(s,a,l)=>(s.displayMode=!1,o(s,a,l)),"md")},async()=>{await an.MarkdownRenderer.render(t.app,t.markdown,t.el,e,r)}),n&&r.unload(),t.shouldRegisterLinkHandlers&&await Lp(t.app,t.el,t.sourcePath)}i(Hb,"fullRender");async function Lp(t,e,n){Mp??=await jb(t),an.MarkdownPreviewRenderer.registerDomEvents(e,new Mp(new dl(t,n??"",e)))}i(Lp,"registerLinkHandlers");async function qn(t,e,n){let r=ft(t,e),o=G(t,e);if(n??=o,Ve(r))return createEl("a",{text:n},l=>{l.addEventListener("click",c=>{c.preventDefault(),t.internalPlugins.getEnabledPluginById(Le.FileExplorer)?.revealInFolder(r)})});let s=createSpan();await Hb({app:t,el:s,markdown:`[[${o}|${n}]]`});let a=s.find("a");return await Lp(t,a),a}i(qn,"renderInternalLink");async function jb(t){let e=t.vault.getMarkdownFiles()[0],n=!1;e||(e=await t.vault.create("__temp.md",""),n=!0);let r=null;try{return await el(an.MarkdownPreviewRenderer,{registerDomEvents:i(o=>(s,a,l)=>{r=a.constructor,o(s,a,l)},"registerDomEvents")},async()=>{let o=t.workspace.getLeaf(!0);await o.openFile(e,{active:!0,state:{mode:"preview"}}),await ri(),o.detach()}),Ge(r,"Failed to get register dom events handlers constructor"),r}finally{n&&await Tt(t,e)}}i(jb,"getDomEventsHandlersConstructor");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ro=class{static{i(this,"PathSetting")}constructor(e){this.type=e,this.defaultRegExp=Kb(e),this.regExp=this.defaultRegExp}get array(){return this._array}set array(e){this._array=e.filter(Boolean),this.regExp=qb(this._array,this.defaultRegExp)}_array=[];defaultRegExp;regExp;isPathIgnored(e){switch(this.type){case"Exclude":return this.regExp.test(e);case"Include":return!this.regExp.test(e);default:throw new Error(`Invalid path setting type: ${this.type}`)}}},Lr=class{static{i(this,"PathSettings")}get excludePaths(){return this._excludePaths.array}set excludePaths(e){this._excludePaths.array=e}get includePaths(){return this._includePaths.array}set includePaths(e){this._includePaths.array=e}_excludePaths=new ro("Exclude");_includePaths=new ro("Include");isPathIgnored(e){return this._includePaths.isPathIgnored(e)||this._excludePaths.isPathIgnored(e)}};function Kb(t){switch(t){case"Exclude":return uc;case"Include":return cc;default:throw new Error(`Invalid path setting type: ${t}`)}}i(Kb,"getDefaultRegExp");function qb(t,e){if(t.length===0)return e;let n=t.map(r=>r==="/"?e.source:r.startsWith("/")&&r.endsWith("/")?r.slice(1,-1):(r=lr(r,"/"),`^${ms(r)}(/|$)`)).map(r=>`(${r})`).join("|");return new RegExp(n)}i(qb,"makeRegExp");var io=class{static{i(this,"PluginSettings")}collectAttachmentUsedByMultipleNotesMode="Skip";consistencyReportFile="consistency-report.md";emptyFolderBehavior=Ae.DeleteWithEmptyParents;moveAttachmentToProperFolderUsedByMultipleNotesMode="CopyAll";shouldChangeNoteBacklinksDisplayText=!0;shouldCollectAttachmentsAutomatically=!1;shouldDeleteAttachmentsWithNote=!1;shouldDeleteExistingFilesWhenMovingNote=!1;shouldMoveAttachmentsWithNote=!1;shouldShowBackupWarning=!0;shouldUpdateLinks=!0;treatAsAttachmentExtensions=[".excalidraw.md"];get excludePaths(){return this._pathSettings.excludePaths}set excludePaths(e){this._pathSettings.excludePaths=e}get excludePathsFromAttachmentCollecting(){return this._attachmentCollectingPaths.excludePaths}set excludePathsFromAttachmentCollecting(e){this._attachmentCollectingPaths.excludePaths=e}get hadDangerousSettingsReverted(){return this._hadDangerousSettingsReverted}get includePaths(){return this._pathSettings.includePaths}set includePaths(e){this._pathSettings.includePaths=e}_attachmentCollectingPaths=new Lr;_hadDangerousSettingsReverted=!1;_pathSettings=new Lr;isExcludedFromAttachmentCollecting(e){return this._attachmentCollectingPaths.isPathIgnored(e)}isPathIgnored(e){return this._pathSettings.isPathIgnored(e)}revertDangerousSettings(){this.shouldShowBackupWarning&&(this._hadDangerousSettingsReverted=this.shouldDeleteAttachmentsWithNote||this.shouldDeleteExistingFilesWhenMovingNote||this.shouldMoveAttachmentsWithNote||this.shouldCollectAttachmentsAutomatically,this.shouldDeleteAttachmentsWithNote=!1,this.shouldDeleteExistingFilesWhenMovingNote=!1,this.shouldMoveAttachmentsWithNote=!1,this.shouldCollectAttachmentsAutomatically=!1)}};var pl=class extends Gn.Modal{constructor(n,r,o,s,a){super(n);this.attachmentPath=r;this.backlinks=o;this.resolve=s;this.isCancelMode=a}static{i(this,"CollectAttachmentUsedByMultipleNotesModal")}isSelected=!1;onClose(){this.isSelected||this.select("Cancel",!1)}onOpen(){super.onOpen(),te(()=>this.onOpenAsync())}async onOpenAsync(){super.onOpen(),new Gn.Setting(this.contentEl).setName(E(o=>o.collectAttachmentUsedByMultipleNotesModal.heading)).setHeading(),this.contentEl.appendChild(await no(async o=>{o.appendText(E(s=>s.collectAttachmentUsedByMultipleNotesModal.content.part1)),o.appendText(" "),o.appendChild(await qn(this.app,this.attachmentPath)),o.appendText(" "),o.appendText(E(s=>s.collectAttachmentUsedByMultipleNotesModal.content.part2)),o.appendChild(await ll("ul",{},async s=>{for(let a of this.backlinks)s.appendChild(await ll("li",{},async l=>{l.appendChild(await qn(this.app,a))}))}))}));let n=!1;this.isCancelMode||new Gn.Setting(this.contentEl).setName(E(o=>o.collectAttachmentUsedByMultipleNotesModal.shouldUseSameActionForOtherProblematicAttachmentsToggle)).addToggle(o=>{o.setValue(!1),o.onChange(s=>{n=s})});let r=new Gn.Setting(this.contentEl);this.isCancelMode||r.addButton(o=>{o.setButtonText(E(s=>s.buttons.skip)),o.onClick(()=>{this.select("Skip",n)})}).addButton(o=>{o.setButtonText(E(s=>s.buttons.move)),o.onClick(()=>{this.select("Move",n)})}).addButton(o=>{o.setButtonText(E(s=>s.buttons.copy)),o.onClick(()=>{this.select("Copy",n)})}),r.addButton(o=>{o.setButtonText(E(s=>s.obsidianDevUtils.buttons.cancel)),o.onClick(()=>{this.select("Cancel",n)})})}select(n,r){this.isSelected=!0,this.resolve({mode:n,shouldUseSameActionForOtherProblematicAttachments:r}),this.close()}};function hl(t,e,n,r){return new Promise(o=>{new pl(t,e,n,o,r??!1).open()})}i(hl,"selectMode");async function Yb(t,e,n,r){r.throwIfAborted();let o=t.app;if(n.isAborted)return;let s=null,a=500,l=!1;te(c);try{let u=St(o,e),d=new Set,p=await Xe(o,e);if(r.throwIfAborted(),n.isAborted||!p)return;let h=u?await Jb(o,e):je(p);r.throwIfAborted();for(let f of h){if(n.isAborted)return;let b=await Qb(t,f,e.path,e.path,d);if(r.throwIfAborted(),!b)continue;if(t.settings.isExcludedFromAttachmentCollecting(b.oldAttachmentPath)){console.warn(`Skipping collecting attachment ${b.oldAttachmentPath} as it is excluded from attachment collecting.`);continue}let k=await Be(o,b.oldAttachmentPath);if(r.throwIfAborted(),k.keys().length>1){let w=k.keys().sort((P,I)=>P.localeCompare(I)),A=w.map(P=>`- ${P}`).join(` +`);async function v(P){if(r.throwIfAborted(),!b)return!1;switch(P){case"Cancel":return console.error(`Cancelling collecting attachments, as attachment ${b.oldAttachmentPath} is referenced by multiple notes. +${A}`),t.settings.collectAttachmentUsedByMultipleNotesMode==="Cancel"&&await hl(o,b.oldAttachmentPath,w,!0),n.isAborted=!0,!1;case"Copy":if(!b.newAttachmentPath)return console.warn(`Skipping collecting attachment ${b.oldAttachmentPath} as it is already in the destination folder.`),!1;b.newAttachmentPath=await zn(o,b.oldAttachmentPath,b.newAttachmentPath),await on(o,e,I=>{if(Ke(o,I,e)?.path===b.oldAttachmentPath)return sn({app:o,link:I,newSourcePathOrFile:e,newTargetPathOrFile:b.newAttachmentPath??"",oldSourcePathOrFile:e,oldTargetPathOrFile:b.oldAttachmentPath})});break;case"Move":if(!b.newAttachmentPath)return console.warn(`Skipping collecting attachment ${b.oldAttachmentPath} as it is already in the destination folder.`),!1;await y(),r.throwIfAborted();break;case"Prompt":{let{mode:I,shouldUseSameActionForOtherProblematicAttachments:C}=await hl(o,b.oldAttachmentPath,w);return C&&(n.collectAttachmentUsedByMultipleNotesMode=I),v(I)}case"Skip":return console.warn(`Skipping collecting attachment ${b.oldAttachmentPath} as it is referenced by multiple notes. +${A}`),!1;default:throw new Error(`Unknown collect attachment used by multiple notes mode: ${t.settings.collectAttachmentUsedByMultipleNotesMode}`)}return!0}if(i(v,"applyCollectAttachmentUsedByMultipleNotesMode"),!await v(n.collectAttachmentUsedByMultipleNotesMode??t.settings.collectAttachmentUsedByMultipleNotesMode)){r.throwIfAborted();continue}}else r.throwIfAborted(),await y(),r.throwIfAborted();async function y(){r.throwIfAborted(),b?.newAttachmentPath&&(b.newAttachmentPath=await Hn(o,b.oldAttachmentPath,b.newAttachmentPath))}i(y,"registerMoveAttachment")}}finally{s?.hide(),l=!0}async function c(){await sleep(a),!l&&(s=new ln.Notice(E(u=>u.notice.collectingAttachments,{noteFilePath:e.path}),0))}i(c,"showNotice")}i(Yb,"collectAttachments");function oo(t){Ue({abortSignal:t.abortSignal,app:t.app,operationFn:i(e=>Op(t,[t.app.vault.getRoot()],e),"operationFn"),operationName:E(e=>e.commands.collectAttachmentsEntireVault)})}i(oo,"collectAttachmentsEntireVault");function Yn(t,e){Ue({abortSignal:t.abortSignal,app:t.app,operationFn:i(n=>Op(t,e,n),"operationFn"),operationName:E(n=>n.menuItems.collectAttachmentsInFile)})}i(Yn,"collectAttachmentsInAbstractFiles");async function fl(t){let e=await Gt({app:t.plugin.app,context:t.actionContext,notePathOrFile:t.noteFilePath,oldAttachmentPathOrFile:t.attachmentFile,shouldSkipDuplicateCheck:!0});return t.attachmentFile.path===e?null:e}i(fl,"getProperAttachmentPath");function Nr(t,e){if(!e||!Oe(t.app,e))return!1;let n=G(t.app,e);return t.settings.treatAsAttachmentExtensions.every(r=>!n.endsWith(r))}i(Nr,"isNoteEx");async function Op(t,e,n){n.throwIfAborted();let r=e.length===1&&Z(e[0])?e[0]:null;if(r&&t.settings.isPathIgnored(r.path)){new ln.Notice(E(d=>d.notice.notePathIsIgnored)),console.warn(`Cannot collect attachments in the note as note path is ignored: ${r.path}.`);return}if(!(!!r||await Ip({app:t.app,cancelButtonText:E(d=>d.obsidianDevUtils.buttons.cancel),message:createFragment(d=>{d.appendText(E(p=>p.attachmentCollector.confirm.part1)),d.createEl("br"),d.createEl("ul",{},p=>{for(let h of e)p.createEl("li",{},f=>{ne(f,h.path)})}),d.createEl("br"),d.appendText(E(p=>p.attachmentCollector.confirm.part2))}),okButtonText:E(d=>d.obsidianDevUtils.buttons.ok),title:createFragment(d=>{(0,ln.setIcon)(d.createSpan(),"lucide-alert-triangle"),d.appendText(" "),d.appendText(E(p=>p.menuItems.collectAttachmentsInFiles))})}))){n.throwIfAborted();return}t.consoleDebug(`Collect attachments in files: +${e.map(d=>d.path).join(` +`)}`);let s=new Set;for(let d of e)Z(d)&&Oe(t.app,d)&&s.add(d),Ve(d)&&ln.Vault.recurseChildren(d,p=>{Z(p)&&Oe(t.app,p)&&s.add(p)});let a=Array.from(s);a.sort((d,p)=>d.path.localeCompare(p.path));let l={},c=new AbortController,u=nt(c.signal,t.abortSignal);await gt({abortSignal:u,buildNoticeMessage:i((d,p)=>E(h=>h.attachmentCollector.progressBar.message,{iterationStr:p,noteFilePath:d.path}),"buildNoticeMessage"),items:a,processItem:i(async d=>{if(u.throwIfAborted(),t.settings.isPathIgnored(d.path)){console.warn(`Cannot collect attachments in the note as note path is ignored: ${d.path}.`);return}await Yb(t,d,l,u),u.throwIfAborted(),l.isAborted&&c.abort()},"processItem"),progressBarTitle:`${t.manifest.name}: ${E(d=>d.attachmentCollector.progressBar.title)}`,shouldContinueOnError:!0,shouldShowProgressBar:!0})}i(Op,"collectAttachmentsInAbstractFilesImpl");async function Jb(t,e){return(await t.vault.readJson(e.path)).nodes.filter(o=>o.type==="file").map(o=>o.file).map(o=>({link:o,original:o,position:{end:{col:0,line:0,loc:0,offset:0},start:{col:0,line:0,loc:0,offset:0}}}))}i(Jb,"getCanvasLinks");async function Qb(t,e,n,r,o){let s=t.app,a=Ke(s,e,r,!0);return!a||Nr(t,a)||o.has(a.path)?null:(o.add(a.path),a.deleted?(console.warn(`Skipping collecting attachment ${e.link} as it could not be resolved.`),null):{newAttachmentPath:await fl({actionContext:"CollectAttachments",attachmentFile:a,noteFilePath:n,plugin:t,reference:e}),oldAttachmentPath:a.path})}i(Qb,"prepareAttachmentToMove");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var so=class{static{i(this,"CommandBase")}icon;id;name;originalId;originalName;app;plugin;constructor(e){this.id=e.id,this.name=e.name,this.icon=e.icon,this.plugin=e.plugin,this.app=this.plugin.app,this.originalId=this.id,this.originalName=this.name}register(){this.plugin.addCommand(this)}},ie=class{static{i(this,"CommandInvocationBase")}constructor(e){this.plugin=e,this.app=e.app}app;lastCanExecuteResult;invoke(e){return this.lastCanExecuteResult=this.canExecute(),!e&&this.lastCanExecuteResult&&te(()=>this.execute()),this.lastCanExecuteResult}async invokeAsync(e){this.lastCanExecuteResult=this.canExecute(),!e&&this.lastCanExecuteResult&&await this.execute()}canExecute(){return!0}async execute(){if(Ge(this.lastCanExecuteResult,"canExecute() must be called before execute()"),!this.lastCanExecuteResult)throw new Error("canExecute() must return true before execute()");await Promise.resolve()}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var se=class extends so{static{i(this,"NonEditorCommandBase")}constructor(e){super(e),this.checkCallback=this.checkCallback.bind(this)}checkCallback(e){return this.createCommandInvocation().invoke(e)}};var ml=class extends ie{static{i(this,"CheckConsistencyCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.checkConsistency()}},ao=class extends se{static{i(this,"CheckConsistencyCommand")}constructor(e){super({icon:"check",id:"check-consistency",name:"Check vault consistency",plugin:e})}createCommandInvocation(){return new ml(this.plugin)}};var gl=class extends ie{static{i(this,"CollectAttachmentsEntireVaultCommandInvocation")}constructor(e){super(e)}async execute(){oo(this.plugin),await Promise.resolve()}},lo=class extends se{static{i(this,"CollectAttachmentsEntireVaultCommand")}constructor(e){super({icon:"download",id:"collect-attachments-entire-vault",name:E(n=>n.commands.collectAttachmentsEntireVault),plugin:e})}createCommandInvocation(){return new gl(this.plugin)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var cn=class extends ie{static{i(this,"AbstractFileCommandInvocationBase")}_abstractFile;get abstractFile(){if(!this._abstractFile)throw new Error("Abstract file not set");return this._abstractFile}constructor(e,n){super(e),this._abstractFile=n}canExecute(){return super.canExecute()&&!!this._abstractFile}},kt=class extends se{static{i(this,"AbstractFileCommandBase")}get fileMenuItemName(){return this._fileMenuItemName}get fileMenuSection(){return this._fileMenuSection}get fileMenuSubmenuIcon(){return this._fileMenuSubmenuIcon}get filesMenuItemName(){return this._filesMenuItemName}get filesMenuSection(){return this._filesMenuSection}get filesMenuSubmenuIcon(){return this._filesMenuSubmenuIcon}get shouldAddCommandToSubmenu(){return this._shouldAddCommandToSubmenu}_fileMenuItemName;_fileMenuSection;_fileMenuSubmenuIcon;_filesMenuItemName;_filesMenuSection;_filesMenuSubmenuIcon;_shouldAddCommandToSubmenu;constructor(e){super(e),this._fileMenuItemName=e.fileMenuItemName,this._fileMenuSection=e.fileMenuSection,this._fileMenuSubmenuIcon=e.fileMenuSubmenuIcon,this._filesMenuItemName=e.filesMenuItemName,this._filesMenuSection=e.filesMenuSection,this._filesMenuSubmenuIcon=e.filesMenuSubmenuIcon,this._shouldAddCommandToSubmenu=e.shouldAddCommandToSubmenu}checkCallback(e){return this.shouldAddToCommandPalette()?super.checkCallback(e):!1}register(){super.register(),this.plugin.registerEvent(this.app.workspace.on("file-menu",this.handleAbstractFileMenu.bind(this))),this.plugin.registerEvent(this.app.workspace.on("files-menu",this.handleAbstractFilesMenu.bind(this)))}createCommandInvocation(e){return this.createCommandInvocationForAbstractFile(e??this.app.workspace.getActiveFile())}createCommandInvocationForAbstractFiles(e){return new bl(this.plugin,e,this.createCommandInvocationForAbstractFile.bind(this))}shouldAddToAbstractFileMenu(e,n,r){return!1}shouldAddToAbstractFilesMenu(e,n,r){for(let o of e)if(!this.shouldAddToAbstractFileMenu(o,n,r))return!1;return!0}shouldAddToCommandPalette(){return!0}handleAbstractFileMenu(e,n,r,o){if(!this.shouldAddToAbstractFileMenu(n,r,o)||!this.createCommandInvocation(n).invoke(!0))return;let s=this.fileMenuSection??this.plugin.manifest.name;this.shouldAddCommandToSubmenu&&e.setSectionSubmenu(s,{icon:this.fileMenuSubmenuIcon??"",title:s}),e.addItem(a=>{a.setTitle(this.fileMenuItemName??this.originalName).setIcon(this.icon).setSection(s).onClick(()=>this.createCommandInvocation(n).invoke(!1))})}handleAbstractFilesMenu(e,n,r,o){if(!this.shouldAddToAbstractFilesMenu(n,r,o)||!this.createCommandInvocationForAbstractFiles(n).invoke(!0))return;let s=this.filesMenuSection??this.fileMenuSection??this.plugin.manifest.name;this.shouldAddCommandToSubmenu&&e.setSectionSubmenu(s,{icon:this.filesMenuSubmenuIcon??this.fileMenuSubmenuIcon??"",title:s}),e.addItem(a=>{a.setTitle(this.filesMenuItemName??this.fileMenuItemName??this.originalName).setIcon(this.icon).setSection(s).onClick(()=>this.createCommandInvocationForAbstractFiles(n).invoke(!1))})}},lt=class extends ie{static{i(this,"AbstractFilesCommandInvocationBase")}constructor(e,n){super(e),this.abstractFiles=n}},Jn=class extends cn{static{i(this,"ArrayDelegatingAbstractFileCommandInvocation")}constructor(e,n,r){super(e,n),this.createCommandInvocationForFiles=r}canExecute(){return super.canExecute()&&this.createCommandInvocationForFiles([this.abstractFile]).invoke(!0)}async execute(){await this.createCommandInvocationForFiles([this.abstractFile]).invokeAsync(!1)}},bl=class extends lt{static{i(this,"SequentialAbstractFilesCommandInvocationBase")}constructor(e,n,r){super(e,n),this.createCommandInvocationForFile=r}canExecute(){return super.canExecute()&&this.abstractFiles.length>0&&this.abstractFiles.every(e=>this.createCommandInvocationForFile(e).invoke(!0))}async execute(){for(let e of this.abstractFiles)await this.createCommandInvocationForFile(e).invokeAsync(!1)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var co=class extends cn{static{i(this,"FolderCommandInvocationBase")}get folder(){return Kr(this._abstractFile)}canExecute(){return super.canExecute()&&!!this.folder}};var uo=class extends kt{static{i(this,"FolderCommandBase")}constructor(e){super(e)}createCommandInvocation(e){let n=qr(e??null)??this.app.workspace.getActiveFile()?.parent??null;return this.createCommandInvocationForFolder(n)}createCommandInvocationForAbstractFile(e){return this.createCommandInvocationForFolder(qr(e))}createCommandInvocationForAbstractFiles(e){return this.createCommandInvocationForFolders(ws(e))}createCommandInvocationForFolders(e){return new yl(this.plugin,e,this.createCommandInvocationForFolder.bind(this))}shouldAddToAbstractFileMenu(e,n,r){return Ve(e)?this.shouldAddToFolderMenu(e,n,r):!1}shouldAddToAbstractFilesMenu(e,n,r){return e.every(o=>Ve(o))?this.shouldAddToFoldersMenu(ws(e),n,r):!1}shouldAddToFolderMenu(e,n,r){return!1}shouldAddToFoldersMenu(e,n,r){return!1}},wl=class extends lt{static{i(this,"FoldersCommandInvocationBase")}constructor(e,n){super(e,n),this.folders=n}},yl=class extends wl{static{i(this,"SequentialFoldersCommandInvocationBase")}constructor(e,n,r){super(e,n),this.createCommandInvocationForFolder=r}canExecute(){return super.canExecute()&&this.folders.length>0&&this.folders.every(e=>this.createCommandInvocationForFolder(e).invoke(!0))}async execute(){for(let e of this.folders)await this.createCommandInvocationForFolder(e).invokeAsync(!1)}};var kl=class extends co{static{i(this,"CollectAttachmentsInFolderCommandInvocation")}constructor(e,n){super(e,n)}async execute(){Yn(this.plugin,[this.folder]),await Promise.resolve()}},po=class extends uo{static{i(this,"CollectAttachmentsInCurrentFolderCommand")}constructor(e){super({icon:"download",id:"collect-attachments-in-current-folder",name:E(n=>n.commands.collectAttachmentsCurrentFolder),plugin:e})}createCommandInvocationForFolder(e){return new kl(this.plugin,e)}};var Cl=class extends lt{static{i(this,"CollectAttachmentsInFilesCommandInvocation")}constructor(e,n){super(e,n)}canExecute(){if(!super.canExecute())return!1;for(let e of this.abstractFiles)if(Z(e)&&!Oe(this.app,e))return!1;return!0}async execute(){Yn(this.plugin,this.abstractFiles)}},ho=class extends kt{static{i(this,"CollectAttachmentsInFileCommand")}constructor(e){super({fileMenuItemName:E(n=>n.menuItems.collectAttachmentsInFile),filesMenuItemName:E(n=>n.menuItems.collectAttachmentsInFiles),icon:"download",id:"collect-attachments-in-file",name:E(n=>n.commands.collectAttachmentsCurrentNote),plugin:e})}createCommandInvocationForAbstractFile(e){return new Jn(this.plugin,e,this.createCommandInvocationForAbstractFiles.bind(this))}createCommandInvocationForAbstractFiles(e){return new Cl(this.plugin,e)}shouldAddToAbstractFileMenu(){return!0}shouldAddToAbstractFilesMenu(){return!0}};var Al=class extends ie{static{i(this,"ConvertAllEmbedsPathsToRelativeCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.convertAllEmbedsPathsToRelative()}},fo=class extends se{static{i(this,"ConvertAllEmbedsPathsToRelativeCommand")}constructor(e){super({icon:"activity",id:"convert-all-embed-paths-to-relative",name:"Convert all embed paths to relative",plugin:e})}createCommandInvocation(){return new Al(this.plugin)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Ct=class extends cn{static{i(this,"FileCommandInvocationBase")}get file(){return jr(this._abstractFile)}constructor(e,n){super(e,n)}canExecute(){return super.canExecute()&&!!this._abstractFile}};var At=class extends kt{static{i(this,"FileCommandBase")}constructor(e){super(e)}createCommandInvocation(e){return this.createCommandInvocationForAbstractFile(e??this.app.workspace.getActiveFile())}createCommandInvocationForAbstractFile(e){return this.createCommandInvocationForFile(ys(e))}createCommandInvocationForAbstractFiles(e){return this.createCommandInvocationForFiles(bs(e))}createCommandInvocationForFiles(e){return new vl(this.plugin,e,this.createCommandInvocationForFile.bind(this))}shouldAddToAbstractFileMenu(e,n,r){return Z(e)?this.shouldAddToFileMenu(e,n,r):!1}shouldAddToAbstractFilesMenu(e,n,r){return e.every(o=>Z(o))?this.shouldAddToFilesMenu(bs(e),n,r):!1}shouldAddToFileMenu(e,n,r){return!1}shouldAddToFilesMenu(e,n,r){return!1}},xl=class extends lt{static{i(this,"FilesCommandInvocationBase")}constructor(e,n){super(e,n),this.files=n}},vl=class extends xl{static{i(this,"SequentialFilesCommandInvocationBase")}constructor(e,n,r){super(e,n),this.createCommandInvocationForFile=r}canExecute(){return super.canExecute()&&this.files.length>0&&this.files.every(e=>this.createCommandInvocationForFile(e).invoke(!0))}async execute(){for(let e of this.files)await this.createCommandInvocationForFile(e).invokeAsync(!1)}};var El=class extends Ct{static{i(this,"ConvertAllEmbedsPathsToRelativeCurrentNoteCommandInvocation")}constructor(e,n){super(e,n)}async execute(){this.plugin.convertAllEmbedsPathsToRelativeCurrentNote(this.file),await Promise.resolve()}},mo=class extends At{static{i(this,"ConvertAllEmbedsPathsToRelativeCurrentNoteCommand")}constructor(e){super({icon:"activity",id:"convert-all-embed-paths-to-relative-current-note",name:"Convert all embed paths to relative in current note",plugin:e})}createCommandInvocationForFile(e){return new El(this.plugin,e)}};var Sl=class extends ie{static{i(this,"ConvertAllLinkPathsToRelativeCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.convertAllLinkPathsToRelative(this.plugin.abortSignal)}},go=class extends se{static{i(this,"ConvertAllLinkPathsToRelativeCommand")}constructor(e){super({icon:"activity",id:"convert-all-link-paths-to-relative",name:"Convert all link paths to relative",plugin:e})}createCommandInvocation(){return new Sl(this.plugin)}};var Pl=class extends Ct{static{i(this,"ConvertAllLinkPathsToRelativeCurrentNoteCommandInvocation")}constructor(e,n){super(e,n)}async execute(){this.plugin.convertAllLinkPathsToRelativeCurrentNote(this.file),await Promise.resolve()}},bo=class extends At{static{i(this,"ConvertAllLinkPathsToRelativeCurrentNoteCommand")}constructor(e){super({icon:"activity",id:"convert-all-link-paths-to-relative-current-note",name:"Convert all link paths to relative in current note",plugin:e})}createCommandInvocationForFile(e){return new Pl(this.plugin,e)}};var Tl=class extends ie{static{i(this,"DeleteEmptyFoldersCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.deleteEmptyFolders()}},wo=class extends se{static{i(this,"DeleteEmptyFoldersCommand")}constructor(e){super({icon:"trash",id:"delete-empty-folders",name:"Delete empty folders",plugin:e})}createCommandInvocation(){return new Tl(this.plugin)}};var ko=require("obsidian");var Qn=require("obsidian");var Fl=class extends Qn.Modal{constructor(n,r,o,s,a){super(n);this.attachmentPath=r;this.backlinks=o;this.resolve=s;this.isCancelMode=a}static{i(this,"MoveAttachmentToProperFolderUsedByMultipleNotesModal")}isSelected=!1;selectedBacklinks=new Set;onClose(){this.isSelected||this.select("Cancel",!1)}onOpen(){super.onOpen(),te(()=>this.onOpenAsync())}async onOpenAsync(){new Qn.Setting(this.contentEl).setName(E(o=>o.moveAttachmentToProperFolderUsedByMultipleNotesModal.heading)).setHeading(),this.contentEl.appendChild(await no(async o=>{o.appendText(E(s=>s.moveAttachmentToProperFolderUsedByMultipleNotesModal.content.part1)),o.appendText(" "),o.appendChild(await qn(this.app,this.attachmentPath)),o.appendText(" "),o.appendText(E(s=>s.moveAttachmentToProperFolderUsedByMultipleNotesModal.content.part2)),o.createEl("br"),o.appendText(E(s=>s.moveAttachmentToProperFolderUsedByMultipleNotesModal.content.part3)),o.createEl("br");for(let s of this.backlinks)this.selectedBacklinks.add(s),o.createEl("br"),o.createEl("input",{attr:{checked:!0},type:"checkbox"}),o.appendChild(await qn(this.app,s));o.createEl("br"),o.createEl("br")}));let n=!1;this.isCancelMode||new Qn.Setting(this.contentEl).setName(E(o=>o.moveAttachmentToProperFolderUsedByMultipleNotesModal.shouldUseSameActionForOtherProblematicAttachmentsToggle)).addToggle(o=>{o.setValue(!1),o.onChange(s=>{n=s})});let r=new Qn.Setting(this.contentEl);this.isCancelMode||r.addButton(o=>{o.setButtonText(E(s=>s.buttons.skip)),o.onClick(()=>{this.select("Skip",n)})}).addButton(o=>{o.setButtonText(E(s=>s.buttons.copyAll)),o.onClick(()=>{this.select("CopyAll",n)})}).addButton(o=>{o.setButtonText(E(s=>s.buttons.select)),o.onClick(()=>{this.select("Prompt",n)})}),r.addButton(o=>{o.setButtonText(E(s=>s.obsidianDevUtils.buttons.cancel)),o.onClick(()=>{this.select("Cancel",n)})})}select(n,r){this.isSelected=!0,this.resolve({backlinksToCopy:Array.from(this.selectedBacklinks).sort((o,s)=>o.localeCompare(s)),mode:n,shouldUseSameActionForOtherProblematicAttachments:r}),this.close()}};function Il(t,e,n,r){return new Promise(o=>{new Fl(t,e,n,o,r??!1).open()})}i(Il,"selectMode");var Ml=class extends lt{static{i(this,"MoveAttachmentToProperFolderCommandInvocation")}constructor(e,n){super(e,n)}canExecute(){if(!super.canExecute())return!1;for(let e of this.abstractFiles)if(Z(e)&&Nr(this.plugin,e))return!1;return!0}async execute(){let e=new Set;for(let a of this.abstractFiles)Z(a)&&!Nr(this.plugin,a)&&e.add(a),Ve(a)&&ko.Vault.recurseChildren(a,l=>{Z(l)&&!Nr(this.plugin,l)&&e.add(l)});let n=Array.from(e);n.sort((a,l)=>a.path.localeCompare(l.path));let r=new AbortController,o=nt(r.signal,this.plugin.abortSignal),s={};await gt({abortSignal:o,buildNoticeMessage:i((a,l)=>E(c=>c.moveAttachmentToProperFolder.progressBar.message,{attachmentFilePath:a.path,iterationStr:l}),"buildNoticeMessage"),items:n,processItem:i(async a=>{if(o.throwIfAborted(),this.plugin.settings.isPathIgnored(a.path)){console.warn(`Cannot move attachment to proper folder as attachment path is ignored: ${a.path}.`);return}await this.moveAttachmentToProperFolder(a,s)&&o.throwIfAborted()},"processItem"),progressBarTitle:`${this.plugin.manifest.name}: ${E(a=>a.moveAttachmentToProperFolder.progressBar.title)}`,shouldContinueOnError:!0,shouldShowProgressBar:!0})}async moveAttachmentToProperFolder(e,n){let r=await Be(this.plugin.app,e);if(r.keys().length===0)return new ko.Notice(E(l=>l.moveAttachmentToProperFolder.unusedAttachment,{attachmentPath:e.path})),!0;let o=[],s=this;if(r.keys().length>1&&!await a(n.mode??this.plugin.settings.moveAttachmentToProperFolderUsedByMultipleNotesMode))return!1;for(let l of o){let c=this.plugin.app.vault.getFileByPath(l);if(!c)continue;let u=r.get(l)?.[0];if(!u)continue;let d=await fl({actionContext:"MoveAttachmentToProperFolder",attachmentFile:e,noteFilePath:l,plugin:this.plugin,reference:u});if(!d){console.warn(`Skipping moving attachment ${e.path} to proper folder as it is already in the destination folder.`);continue}let p=new Set((r.get(l)??[]).map(h=>Kt(h)));await zn(this.plugin.app,e,d),await on(this.plugin.app,c,h=>{let f=Kt(h);if(p.has(f))return sn({app:this.plugin.app,link:h,newSourcePathOrFile:c,newTargetPathOrFile:d,oldTargetPathOrFile:e})})}return r=await Be(this.plugin.app,e),r.keys().length===0&&await Ft(this.plugin.app,e),!0;async function a(l){switch(l){case"Cancel":return s.plugin.settings.moveAttachmentToProperFolderUsedByMultipleNotesMode==="Cancel"&&await Il(s.plugin.app,e.path,Array.from(r.keys()),!0),!1;case"CopyAll":return o=Array.from(r.keys()),!0;case"Prompt":{let{backlinksToCopy:c,mode:u,shouldUseSameActionForOtherProblematicAttachments:d}=await Il(s.plugin.app,e.path,Array.from(r.keys()));return d&&(n.mode=u),u==="Prompt"?(o=c,!0):a(u)}case"Skip":return o=[],!0;default:return!1}}i(a,"handleMode")}},yo=class extends kt{static{i(this,"MoveAttachmentToProperFolderCommand")}constructor(e){super({icon:"move",id:"move-attachment-to-proper-folder",name:E(n=>n.commands.moveAttachmentToProperFolder),plugin:e})}createCommandInvocationForAbstractFile(e){return new Jn(this.plugin,e,this.createCommandInvocationForAbstractFiles.bind(this))}createCommandInvocationForAbstractFiles(e){return new Ml(this.plugin,e)}shouldAddToAbstractFileMenu(){return!0}shouldAddToAbstractFilesMenu(){return!0}};var Ll=class extends ie{static{i(this,"ReorganizeVaultCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.reorganizeVault()}},Co=class extends se{static{i(this,"ReorganizeVaultCommand")}constructor(e){super({icon:"sort-asc",id:"reorganize-vault",name:"Reorganize vault",plugin:e})}createCommandInvocation(){return new Ll(this.plugin)}};var Nl=class extends ie{static{i(this,"ReplaceAllWikiEmbedsWithMarkdownEmbedsCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.replaceAllWikiEmbedsWithMarkdownEmbeds()}},Ao=class extends se{static{i(this,"ReplaceAllWikiEmbedsWithMarkdownEmbedsCommand")}constructor(e){super({icon:"replace",id:"replace-all-wiki-embeds-with-markdown-embeds",name:"Replace all wiki embeds with Markdown embeds",plugin:e})}createCommandInvocation(){return new Nl(this.plugin)}};var Ol=class extends Ct{static{i(this,"ReplaceAllWikiEmbedsWithMarkdownEmbedsCurrentNoteCommandInvocation")}constructor(e,n){super(e,n)}async execute(){this.plugin.replaceAllWikiEmbedsWithMarkdownEmbedsCurrentNote(this.file),await Promise.resolve()}},xo=class extends At{static{i(this,"ReplaceAllWikiEmbedsWithMarkdownEmbedsCurrentNoteCommand")}constructor(e){super({icon:"replace",id:"replace-all-wiki-embeds-with-markdown-embeds-current-note",name:"Replace all wiki embeds with Markdown embeds in current note",plugin:e})}createCommandInvocationForFile(e){return new Ol(this.plugin,e)}};var Rl=class extends ie{static{i(this,"ReplaceAllWikilinksWithMarkdownLinksCommandInvocation")}constructor(e){super(e)}async execute(){await this.plugin.replaceAllWikilinksWithMarkdownLinks()}},vo=class extends se{static{i(this,"ReplaceAllWikilinksWithMarkdownLinksCommand")}constructor(e){super({icon:"replace",id:"replace-all-wikilinks-with-markdown-links",name:"Replace all wikilinks with markdown links",plugin:e})}createCommandInvocation(){return new Rl(this.plugin)}};var Dl=class extends Ct{static{i(this,"ReplaceAllWikilinksWithMarkdownLinksCurrentNoteCommandInvocation")}constructor(e,n){super(e,n)}async execute(){this.plugin.replaceAllWikilinksWithMarkdownLinksCurrentNote(this.file),await Promise.resolve()}},Eo=class extends At{static{i(this,"ReplaceAllWikilinksWithMarkdownLinksCurrentNoteCommand")}constructor(e){super({icon:"replace",id:"replace-all-wikilinks-with-markdown-links-current-note",name:"Replace all wikilinks with markdown links in current note",plugin:e})}createCommandInvocationForFile(e){return new Dl(this.plugin,e)}};var wL=require("obsidian");var So=require("obsidian");var Bt=class extends Map{constructor(n){super();this.title=n}static{i(this,"ConsistencyCheckResult")}add(n,r){this.has(n)||this.set(n,[]);let o=this.get(n);o&&o.push(r)}toString(n,r){if(this.size>0){let o=`# ${this.title} (${String(this.size)} files) +`;for(let s of this.keys()){let a=X(n,s);if(!a)continue;let l=Xi({app:n,sourcePathOrFile:r,targetPathOrFile:a});o+=`${l}: +`;for(let c of this.get(s)??[])tt(c)?o+=`- (line ${String(c.position.start.line+1)}): \`${c.link}\` +`:Ee(c)&&(o+=`- (key ${c.key}): \`${c.link}\` +`);o+=` + +`}return o}return`# ${this.title} +No problems found + +`}},Xn=class{constructor(e){this.plugin=e;}static{i(this,"LinksHandler")}async checkConsistency(e,n,r,o,s,a){if(this.plugin.settings.isPathIgnored(e.path))return;let l=await Xe(this.plugin.app,e.path);if(!l)return;let c=l.links??[],u=l.embeds??[],d=l.frontmatterLinks??[];for(let p of c)await this.isValidLink(p,e.path)||n.add(e.path,p),Mr(p.original)&&o.add(e.path,p);for(let p of u)await this.isValidLink(p,e.path)||r.add(e.path,p),Mr(p.original)&&s.add(e.path,p);for(let p of d)await this.isValidLink(p,e.path)||a.add(e.path,p)}async convertAllNoteEmbedsPathsToRelative(e,n){return await this.convertAllNoteRefPathsToRelative(e,!0,n)}async convertAllNoteLinksPathsToRelative(e,n){return await this.convertAllNoteRefPathsToRelative(e,!1,n)}async getCachedNotesThatHaveLinkToFile(e){let n=X(this.plugin.app,e);return n?(await Be(this.plugin.app,n)).keys():[]}getFullPathForLink(e,n){({linkPath:e}=Dt(e));let r=K(n);return oe(r,e)}async replaceAllNoteWikilinksWithMarkdownLinks(e,n,r){if(this.plugin.settings.isPathIgnored(e))return 0;let o=X(this.plugin.app,e);if(!o)return console.warn(`can't update wikilinks in note, file not found: ${e}`),0;let s=await Xe(this.plugin.app,o);if(r.throwIfAborted(),!s)return 0;let l=((n?s.embeds:s.links)??[]).filter(c=>Mr(c.original)).length;return await eo({app:this.plugin.app,linkStyle:Xa.Markdown,newSourcePathOrFile:o,shouldUpdateEmbedOnlyLinks:n}),l}async updateChangedPathsInNote(e,n){if(this.plugin.settings.isPathIgnored(e))return;let r=X(this.plugin.app,e);if(!r){console.warn(`can't update links in note, file not found: ${e}`);return}let o=new Map;for(let s of n)o.set(s.oldPath,s.newPath);await this.updateLinks(r,r.path,o)}async convertAllNoteRefPathsToRelative(e,n,r){if(this.plugin.settings.isPathIgnored(e))return[];let o=X(this.plugin.app,e);if(!o)return[];let s=[];return await Tr(this.plugin.app,o,async(a,l)=>{let c=await Xe(this.plugin.app,o);a.throwIfAborted();let u=await this.plugin.app.vault.cachedRead(o);if(a.throwIfAborted(),l!==u)return null;if(!c)return[];let d=(n?c.embeds:c.links)??[],p=[];for(let h of d){let f=this.convertLink({forceRelativePath:!0,link:h,note:o,oldNotePath:e});p.push(nn(h,f)),s.push({newLink:f,old:h})}return p},{abortSignal:r}),s}convertLink({forceRelativePath:e,link:n,note:r,oldNotePath:o,pathChangeMap:s}){let{linkPath:a,subpath:l}=Dt(n.link),c=Ke(this.plugin.app,n,o)?.path??oe(K(o),a),u=s?s.get(c):Ke(this.plugin.app,n,r.path)?.path??oe(K(r.path),a);if(!u)return n.original;let d=X(this.plugin.app,u)??X(this.plugin.app,c);if(!d)return n.original;let p=n.displayText&&oe(r.parent?.path??"",n.displayText)===c?void 0:n.displayText;return Xi({alias:p,app:this.plugin.app,linkPathStyle:e?Qi.RelativePathToTheSource:Qi.ObsidianSettingsDefault,originalLink:n.original,sourcePathOrFile:r.path,subpath:l,targetPathOrFile:d})}async isValidLink(e,n){let{linkPath:r,subpath:o}=Dt(e.link),s;r?r.startsWith("/")?s=(0,So.normalizePath)(r):s=oe(K(n),r):s=n;let a=X(this.plugin.app,s);if(!a)return!1;if(!o)return!0;let l=a.extension.toLocaleLowerCase();if(l==="pdf")return o.startsWith("#page=");if(l!==Ht)return!1;let c=await Xe(this.plugin.app,a);return c?!!(0,So.resolveSubpath)(c,o):!1}async updateLinks(e,n,r){await Tr(this.plugin.app,e,async(o,s)=>{o.throwIfAborted();let a=await Xe(this.plugin.app,e);o.throwIfAborted();let l=await this.plugin.app.vault.cachedRead(e);return o.throwIfAborted(),s!==l?null:a?je(a).map(u=>nn(u,this.convertLink({link:u,note:e,oldNotePath:n,pathChangeMap:r}))):[]})}};var Zn=class{constructor(e,n){this.plugin=e;this.lh=n;}static{i(this,"FilesHandler")}async collectAttachmentsForCachedNote(e){if(this.plugin.settings.isPathIgnored(e))return{movedAttachments:[]};let n={movedAttachments:[]},r=await Xe(this.plugin.app,e);if(!r)return n;for(let o of je(r)){let{linkPath:s}=Dt(o.link);if(!s)continue;let a=this.lh.getFullPathForLink(s,e);if(n.movedAttachments.findIndex(d=>d.oldPath===a)!==-1)continue;let l=Ke(this.plugin.app,o,e);if(!l){let d=Zi(o.original)?"embed":"link";console.warn(`${e} has bad ${d} (file does not exist): ${s}`);continue}if(this.isNoteEx(l)||this.plugin.settings.isExcludedFromAttachmentCollecting(l.path))continue;let c=await Gt({app:this.plugin.app,context:"consistent-attachments-and-links",notePathOrFile:e,oldAttachmentPathOrFile:l,shouldSkipDuplicateCheck:!0});if(K(c)===K(l.path))continue;let u=await this.moveAttachment(l,c,[e]);n.movedAttachments=n.movedAttachments.concat(u.movedAttachments)}return n}async deleteEmptyFolders(e){if(this.plugin.settings.isPathIgnored(e))return;e=Wr(e,"./");let n=await Wn(this.plugin.app,e);for(let r of n.folders)await this.deleteEmptyFolders(r);if(n=await Wn(this.plugin.app,e),n.files.length===0&&n.folders.length===0&&(this.plugin.consoleDebug(`delete empty folder: + ${e}`),await this.plugin.app.vault.exists(e)))try{await this.plugin.app.vault.adapter.rmdir(e,!1)}catch(r){if(await this.plugin.app.vault.adapter.exists(e))throw r}}isNoteEx(e){if(!e||!Oe(this.plugin.app,e))return!1;let n=G(this.plugin.app,e);return this.plugin.settings.treatAsAttachmentExtensions.every(r=>!n.endsWith(r))}async createFolderForAttachmentFromPath(e){await Vn(this.plugin.app,K(e))}async deleteFile(e){if(await Tt(this.plugin.app,e),!!e.parent)switch(this.plugin.settings.emptyFolderBehavior){case Ae.Delete:await Ft(this.plugin.app,e.parent,void 0,void 0,!0);break;case Ae.DeleteWithEmptyParents:await Pr(this.plugin.app,e.parent);break;default:break}}async moveAttachment(e,n,r){let o=e.path,s={movedAttachments:[]};if(this.plugin.settings.isPathIgnored(o)||this.isNoteEx(e))return s;if(o===n)return console.warn("Can't move file. Source and destination path the same."),s;await this.createFolderForAttachmentFromPath(n);let a=await this.lh.getCachedNotesThatHaveLinkToFile(o);for(let d of r)a.remove(d);if(o!==e.path)return console.warn("File was moved already"),await this.moveAttachment(e,n,r);let l=e.parent,c=a.length===0,u=X(this.plugin.app,n);if(u&&(this.plugin.settings.shouldDeleteExistingFilesWhenMovingNote?(this.plugin.consoleDebug(`delete: ${n}`),await this.deleteFile(u)):n=ji(this.plugin.app,n)),this.plugin.consoleDebug(`${c?"move":"copy"} + from: ${o} + to: ${n}`),s.movedAttachments.push({newPath:n,oldPath:o}),c?await Hn(this.plugin.app,e,n):await zn(this.plugin.app,e,n),l)switch(this.plugin.settings.emptyFolderBehavior){case Ae.Delete:await Ft(this.plugin.app,l,void 0,void 0,!0);break;case Ae.DeleteWithEmptyParents:await Pr(this.plugin.app,l);break;default:break}return s}};var Dp={attachmentCollector:{confirm:{part1:"Do you want to collect attachments for all notes in folders recursively?",part2:"This operation cannot be undone."},progressBar:{message:"Collecting attachments {{iterationStr}} - '{{noteFilePath}}'.",title:"Collecting attachments..."}},buttons:{copy:"Copy",copyAll:"Copy all",move:"Move",previewAttachmentFile:"Preview attachment file",select:"Select",skip:"Skip"},collectAttachmentUsedByMultipleNotesModal:{content:{part1:"Attachment",part2:"is referenced by multiple notes."},heading:"Collecting attachment used by multiple notes",shouldUseSameActionForOtherProblematicAttachmentsToggle:"Should use the same action for other problematic attachments"},commands:{collectAttachmentsCurrentFolder:"Collect attachments in current folder",collectAttachmentsCurrentNote:"Collect attachments in current note",collectAttachmentsEntireVault:"Collect attachments in entire vault",moveAttachmentToProperFolder:"Move attachment to proper folder"},menuItems:{collectAttachmentsInFile:"Collect attachments in file",collectAttachmentsInFiles:"Collect attachments in files"},moveAttachmentToProperFolder:{progressBar:{message:"Moving attachment to proper folder {{iterationStr}} - '{{attachmentFilePath}}'.",title:"Moving attachment to proper folder..."},unusedAttachment:"Attachment {{attachmentPath}} is not used by any note. It will not be moved."},moveAttachmentToProperFolderUsedByMultipleNotesModal:{content:{part1:"Attachment",part2:"is referenced by multiple notes.",part3:"Select notes to copy the attachment to."},heading:"Collecting attachment used by multiple notes",shouldUseSameActionForOtherProblematicAttachmentsToggle:"Should use the same action for other problematic attachments"},notice:{collectingAttachments:"Collecting attachments for '{{noteFilePath}}'",collectingAttachmentsCancelled:"Collecting attachments cancelled. See console for details.",generatedAttachmentFileNameIsInvalid:{part1:`Generated attachment file name '{{path}}' is invalid. +{{validationMessage}} +Check your`,part2:"setting."},notePathIsIgnored:"Note path is ignored"},obsidianDevUtils:{buttons:{cancel:"Cancel",ok:"OK"},dataview:{itemsPerPage:"Items per page:",jumpToPage:"Jump to page:"},notices:{attachmentIsStillUsed:"Attachment {{attachmentPath}} is still used by other notes. It will not be deleted.",unhandledError:"An unhandled error occurred. Please check the console for more information."}},pluginSettings:{attachmentRenameMode:{all:{description:"all files are renamed.",displayText:"All"},none:{description:"their names are preserved.",displayText:"None"},onlyPastedImages:{description:"only pasted images are renamed. Applies only when the PNG image content is pasted from the clipboard directly. Typically, for pasting screenshots.",displayText:"Only pasted images"}},collectAttachmentUsedByMultipleNotesMode:{cancel:{description:"cancel the attachment collecting.",displayText:"Cancel"},copy:{description:"copy the attachment to the new location.",displayText:"Copy"},move:{description:"move the attachment to the new location.",displayText:"Move"},prompt:{description:"prompt the user to choose the action.",displayText:"Prompt"},skip:{description:"skip the attachment and proceed to the next one.",displayText:"Skip"}},defaultImageSizeDimension:{height:"Height",width:"Width"},emptyAttachmentFolderBehavior:{delete:{description:"will delete the empty attachment folder.",displayText:"Delete"},deleteWithEmptyParents:{description:"will delete the empty attachment folder and its empty parent folders.",displayText:"Delete with empty parents"},keep:{description:"will keep the empty attachment folder.",displayText:"Keep"}},moveAttachmentToProperFolderUsedByMultipleNotesMode:{cancel:{description:"cancel the attachment collecting.",displayText:"Cancel"},copyAll:{description:"copy the attachment to the new location for all notes.",displayText:"Copy all"},prompt:{description:"prompt the user to choose the action.",displayText:"Prompt"},skip:{description:"skip the attachment and proceed to the next one.",displayText:"Skip"}}},pluginSettingsManager:{customToken:{codeComment:`// Custom tokens were commented out as they have to be updated to the new format introduced in plugin version 9.0.0. +// Refer to the documentation (https://github.com/RainCat1998/obsidian-custom-attachment-location?tab=readme-ov-file#custom-tokens) for more information.`,deprecated:{part1:"In plugin version 9.0.0, the format of custom token registration changed. Please update your tokens accordingly. Refer to the",part2:"documentation",part3:"for more information"}},legacyRenameAttachmentsToLowerCase:{part1:"In plugin version 9.0.0, the",part2:"setting is deprecated. Use",part3:"format instead. See",part4:"documentation",part5:"for more information"},markdownUrlFormat:{deprecated:{part1:"You have potentially incorrect value set for the",part2:"format. Please refer to the",part3:"documentation",part4:"for more information",part5:"This message will not be shown again."}},specialCharacters:{part1:"In plugin version 9.16.0, the",part2:"default setting value was changed. Your setting value was updated to the new default value."},validation:{defaultImageSizeMustBePercentageOrPixels:"Default image size must be in pixels or percentage",invalidCustomTokensCode:"Invalid custom tokens code",invalidRegularExpression:"Invalid regular expression {{regExp}}",specialCharactersMustNotContainSlash:"Special characters must not contain /",specialCharactersReplacementMustNotContainInvalidFileNamePathCharacters:"Special character replacement must not contain invalid file name path characters."}},pluginSettingsTab:{attachmentRenameMode:{description:{part1:"When attaching files:"},name:"Attachment rename mode"},collectAttachmentUsedByMultipleNotesMode:{description:{part1:"When the collected attachment is used by multiple notes:"},name:"Collect attachment used by multiple notes mode"},collectedAttachmentFileName:{description:{part1:"See available",part2:"tokens",part3:"Leave empty to use",part4:"setting instead."},name:"Collected attachment file name"},customTokens:{description:{part1:"Custom tokens to be used.",part2:"See",part3:"documentation",part4:"for more information.",part5:"\u26A0\uFE0F Custom tokens can be an arbitrary JavaScript code. If poorly written, it can cause the data loss. Use it at your own risk."},name:"Custom tokens"},defaultImageSize:{description:{part1:"The default image size.",part2:"Can be specified in pixels",part3:"or percentage of the full image size",part4:"Leave blank to use the original image size."},name:"Default image size"},duplicateNameSeparator:{description:{part1:"When you are pasting/dragging a file with the same name as an existing file, this separator will be added to the file name.",part2:"E.g., when you are dragging file",part3:", it will be renamed to ",part4:", etc, getting the first name available."},name:"Duplicate name separator"},emptyAttachmentFolderBehavior:{description:{part1:"When the attachment folder becomes empty:"},name:"Empty attachment folder behavior"},excludePaths:{description:{part1:"Exclude notes from the following paths.",part2:"Insert each path on a new line.",part3:"You can use path string or",part4:"If the setting is empty, no notes are excluded."},name:"Exclude paths"},excludePathsFromAttachmentCollecting:{description:{part1:"Exclude attachments from the following paths when",part2:"Collect attachments",part3:"command is executed.",part4:"Insert each path on a new line.",part5:"You can use path string or",part6:"If the setting is empty, no paths are excluded from attachment collecting."},name:"Exclude paths from attachment collecting"},generatedAttachmentFileName:{description:{part1:"See available",part2:"tokens"},name:"Generated attachment file name"},includePaths:{description:{part1:"Include notes from the following paths.",part2:"Insert each path on a new line.",part3:"You can use path string or",part4:"If the setting is empty, all notes are included."},name:"Include paths"},jpegQuality:{description:"The smaller the quality, the greater the compression ratio.",name:"JPEG Quality"},locationForNewAttachments:{description:{part1:"Start with",part2:"to use relative path.",part3:"See available",part4:"tokens",part5:"Dot-folders like",part6:"are not recommended, because Obsidian does not track them. You might need to use",part7:"Plugin to manage them."},name:"Location for new attachments"},markdownUrlFormat:{description:{part1:"Format for the URL that will be inserted into Markdown.",part2:"See available",part3:"tokens",part4:"Leave blank to use the default format."},name:"Markdown URL format"},moveAttachmentToProperFolderUsedByMultipleNotesMode:{description:{part1:"When the attachment is used by multiple notes:"},name:"Move attachment to proper folder used by multiple notes mode"},renameAttachmentsToLowerCase:"Rename attachments to lower case",renamedAttachmentFileName:{description:{part1:"See available",part2:"tokens",part3:"Leave empty to use",part4:"setting instead."},name:"Renamed attachment file name"},resetToSampleCustomTokens:{message:"Are you sure you want to reset the custom tokens to the sample custom tokens? Your changes will be lost.",title:"Reset to sample custom tokens"},shouldConvertPastedImagesToJpeg:{description:"Whether to convert pasted images to JPEG. Applies only when the PNG image content is pasted from the clipboard directly. Typically, for pasting screenshots.",name:"Should convert pasted images to JPEG"},shouldDeleteOrphanAttachments:{description:"If enabled, when the note is deleted, its orphan attachments are deleted as well.",name:"Should delete orphan attachments"},shouldHandleRenames:{description:"Whether to handle renames.",name:"Should handle renames"},shouldRenameAttachmentFiles:{description:{part1:"If enabled, when a note is renamed or moved, its attachments will be renamed according to the",part2:"setting."},name:"Should rename attachment files"},shouldRenameAttachmentFolders:{description:"Whether to rename attachment folders when a note is renamed or moved.",name:"Should rename attachment folders"},shouldRenameCollectedAttachments:{description:{part1:"If enabled, attachments processed via",part2:"Collect attachments",part3:"commands will be renamed according to the",part4:"setting."},name:"Should rename collected attachments"},specialCharacters:{description:{part1:"Special characters in attachment folder and file name to be replaced or removed.",part2:"Leave blank to preserve special characters."},name:"Special characters"},specialCharactersReplacement:{description:{part1:"Replacement string for special characters in attachment folder and file name.",part2:"Leave blank to remove special characters."},name:"Special characters replacement"},timeoutInSeconds:{description:{part1:"The timeout in seconds for all operations.",part2:"If",part3:"is set, the operations execution timeout is disabled."},name:"Timeout in seconds"},treatAsAttachmentExtensions:{description:{part1:"Treat files with these extensions as attachments.",part2:"By default",part3:"and",part4:"linked files are not treated as attachments and are not moved with the note.",part5:"You can add custom extensions, e.g.",part6:", to override this behavior."},name:"Treat as attachment extensions"}},promptWithPreviewModal:{previewModal:{title:"Preview attachment file '{{fullFileName}}'"},title:"Provide a value for the prompt token"},regularExpression:"/regular expression/"};var Bp=Dp;var Xb={en:Bp},_p=Xb;i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var _t=class{static{i(this,"Transformer")}getTransformer(e){if(e===this.id)return this;throw new Error(`Transformer with id ${e} not found`)}transformObjectRecursively(e){return this.transformValueRecursively(e,"")}getTransformerId(e,n){return this.canTransform(e,n)?this.id:null}transformValueRecursively(e,n){let r=this.getTransformerId(e,n);if(r){let a=this.transformValue(e,n);return a===void 0?void 0:{__transformerId:r,transformedValue:a}}if(e===null)return null;if(typeof e!="object")return e;if(Array.isArray(e))return e.map((a,l)=>this.transformValueRecursively(a,String(l)));let o=e;if(o.__transformerId)return this.getTransformer(o.__transformerId).restoreValue(o.transformedValue,n);let s={};for(let a of vn(e)){let l=e[a],c=this.transformValueRecursively(l,a);s[a]=c}return s}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Ze=class extends _t{static{i(this,"TypedTransformer")}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Po=class extends Ze{static{i(this,"DateTransformer")}get id(){return"date"}canTransform(e){return e instanceof Date}restoreValue(e){return new Date(e)}transformValue(e){return e.toISOString()}};var $p=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var To=class extends Ze{static{i(this,"DurationTransformer")}get id(){return"duration"}canTransform(e){let n=e??{};return!!n.asHours&&!!n.asMinutes&&!!n.asSeconds&&!!n.asMilliseconds}restoreValue(e){return $p.moment.duration(e)}transformValue(e){return e.toISOString()}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Fo=class extends _t{static{i(this,"GroupTransformer")}constructor(e){super(),this.transformers=e}get id(){return"group"}canTransform(e,n){return this.getFirstTransformerThatCanTransform(e,n)!==null}getTransformer(e){return ee(this.transformers.find(n=>n.id===e),`No transformer with id ${e} found`)}transformValue(e,n){let r=this.getFirstTransformerThatCanTransform(e,n);return Ge(r,"No transformer can transform the value"),r.transformValue(e,n)}getTransformerId(e,n){let r=this.getFirstTransformerThatCanTransform(e,n);return r===null?null:r.id}restoreValue(){throw new Error("GroupTransformer does not support restoring values")}getFirstTransformerThatCanTransform(e,n){return this.transformers.find(r=>r.canTransform(e,n))??null}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Io=class extends Ze{static{i(this,"MapTransformer")}get id(){return"map"}canTransform(e){return e instanceof Map}restoreValue(e){return new Map(e)}transformValue(e){return Array.from(e.entries())}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Mo=class extends Ze{static{i(this,"SetTransformer")}get id(){return"set"}canTransform(e){return e instanceof Set}restoreValue(e){return new Set(e)}transformValue(e){return Array.from(e)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Zb="_",Lo=class extends _t{static{i(this,"SkipPrivatePropertyTransformer")}get id(){return"skip-private-property"}canTransform(e,n){return n.startsWith(Zb)}transformValue(){}restoreValue(){throw new Error("SkipPrivatePropertyTransformer does not support restoring values")}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Or=class{static{i(this,"TwoWayMap")}keyValueMap=new Map;valueKeyMap=new Map;constructor(e=[]){for(let[n,r]of e)this.set(n,r)}clear(){this.keyValueMap.clear(),this.valueKeyMap.clear()}deleteKey(e){let n=this.getValue(e);n!==void 0&&this.valueKeyMap.delete(n),this.keyValueMap.delete(e)}deleteValue(e){let n=this.getKey(e);n!==void 0&&this.keyValueMap.delete(n),this.valueKeyMap.delete(e)}entries(){return this.keyValueMap.entries()}getKey(e){return this.valueKeyMap.get(e)}getValue(e){return this.keyValueMap.get(e)}hasKey(e){return this.keyValueMap.has(e)}hasValue(e){return this.valueKeyMap.has(e)}keys(){return this.keyValueMap.keys()}set(e,n){this.deleteKey(e),this.deleteValue(n),this.keyValueMap.set(e,n),this.valueKeyMap.set(n,e)}values(){return this.valueKeyMap.keys()}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var No=class extends Ze{static{i(this,"TwoWayMapTransformer")}get id(){return"two-way-map"}canTransform(e){return e instanceof Or}restoreValue(e){return new Or(e)}transformValue(e){return Array.from(e.entries())}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ew=new Fo([new Lo,new Po,new To,new Io,new Mo,new No]),Oo=class extends pt{static{i(this,"PluginSettingsManagerBase")}constructor(e){super(),this.plugin=e,this.app=e.app,this.defaultSettings=this.createDefaultSettings(),this.currentSettingsWrapper=this.createDefaultSettingsWrapper(),this.lastSavedSettingsWrapper=this.createDefaultSettingsWrapper(),this.propertyNames=vn(this.currentSettingsWrapper.settings),this.registerValidators(),this.registerLegacySettingsConverters()}app;defaultSettings;get settingsWrapper(){return this.currentSettingsWrapper}currentSettingsWrapper;lastSavedSettingsWrapper;legacySettingsConverters=[];propertyNames;validators=new Map;async editAndSave(e,n){await this.edit(e),await this.saveToFile(n)}async ensureSafe(e){let n=await this.validate(e);for(let r of this.propertyNames)n[r]&&(e[r]=this.defaultSettings[r])}async getSafeCopy(e){let n=await this.cloneSettings(e);return await this.ensureSafe(n),n}async loadFromFile(e){let n=await this.plugin.loadData();this.lastSavedSettingsWrapper=this.createDefaultSettingsWrapper(),this.currentSettingsWrapper=this.createDefaultSettingsWrapper();try{if(n==null)return;if(typeof n!="object"){console.error(`Invalid settings from data.json. Expected Object, got: ${typeof n}`);return}let r=n,o=await this.rawRecordToSettings(r),s=await this.validate(o);for(let l of this.propertyNames)this.setPropertyImpl(l,o[l],s[l]);this.lastSavedSettingsWrapper=await this.cloneSettingsWrapper(this.currentSettingsWrapper);let a=await this.settingsToRawRecord(this.currentSettingsWrapper.settings);Je(a,n)||await this.saveToFileImpl()}finally{await this.triggerAsync("loadSettings",this.currentSettingsWrapper,e)}}on(e,n,r){return super.on(e,n,r)}async revalidate(){return await this.edit(Me),this.currentSettingsWrapper.validationMessages}async saveToFile(e){Je(this.lastSavedSettingsWrapper.settings,this.currentSettingsWrapper.settings)||(await this.saveToFileImpl(),await this.triggerAsync("saveSettings",this.currentSettingsWrapper,this.lastSavedSettingsWrapper,e),this.lastSavedSettingsWrapper=await this.cloneSettingsWrapper(this.currentSettingsWrapper))}async setProperty(e,n){return await this.edit(r=>{r[e]=n}),this.currentSettingsWrapper.validationMessages[e]}async validate(e){let n={};for(let[r,o]of this.validators.entries()){let s=await o(e[r],e);s&&(n[r]=s)}return n}getTransformer(){return ew}async onLoadRecord(e){for(let n of this.legacySettingsConverters)n(e);await Promise.resolve()}async onSavingRecord(e){await ut()}registerLegacySettingsConverter(e,n){let r=this;this.legacySettingsConverters.push(o);function o(s){let a=new Set(Object.keys(new e)),l=new Set(r.propertyNames),c=s;n(c);for(let u of Object.keys(c))l.has(u)||a.has(u)&&delete s[u]}i(o,"legacySettingsConverter")}registerLegacySettingsConverters(){}registerValidator(e,n){this.validators.set(e,n)}registerValidators(){}async cloneSettings(e){let n=await this.settingsToRawRecord(e),r=JSON.stringify(n),o=JSON.parse(r);return await this.rawRecordToSettings(o)}async cloneSettingsWrapper(e){return{safeSettings:await this.cloneSettings(e.safeSettings),settings:await this.cloneSettings(e.settings),validationMessages:{...e.validationMessages}}}createDefaultSettingsWrapper(){return{safeSettings:this.createDefaultSettings(),settings:this.createDefaultSettings(),validationMessages:{}}}async edit(e){try{await e(this.currentSettingsWrapper.settings)}finally{let n=await this.validate(this.currentSettingsWrapper.settings);for(let r of this.propertyNames){let o=n[r]??"";this.currentSettingsWrapper.validationMessages[r]=o,this.currentSettingsWrapper.safeSettings[r]=o?this.defaultSettings[r]:this.currentSettingsWrapper.settings[r]}}}isValidPropertyName(e){return typeof e!="string"?!1:this.propertyNames.includes(e)}async rawRecordToSettings(e){e=this.getTransformer().transformObjectRecursively(e),await this.onLoadRecord(e);let n=this.createDefaultSettings();for(let[r,o]of Object.entries(e)){if(!this.isValidPropertyName(r)){Y("PluginSettingsManagerBase:rawRecordToSettings")(`Unknown property: ${r}`);continue}typeof o!=typeof this.defaultSettings[r]&&Y("PluginSettingsManagerBase:rawRecordToSettings")("Possible invalid value type. It might lead to an unexpected behavior of the plugin. There is also a chance it is a false-negative warning, as we are unable to determine the exact type of the value in runtime.",{defaultValue:this.defaultSettings[r],propertyName:r,value:o}),n[r]=o}return n}async saveToFileImpl(){await this.plugin.saveData(await this.settingsToRawRecord(this.currentSettingsWrapper.settings))}setPropertyImpl(e,n,r){this.currentSettingsWrapper.settings[e]=n,this.currentSettingsWrapper.validationMessages[e]=r??"",this.currentSettingsWrapper.safeSettings[e]=r?this.defaultSettings[e]:n}async settingsToRawRecord(e){let n={};for(let r of this.propertyNames)n[r]=e[r];return await this.onSavingRecord(n),this.getTransformer().transformObjectRecursively(n)}};var Bl=class{static{i(this,"LegacySettings")}autoCollectAttachments=!1;changeNoteBacklinksAlt=!1;deleteAttachmentsWithNote=!1;deleteEmptyFolders=!1;deleteExistFilesWhenMoveNote=!1;emptyAttachmentFolderBehavior=Ae.DeleteWithEmptyParents;ignoreFiles=[];ignoreFolders=[];moveAttachmentsWithNote=!1;showBackupWarning=!1;updateLinks=!1},Ro=class extends Oo{static{i(this,"PluginSettingsManager")}createDefaultSettings(){return new io}registerLegacySettingsConverters(){this.registerLegacySettingsConverter(Bl,e=>{let n=e.excludePaths??[];if(e.ignoreFiles)for(let r of e.ignoreFiles)n.push(`/${r}$/`);if(e.ignoreFolders)for(let r of e.ignoreFolders??[])n.push(r);n.length>0&&(e.excludePaths=n),e.deleteEmptyFolders!==void 0&&(e.emptyFolderBehavior=e.deleteEmptyFolders?Ae.DeleteWithEmptyParents:Ae.Keep),e.emptyAttachmentFolderBehavior!==void 0&&(e.emptyFolderBehavior=e.emptyAttachmentFolderBehavior),e.autoCollectAttachments!==void 0&&(e.shouldCollectAttachmentsAutomatically=e.autoCollectAttachments),e.changeNoteBacklinksAlt!==void 0&&(e.shouldChangeNoteBacklinksDisplayText=e.changeNoteBacklinksAlt),e.deleteAttachmentsWithNote!==void 0&&(e.shouldDeleteAttachmentsWithNote=e.deleteAttachmentsWithNote),e.deleteExistFilesWhenMoveNote!==void 0&&(e.shouldDeleteExistingFilesWhenMovingNote=e.deleteExistFilesWhenMoveNote),e.moveAttachmentsWithNote!==void 0&&(e.shouldMoveAttachmentsWithNote=e.moveAttachmentsWithNote),e.showBackupWarning!==void 0&&(e.shouldShowBackupWarning=e.showBackupWarning),e.updateLinks!==void 0&&(e.shouldUpdateLinks=e.updateLinks)})}registerValidators(){super.registerValidators(),this.registerValidator("includePaths",zp),this.registerValidator("excludePaths",zp)}};function zp(t){for(let e of t)if(e.startsWith("/")&&e.endsWith("/")){let n=e.slice(1,-1);if(!lc(n))return`Invalid regular expression ${e}`}}i(zp,"pathsValidator");var sh=require("obsidian");var un=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Do(t){let e=t.parentElement;if(Ge(e,"Element must be attached to the DOM"),e.classList.contains(M.SettingComponentWrapper))return e;let n=Array.from(e.children),r=createDiv();q(r,M.SettingComponentWrapper);for(let o of n)r.appendChild(o);return e.appendChild(r),r}i(Do,"ensureWrapped");var Vp=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var _l=class{static{i(this,"AbstractTextComponentWrapper")}constructor(e){this.abstractTextComponent=e}empty(){this.abstractTextComponent.setValue("")}isEmpty(){return this.abstractTextComponent.getValue()===""}setPlaceholderValue(e){return this.abstractTextComponent.setPlaceholder(e),this}};function Up(t){return tw(t)?t:t instanceof Vp.AbstractTextComponent?new _l(t):null}i(Up,"getTextBasedComponentValue");function tw(t){let e=t;return typeof e.setPlaceholderValue=="function"&&typeof e.isEmpty=="function"}i(tw,"isTextBasedComponent");var xe=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Bo=class{static{i(this,"OverlayValidatorComponent")}constructor(e){this.el=e;let n=Do(e);this._validatorEl=n.createEl("input",{attr:{tabindex:-1}}),q(this._validatorEl,M.OverlayValidator),this._validatorEl.addEventListener("focus",()=>{this.el.focus()}),this._validatorEl.isActiveElement=this.isElementOrDescendantActive.bind(this);let r=this.el.querySelector("[tabindex]");r||(this.el.getAttr("tabindex")===null&&(this.el.tabIndex=-1),r=this.el),this.el.addEventListener("focusin",()=>{this.forceBlurValidatorEl()}),this.el.addEventListener("click",()=>{r.focus()}),this.el.addEventListener("focusout",()=>{window.setTimeout(()=>{this.isElementOrDescendantActive()||this.forceBlurValidatorEl()},0)})}get validatorEl(){return this._validatorEl}_validatorEl;forceBlurValidatorEl(){this._validatorEl.dispatchEvent(new Event("blur"))}isElementOrDescendantActive(){return this.el.contains(document.activeElement)}},$t=class{static{i(this,"ValidatorElementWrapper")}constructor(e){this.validatorEl=e}};function Wp(t){return nw(t)?t:t instanceof xe.ColorComponent?new $t(t.colorPickerEl):t instanceof xe.DropdownComponent?new $t(t.selectEl):t instanceof xe.ProgressBarComponent?new Bo(t.progressBar):t instanceof xe.SearchComponent?new $t(t.inputEl):t instanceof xe.SliderComponent?new $t(t.sliderEl):t instanceof xe.TextAreaComponent?new $t(t.inputEl):t instanceof xe.TextComponent?new $t(t.inputEl):t instanceof xe.ToggleComponent?new Bo(t.toggleEl):null}i(Wp,"getValidatorComponent");function nw(t){return!!t.validatorEl}i(nw,"isValidatorComponent");var rw=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();function Hp(t){return t.validationMessage!==void 0}i(Hp,"isValidationMessageHolder");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var $l="PluginSettingsTab",_o=class extends un.PluginSettingTab{static{i(this,"PluginSettingsTabBase")}constructor(e){super(e.app,e),this.plugin=e,q(this.containerEl,M.PluginSettingsTab),this.saveSettingsDebounced=(0,un.debounce)(Pn(()=>this.plugin.settingsManager.saveToFile($l)),this.saveSettingsDebounceTimeoutInMilliseconds),this.asyncEventsComponent=new hi,this.asyncEvents=new pt}get isOpen(){return this._isOpen}get saveSettingsDebounceTimeoutInMilliseconds(){return 2e3}_isOpen=!1;asyncEvents;asyncEventsComponent;saveSettingsDebounced;get pluginSettings(){return this.plugin.settingsManager.settingsWrapper.settings}bind(e,n,r){let s={...{componentToPluginSettingsValueConverter:i(P=>P,"componentToPluginSettingsValueConverter"),onChanged:Me,pluginSettingsToComponentValueConverter:i(P=>P,"pluginSettingsToComponentValueConverter"),shouldResetSettingWhenComponentIsEmpty:!0,shouldShowPlaceholderForDefaultValues:!0,shouldShowValidationMessage:!0},...r},a=Wp(e)?.validatorEl,l=Up(e),c=this.pluginSettings[n],u=this.plugin.settingsManager.defaultSettings[n],d=s.pluginSettingsToComponentValueConverter(u);l?.setPlaceholderValue(d);let p,h=null,f=null;if(a){let P=Do(a);h=P.createDiv(),q(h,M.Tooltip,M.TooltipValidator),f=h.createSpan();let I=h.createDiv();q(I,M.TooltipArrow),h.hide(),P.appendChild(h)}this.asyncEventsComponent.registerAsyncEvent(this.on("validationMessageChanged",(P,I)=>{n===P&&(p=I,A())}));let b=!1,k=!1;l&&s.shouldShowPlaceholderForDefaultValues&&Je(c,u)?l.empty():e.setValue(s.pluginSettingsToComponentValueConverter(c));let y=!1,A=(0,un.debounce)(()=>{requestAnimationFrame(()=>{v()})},100);return e.onChange(async P=>{if(y){y=!1;return}b=!1;let I=this.pluginSettings[n],C,$=!0;if(k=!!l?.isEmpty()&&s.shouldResetSettingWhenComponentIsEmpty,k)C=u;else{let H=s.componentToPluginSettingsValueConverter(P);Hp(H)?(p=H.validationMessage,$=!1):C=H}$&&(p=await this.plugin.settingsManager.setProperty(n,C),l&&s.shouldShowPlaceholderForDefaultValues&&!l.isEmpty()&&Je(C,u)&&(b=!0)),A(),$&&await s.onChanged(C,I),this.saveSettingsDebounced()}),a?.addEventListener("focus",()=>{A()}),a?.addEventListener("blur",()=>{A()}),a?.addEventListener("click",()=>{requestAnimationFrame(()=>{A()})}),p=this.plugin.settingsManager.settingsWrapper.validationMessages[n]??"",A(),e;function v(){a?.isActiveElement()||(b?(b=!1,l?.isEmpty()||(y=!0,l?.empty())):k&&(k=!1,l?.isEmpty()&&(y=!0,e.setValue(d)))),a&&(p===""&&(a.setCustomValidity(""),a.checkValidity(),p=a.validationMessage),a.setCustomValidity(p),s.shouldShowValidationMessage?(f&&(f.textContent=p),h?.toggle(!!p)):p&&(0,un.setTooltip)(a,p))}i(v,"updateValidatorEl")}display(){this.containerEl.empty(),this._isOpen=!0,this.asyncEventsComponent.load(),this.asyncEventsComponent.registerAsyncEvent(this.plugin.settingsManager.on("loadSettings",this.onLoadSettings.bind(this))),this.asyncEventsComponent.registerAsyncEvent(this.plugin.settingsManager.on("saveSettings",this.onSaveSettings.bind(this)))}hide(){super.hide(),this.saveSettingsDebounced.cancel(),this._isOpen=!1,this.asyncEventsComponent.unload(),this.asyncEventsComponent.load(),te(()=>this.hideAsync())}async hideAsync(){await this.plugin.settingsManager.saveToFile($l)}show(){this.app.setting.openTab(this)}async onLoadSettings(e,n){this.display(),await ut()}async revalidate(){let e=await this.plugin.settingsManager.revalidate();await this.updateValidations(e)}on(e,n,r){return this.asyncEvents.on(e,n,r)}async onSaveSettings(e,n,r){if(r===$l){await this.updateValidations(e.validationMessages);return}this.display()}async updateValidations(e){for(let[n,r]of Object.entries(e))await this.asyncEvents.triggerAsync("validationMessageChanged",n,r)}};var Rr=require("obsidian");var jp=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var $o=class extends jp.ValueComponent{static{i(this,"CheckboxComponent")}inputEl;get validatorEl(){return this.inputEl}changeCallback;constructor(e){super(),q(e,M.CheckboxComponent),this.inputEl=e.createEl("input",{type:"checkbox"}),this.inputEl.addEventListener("change",this.onChanged.bind(this))}getValue(){return this.inputEl.checked}onChange(e){return this.changeCallback=e,this}onChanged(){this.changeCallback?.(this.getValue())}setDisabled(e){return super.setDisabled(e),this.inputEl.disabled=e,this}setValue(e){return this.inputEl.checked=e,this}};var Vo=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var zo=class extends Vo.ValueComponent{static{i(this,"CodeHighlighterComponent")}get inputEl(){return this.textAreaComponent.inputEl}get validatorEl(){return this.inputEl}codeEl;placeholder="";preEl;simulateChangeCallback;tabSize;textAreaComponent;constructor(e){super(),q(e,M.CodeHighlighterComponent);let n=e.createDiv();q(n,M.SettingComponentWrapper),this.textAreaComponent=new Vo.TextAreaComponent(n),this.preEl=n.createEl("pre",{attr:{tabIndex:"-1"}}),this.codeEl=this.preEl.createEl("code",{attr:{tabIndex:"-1"}}),this.inputEl.addEventListener("input",Pn(this.updateHighlightedCode.bind(this))),this.inputEl.addEventListener("scroll",this.handleScroll.bind(this)),this.inputEl.addEventListener("keydown",this.handleKeyDown.bind(this));let r=2;this.tabSize=r}empty(){this.setValue("")}getValue(){return this.textAreaComponent.getValue()}isEmpty(){return this.textAreaComponent.getValue()===""}onChange(e){let n=i(()=>{e(this.getValue())},"changeHandler");return this.simulateChangeCallback=n,this.textAreaComponent.onChange(n),this}setDisabled(e){return super.setDisabled(e),this.textAreaComponent.setDisabled(e),this}setLanguage(e){let n="language-";for(let r of[this.preEl,this.codeEl]){for(let o of Array.from(r.classList))o.startsWith(n)&&r.classList.remove(o);r.classList.add(`${n}${e}`)}return this}setPlaceholder(e){return this.placeholder=e,te(this.updateHighlightedCode.bind(this)),this}setPlaceholderValue(e){return this.setPlaceholder(e),this}setTabSize(e){return this.tabSize=e,this}setValue(e){return this.textAreaComponent.setValue(e),te(this.updateHighlightedCode.bind(this)),this}simulateChange(){this.simulateChangeCallback?.()}handleKeyDown(e){if(e.key!=="Tab")return;if(e.preventDefault(),e.ctrlKey||e.metaKey){let d=Array.from(activeDocument.querySelectorAll(':is(a, button, input, select, textarea, [tabindex]):not([tabindex="-1"]):not(:disabled):not([type="hidden"])')),p=d.indexOf(this.inputEl),h=e.shiftKey?-1:1;d[(p+h+d.length)%d.length]?.focus();return}let n=this.getValue(),r=this.inputEl.selectionStart,o=this.inputEl.selectionEnd,s=n.slice(0,r),a=n.slice(o),l=" ".repeat(this.tabSize),c=s;e.shiftKey?s.endsWith(l)&&(c=s.slice(0,-this.tabSize)):c=s+l;let u=`${c}${a}`;this.setValue(u),this.inputEl.selectionStart=c.length,this.inputEl.selectionEnd=c.length}handleScroll(){this.preEl.scrollTop=this.inputEl.scrollTop,this.preEl.scrollLeft=this.inputEl.scrollLeft}async updateHighlightedCode(){this.codeEl.textContent=this.inputEl.value||this.placeholder,(await Zl()).highlightElement(this.codeEl),this.preEl.toggleClass(M.IsPlaceholder,this.isEmpty()),requestAnimationFrame(()=>{let n=Math.max(0,this.inputEl.scrollHeight-this.preEl.scrollHeight);this.preEl.setCssProps({"--bottom-gap":Fp(n)}),this.handleScroll()})}};var Gp=require("obsidian");var Uo=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ue=class extends Uo.ValueComponent{static{i(this,"TypedTextComponent")}inputEl;get validatorEl(){return this.inputEl}textComponent;constructor(e,n,r){super(),this.textComponent=new Uo.TextComponent(e),this.inputEl=this.textComponent.inputEl,this.inputEl.type=n,q(e,r)}getValue(){return this.valueFromString(this.textComponent.getValue())}onChange(e){return this.textComponent.onChange(()=>e(this.getValue())),this}onChanged(){this.textComponent.onChanged()}setDisabled(e){return super.setDisabled(e),this.textComponent.setDisabled(e),this}setValue(e){return this.textComponent.setValue(this.valueToString(e)),this}valueToString(e){return String(e)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var _e=class extends ue{static{i(this,"TypedRangeTextComponent")}setMax(e){return this.inputEl.max=this.valueToString(e),this}setMin(e){return this.inputEl.min=this.valueToString(e),this}setStep(e){return this.inputEl.step=String(e),this}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Kp=It(Gp.moment),qp="YYYY-MM-DD",Wo=class extends _e{static{i(this,"DateComponent")}constructor(e){super(e,"date",M.DateComponent)}valueFromString(e){return Kp(e,qp).toDate()}valueToString(e){return Kp(e).format(qp)}};var Qp=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Yp=It(Qp.moment),Jp="YYYY-MM-DDTHH:mm",Ho=class extends _e{static{i(this,"DateTimeComponent")}constructor(e){super(e,"datetime-local",M.DateTimeComponent)}valueFromString(e){return Yp(e,Jp).toDate()}valueToString(e){return Yp(e).format(Jp)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var jo=class extends ue{static{i(this,"EmailComponent")}constructor(e){super(e,"email",M.EmailComponent)}empty(){this.setValue("")}isEmpty(){return this.getValue()===""}setPlaceholderValue(e){return this.textComponent.setPlaceholder(e),this}valueFromString(e){return e}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Ko=class extends ue{static{i(this,"FileComponent")}constructor(e){super(e,"file",M.FileComponent)}getValue(){return this.inputEl.files?.[0]??null}valueFromString(){return this.getValue()}valueToString(e){return e?.name??""}};var eh=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Xp=It(eh.moment),Zp="YYYY-MM",qo=class extends _e{static{i(this,"MonthComponent")}constructor(e){super(e,"month",M.MonthComponent)}valueFromString(e){let n=Xp(e,Zp);if(!n.isValid())throw new Error("Invalid month");return{month:n.month()+1,year:n.year()}}valueToString(e){return Xp().year(e.year).month(e.month-1).format(Zp)}};var Go=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var er=class extends Go.ValueComponent{static{i(this,"MultipleDropdownComponent")}get selectEl(){return this.dropdownComponent.selectEl}get validatorEl(){return this.selectEl}dropdownComponent;simulateChangeCallback;constructor(e){super(),this.dropdownComponent=new Go.DropdownComponent(e),this.dropdownComponent.selectEl.multiple=!0,q(e,M.MultipleDropdownComponent)}addOption(e,n){return this.dropdownComponent.addOption(e,n),this}addOptions(e){return this.dropdownComponent.addOptions(e),this}getValue(){return Array.from(this.dropdownComponent.selectEl.selectedOptions).map(e=>e.value)}onChange(e){let n=i(()=>{e(this.getValue())},"changeHandler");return this.simulateChangeCallback=n,this.dropdownComponent.onChange(n),this}setDisabled(e){return super.setDisabled(e),this.dropdownComponent.setDisabled(e),this}setValue(e){for(let n of Array.from(this.dropdownComponent.selectEl.options))n.selected=e.includes(n.value);return this}simulateChange(){this.simulateChangeCallback?.()}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Yo=class extends ue{static{i(this,"MultipleEmailComponent")}constructor(e){super(e,"email",M.MultipleEmailComponent),this.inputEl.multiple=!0}valueFromString(e){return e.split(",").map(n=>n.trim())}valueToString(e){return e.join(", ")}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Jo=class extends ue{static{i(this,"MultipleFileComponent")}constructor(e){super(e,"file",M.MultipleFileComponent),this.inputEl.multiple=!0}getValue(){return Array.from(this.inputEl.files??[])}valueFromString(){return this.getValue()}valueToString(e){return e[0]?.name??""}};var Xo=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Qo=class extends Xo.ValueComponent{static{i(this,"MultipleTextComponent")}get inputEl(){return this.textAreaComponent.inputEl}get validatorEl(){return this.inputEl}simulateChangeCallback;textAreaComponent;constructor(e){super(),this.textAreaComponent=new Xo.TextAreaComponent(e),q(e,M.MultipleTextComponent)}empty(){this.textAreaComponent.setValue("")}getValue(){return this.textAreaComponent.getValue().split(` +`)}isEmpty(){return this.textAreaComponent.getValue()===""}onChange(e){let n=i(()=>{e(this.getValue())},"changeHandler");return this.simulateChangeCallback=n,this.textAreaComponent.onChange(n),this}setDisabled(e){return super.setDisabled(e),this.textAreaComponent.setDisabled(e),this}setPlaceholder(e){return this.textAreaComponent.setPlaceholder(e),this}setPlaceholderValue(e){return this.setPlaceholder(this.valueToString(e)),this}setValue(e){return this.textAreaComponent.setValue(this.valueToString(e)),this}simulateChange(){this.simulateChangeCallback?.()}valueToString(e){return e.join(` +`)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var Zo=class extends _e{static{i(this,"NumberComponent")}constructor(e){super(e,"number",M.NumberComponent)}empty(){this.textComponent.setValue("")}isEmpty(){return this.textComponent.getValue()===""}setPlaceholder(e){return this.textComponent.setPlaceholder(e),this}setPlaceholderValue(e){return this.textComponent.setPlaceholder(this.valueToString(e)),this}valueFromString(e){return parseInt(e,10)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var es=class extends ue{static{i(this,"PasswordComponent")}constructor(e){super(e,"password",M.PasswordComponent)}setPlaceholder(e){return this.textComponent.setPlaceholder(e),this}valueFromString(e){return e}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ts=class extends ue{static{i(this,"TelephoneComponent")}constructor(e){super(e,"tel",M.TelephoneComponent)}empty(){this.textComponent.setValue("")}isEmpty(){return this.textComponent.getValue()===""}setPlaceholderValue(e){return this.textComponent.setPlaceholder(e),this}valueFromString(e){return e}};var zl=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ns=class extends _e{static{i(this,"TimeComponent")}constructor(e){super(e,"time",M.TimeComponent)}valueFromString(e){return zl.moment.duration(e)}valueToString(e){let n;return e.milliseconds()>0?n="HH:mm:ss.SSS":e.seconds()>0?n="HH:mm:ss":n="HH:mm",zl.moment.utc(e.asMilliseconds()).format(n)}};var th=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var rs=class extends th.ValueComponent{static{i(this,"TriStateCheckboxComponent")}inputEl;get validatorEl(){return this.inputEl}changeCallback;constructor(e){super(),q(e,M.TriStateCheckboxComponent),this.inputEl=e.createEl("input",{type:"checkbox"}),this.inputEl.addEventListener("change",this.onChanged.bind(this))}getValue(){return this.inputEl.indeterminate?null:this.inputEl.checked}onChange(e){return this.changeCallback=e,this}onChanged(){this.changeCallback?.(this.getValue())}setDisabled(e){return super.setDisabled(e),this.inputEl.disabled=e,this}setValue(e){return this.inputEl.indeterminate=e===null,this.inputEl.checked=e??!1,this}};var os=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var is=class extends os.ValueComponent{static{i(this,"TypedDropdownComponent")}get selectEl(){return this.dropdownComponent.selectEl}get validatorEl(){return this.selectEl}dropdownComponent;simulateChangeCallback;values=[];constructor(e){super(),this.dropdownComponent=new os.DropdownComponent(e),q(e,M.TypedDropdownComponent)}addOption(e,n){let r=this.values.indexOf(e);return r===-1&&(this.values.push(e),r=this.values.length-1),this.dropdownComponent.addOption(String(r),n),this}addOptions(e){for(let[n,r]of e.entries())this.addOption(n,r);return this}getValue(){return this.values[this.dropdownComponent.selectEl.selectedIndex]??null}onChange(e){let n=i(()=>{e(this.getValue())},"changeHandler");return this.simulateChangeCallback=n,this.dropdownComponent.onChange(n),this}setDisabled(e){return super.setDisabled(e),this.dropdownComponent.setDisabled(e),this}setValue(e){let n=e===null?-1:this.values.indexOf(e);return this.dropdownComponent.selectEl.selectedIndex=n,this}simulateChange(){this.simulateChangeCallback?.()}};var nh=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ss=class extends nh.ValueComponent{static{i(this,"TypedMultipleDropdownComponent")}get selectEl(){return this.multipleDropdownComponent.selectEl}get validatorEl(){return this.selectEl}multipleDropdownComponent;simulateChangeCallback;values=[];constructor(e){super(),this.multipleDropdownComponent=new er(e),q(e,M.TypedMultipleDropdownComponent)}addOption(e,n){let r=this.values.indexOf(e);return r===-1&&(this.values.push(e),r=this.values.length-1),this.multipleDropdownComponent.addOption(String(r),n),this}addOptions(e){for(let[n,r]of e.entries())this.addOption(n,r);return this}getValue(){return this.multipleDropdownComponent.getValue().map(n=>parseInt(n,10)).map(n=>this.values[n]).filter(n=>n!==void 0)}onChange(e){let n=i(()=>{e(this.getValue())},"changeHandler");return this.simulateChangeCallback=n,this.multipleDropdownComponent.onChange(n),this}setDisabled(e){return super.setDisabled(e),this.multipleDropdownComponent.setDisabled(e),this}setValue(e){let n=e.map(r=>this.values.indexOf(r)).filter(r=>r!==-1);return this.multipleDropdownComponent.setValue(n.map(r=>String(r))),this}simulateChange(){this.simulateChangeCallback?.()}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var as=class extends ue{static{i(this,"UrlComponent")}constructor(e){super(e,"url",M.UrlComponent)}empty(){this.setValue("")}isEmpty(){return this.getValue()===""}setPlaceholderValue(e){return this.textComponent.setPlaceholder(e),this}valueFromString(e){return e}};var oh=require("obsidian");i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var rh=It(oh.moment),ih="YYYY-[W]WW",ls=class extends _e{static{i(this,"WeekComponent")}constructor(e){super(e,"week",M.WeekComponent)}valueFromString(e){let n=rh(e,ih);if(!n.isValid())throw new Error("Invalid week");return{weekNumber:n.isoWeek(),year:n.year()}}valueToString(e){return rh().year(e.year).isoWeek(e.weekNumber).format(ih)}};i((function(){if(globalThis.process)return;let e={browser:!0,cwd(){return"/"},env:{},platform:"android"};globalThis.process=e}),"initEsm")();var ge=class extends Rr.Setting{static{i(this,"SettingEx")}addCheckbox(e){return this.addComponentClass($o,e)}addCodeHighlighter(e){return this.addComponentClass(zo,e)}addComponentClass(e,n){return this.addComponentSafe(r=>{let o=new e(r);return n(o),o})}addDate(e){return this.addComponentClass(Wo,e)}addDateTime(e){return this.addComponentClass(Ho,e)}addEmail(e){return this.addComponentClass(jo,e)}addFile(e){return this.addComponentClass(Ko,e)}addMonth(e){return this.addComponentClass(qo,e)}addMultipleDropdown(e){return this.addComponentClass(er,e)}addMultipleEmail(e){return this.addComponentClass(Yo,e)}addMultipleFile(e){return this.addComponentClass(Jo,e)}addMultipleText(e){return this.addComponentClass(Qo,e)}addNumber(e){return this.addComponentClass(Zo,e)}addPassword(e){return this.addComponentClass(es,e)}addTelephone(e){return this.addComponentClass(ts,e)}addTime(e){return this.addComponentClass(ns,e)}addTriStateCheckbox(e){return this.addComponentClass(rs,e)}addTypedDropdown(e){return this.addComponentClass(is,e)}addTypedMultipleDropdown(e){return this.addComponentClass(ss,e)}addUrl(e){return this.addComponentClass(as,e)}addWeek(e){return this.addComponentClass(ls,e)}addComponentSafe(e){return(0,Rr.requireApiVersion)("1.11.0")?this.addComponent(n=>((0,Rr.requireApiVersion)("0.16.0"),e(n))):(this.components.push(e(this.controlEl)),this)}};var cs=class extends _o{static{i(this,"PluginSettingsTab")}display(){super.display(),this.containerEl.empty();let e="Move Attachments with Note";new ge(this.containerEl).setName(e).setDesc("Automatically move attachments when a note is relocated. This includes attachments located in the same folder or any of its subfolders.").addToggle(s=>this.bind(s,"shouldMoveAttachmentsWithNote",{onChanged:i(async()=>{await this.checkDangerousSetting("shouldMoveAttachmentsWithNote",e)},"onChanged")}));let n="Delete Unused Attachments with Note";new ge(this.containerEl).setName(n).setDesc("Automatically remove attachments that are no longer referenced in other notes when the note is deleted.").addToggle(s=>this.bind(s,"shouldDeleteAttachmentsWithNote",{onChanged:i(async()=>{await this.checkDangerousSetting("shouldDeleteAttachmentsWithNote",n)},"onChanged")})),new ge(this.containerEl).setName("Update links").setDesc("Automatically update links to attachments and other notes when moving notes or attachments.").addToggle(s=>this.bind(s,"shouldUpdateLinks")),new ge(this.containerEl).setName("Empty folder behavior").setDesc(createFragment(s=>{s.appendText("When the folder becomes empty, "),s.createEl("br"),ne(s,"Keep"),s.appendText(" - will keep the empty folder, "),s.createEl("br"),ne(s,"Delete"),s.appendText(" - will delete the empty folder, "),s.createEl("br"),ne(s,"Delete with empty parents"),s.appendText(" - will delete the empty folder and its empty parent folders.")})).addDropdown(s=>{s.addOptions({[Ae.Keep]:"Keep",[Ae.Delete]:"Delete",[Ae.DeleteWithEmptyParents]:"Delete with empty parents"}),this.bind(s,"emptyFolderBehavior")});let r="Delete Duplicate Attachments on Note Move";new ge(this.containerEl).setName(r).setDesc("Automatically delete attachments when moving a note if a file with the same name exists in the destination folder. If disabled, the file will be renamed and moved.").addToggle(s=>this.bind(s,"shouldDeleteExistingFilesWhenMovingNote",{onChanged:i(async()=>{await this.checkDangerousSetting("shouldDeleteExistingFilesWhenMovingNote",r)},"onChanged")})),new ge(this.containerEl).setName("Update backlink text on note rename").setDesc("When a note is renamed, its linked references are automatically updated. If this option is enabled, the text of backlinks to this note will also be modified.").addToggle(s=>this.bind(s,"shouldChangeNoteBacklinksDisplayText")),new ge(this.containerEl).setName("Consistency report filename").setDesc("Specify the name of the file for the consistency report.").addText(s=>{this.bind(s,"consistencyReportFile")});let o="Auto Collect Attachments";new ge(this.containerEl).setName(o).setDesc("Automatically collect attachments when the note is edited.").addToggle(s=>this.bind(s,"shouldCollectAttachmentsAutomatically",{onChanged:i(async()=>{await this.checkDangerousSetting("shouldCollectAttachmentsAutomatically",o)},"onChanged")})),new ge(this.containerEl).setName("Include paths").setDesc(createFragment(s=>{s.appendText("Include notes from the following paths"),s.createEl("br"),s.appendText("Insert each path on a new line"),s.createEl("br"),s.appendText("You can use path string or "),ne(s,"/regular expression/"),s.createEl("br"),s.appendText("If the setting is empty, all notes are included")})).addMultipleText(s=>{this.bind(s,"includePaths")}),new ge(this.containerEl).setName("Exclude paths").setDesc(createFragment(s=>{s.appendText("Exclude notes from the following paths"),s.createEl("br"),s.appendText("Insert each path on a new line"),s.createEl("br"),s.appendText("You can use path string or "),ne(s,"/regular expression/"),s.createEl("br"),s.appendText("If the setting is empty, no notes are excluded")})).addMultipleText(s=>{this.bind(s,"excludePaths")}),new ge(this.containerEl).setName("Exclude paths from attachment collecting").setDesc(createFragment(s=>{s.appendText("Exclude attachments from the following paths when "),ne(s,"Collect attachments"),s.appendText(" command is executed."),s.createEl("br"),s.appendText("Insert each path on a new line"),s.createEl("br"),s.appendText("You can use path string or "),ne(s,"/regular expression/"),s.createEl("br"),s.appendText("If the setting is empty, no paths are excluded from attachment collecting.")})).addMultipleText(s=>{this.bind(s,"excludePathsFromAttachmentCollecting")}),new ge(this.containerEl).setName("Treat as attachment extensions").setDesc(createFragment(s=>{s.appendText("Treat files with these extensions as attachments."),s.createEl("br"),s.appendText("By default, "),ne(s,".md"),s.appendText(" and "),ne(s,".canvas"),s.appendText(" linked files are not treated as attachments and are not moved with the note."),s.createEl("br"),s.appendText("You can add custom extensions, e.g. "),ne(s,".foo.md"),s.appendText(", "),ne(s,".bar.canvas"),s.appendText(", to override this behavior."),s.createEl("br"),s.appendText("Insert each extension on a new line.")})).addMultipleText(s=>{this.bind(s,"treatAsAttachmentExtensions")}),new ge(this.containerEl).setName(E(s=>s.pluginSettingsTab.collectAttachmentUsedByMultipleNotesMode.name)).setDesc(createFragment(s=>{s.appendText(E(a=>a.pluginSettingsTab.collectAttachmentUsedByMultipleNotesMode.description.part1)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.skip.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.skip.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.move.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.move.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.copy.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.copy.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.cancel.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.cancel.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.prompt.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.prompt.description))})).addDropdown(s=>{s.addOptions({Skip:E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.skip.displayText),Move:E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.move.displayText),Copy:E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.copy.displayText),Cancel:E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.cancel.displayText),Prompt:E(a=>a.pluginSettings.collectAttachmentUsedByMultipleNotesMode.prompt.displayText)}),this.bind(s,"collectAttachmentUsedByMultipleNotesMode")}),new ge(this.containerEl).setName(E(s=>s.pluginSettingsTab.moveAttachmentToProperFolderUsedByMultipleNotesMode.name)).setDesc(createFragment(s=>{s.appendText(E(a=>a.pluginSettingsTab.moveAttachmentToProperFolderUsedByMultipleNotesMode.description.part1)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.skip.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.skip.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.copyAll.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.copyAll.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.cancel.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.cancel.description)),s.createEl("br"),ne(s,E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.prompt.displayText)),s.appendText(" - "),s.appendText(E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.prompt.description))})).addDropdown(s=>{s.addOptions({Skip:E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.skip.displayText),CopyAll:E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.copyAll.displayText),Cancel:E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.cancel.displayText),Prompt:E(a=>a.pluginSettings.moveAttachmentToProperFolderUsedByMultipleNotesMode.prompt.displayText)}),this.bind(s,"moveAttachmentToProperFolderUsedByMultipleNotesMode")})}async checkDangerousSetting(e,n){this.plugin.settings[e]&&await pi({app:this.app,message:createFragment(r=>{r.createDiv({cls:"community-modal-readme"},o=>{o.appendText("You enabled "),o.createEl("strong",{cls:"markdown-rendered-code",text:n}),o.appendText(" setting. Without proper configuration it might lead to inconvenient attachment rearrangements or even data loss in your vault."),o.createEl("br"),o.appendText("It is "),o.createEl("strong",{text:"STRONGLY"}),o.appendText(" recommended to backup your vault before using the plugin."),o.createEl("br"),o.createEl("a",{href:"https://github.com/dy-sh/obsidian-consistent-attachments-and-links?tab=readme-ov-file",text:"Read more"}),o.appendText(" about how to use the plugin.")})}),title:createFragment(r=>{(0,sh.setIcon)(r.createSpan(),"triangle-alert"),r.appendText(" Consistent Attachments and Links")})})}};var us=class extends bi{static{i(this,"Plugin")}deletedNoteCache=new Map;linksHandler=new Xn(this);filesHandler=new Zn(this,this.linksHandler);async checkConsistency(){await this.saveAllOpenNotes();let e=new Bt("Bad links"),n=new Bt("Bad embeds"),r=new Bt("Wiki links"),o=new Bt("Wiki embeds"),s=new Bt("Bad frontmatter links");await gt({abortSignal:this.abortSignal,buildNoticeMessage:i((d,p)=>`Checking note ${p} - ${d.path}`,"buildNoticeMessage"),items:Un(this.app),processItem:i(async d=>{await this.linksHandler.checkConsistency(d,e,n,r,o,s)},"processItem"),progressBarTitle:"Consistent Attachments and Links: Checking vault consistency...",shouldContinueOnError:!0,shouldShowProgressBar:!0});let a=this.settings.consistencyReportFile,l=[e,n,r,o,s].map(d=>d.toString(this.app,a)).join("");await Vn(this.app,K(a));let c=await gc(this.app,a);await this.app.vault.modify(c,l);let u=!1;this.app.workspace.iterateAllLeaves(d=>{d.getDisplayText()!==""&&a.startsWith(d.getDisplayText())&&(u=!0)}),u||await this.app.workspace.openLinkText(a,"/",!1)}async convertAllEmbedsPathsToRelative(){await this.saveAllOpenNotes();let e=0,n=0;await gt({abortSignal:this.abortSignal,buildNoticeMessage:i((r,o)=>`Converting embed paths to relative ${o} - ${r.path}`,"buildNoticeMessage"),items:Un(this.app),processItem:i(async r=>{if(this.settings.isPathIgnored(r.path))return;let o=await this.linksHandler.convertAllNoteEmbedsPathsToRelative(r.path,this.abortSignal);o.length>0&&(e+=o.length,n++)},"processItem"),progressBarTitle:"Consistent Attachments and Links: Converting embed paths to relative...",shouldContinueOnError:!0,shouldShowProgressBar:!0}),e===0?new $e.Notice("No embeds found that need to be converted"):new $e.Notice(`Converted ${String(e)} embed${e>1?"s":""} from ${String(n)} note${n>1?"s":""}`)}convertAllEmbedsPathsToRelativeCurrentNote(e){Ue({abortSignal:this.abortSignal,app:this.app,operationFn:or(n=>this.linksHandler.convertAllNoteEmbedsPathsToRelative(e.path,n)),operationName:"Convert all embed paths to relative in current note"})}async convertAllLinkPathsToRelative(e){e.throwIfAborted(),await this.saveAllOpenNotes(),e.throwIfAborted();let n=0,r=0;await gt({abortSignal:e,buildNoticeMessage:i((o,s)=>`Converting link paths to relative ${s} - ${o.path}`,"buildNoticeMessage"),items:Un(this.app),processItem:i(async o=>{if(this.settings.isPathIgnored(o.path))return;let s=await this.linksHandler.convertAllNoteLinksPathsToRelative(o.path,e);s.length>0&&(n+=s.length,r++)},"processItem"),progressBarTitle:"Consistent Attachments and Links: Converting link paths to relative...",shouldContinueOnError:!0,shouldShowProgressBar:!0}),n===0?new $e.Notice("No links found that need to be converted"):new $e.Notice(`Converted ${String(n)} link${n>1?"s":""} from ${String(r)} note${r>1?"s":""}`)}convertAllLinkPathsToRelativeCurrentNote(e){Ue({abortSignal:this.abortSignal,app:this.app,operationFn:or(n=>this.linksHandler.convertAllNoteLinksPathsToRelative(e.path,n)),operationName:"Convert all link paths to relative in current note"})}async deleteEmptyFolders(){await this.filesHandler.deleteEmptyFolders("/")}async onLoadSettings(e,n){await super.onLoadSettings(e,n),e.settings.revertDangerousSettings()}async onSaveSettings(e,n,r){await super.onSaveSettings(e,n,r),this.linksHandler=new Xn(this),this.filesHandler=new Zn(this,this.linksHandler)}async reorganizeVault(){await this.saveAllOpenNotes(),await this.replaceAllWikilinksWithMarkdownLinks(),await this.replaceAllWikiEmbedsWithMarkdownEmbeds(),await this.convertAllEmbedsPathsToRelative(),await this.convertAllLinkPathsToRelative(this.abortSignal),oo(this),await this.deleteEmptyFolders(),new $e.Notice("Reorganization of the vault completed")}async replaceAllWikiEmbedsWithMarkdownEmbeds(){await this.saveAllOpenNotes();let e=0,n=0;await gt({abortSignal:this.abortSignal,buildNoticeMessage:i((r,o)=>`Replacing wiki embeds with markdown embeds ${o} - ${r.path}`,"buildNoticeMessage"),items:Un(this.app),processItem:i(async r=>{if(this.settings.isPathIgnored(r.path))return;let o=await this.linksHandler.replaceAllNoteWikilinksWithMarkdownLinks(r.path,!0,this.abortSignal);e+=o,n++},"processItem"),progressBarTitle:"Consistent Attachments and Links: Replacing wiki embeds with markdown embeds...",shouldContinueOnError:!0,shouldShowProgressBar:!0}),e===0?new $e.Notice("No wiki embeds found that need to be replaced"):new $e.Notice(`Replaced ${String(e)} wiki embed${e>1?"s":""} from ${String(n)} note${n>1?"s":""}`)}replaceAllWikiEmbedsWithMarkdownEmbedsCurrentNote(e){Ue({abortSignal:this.abortSignal,app:this.app,operationFn:or(n=>this.linksHandler.replaceAllNoteWikilinksWithMarkdownLinks(e.path,!0,n)),operationName:"Replace all wiki embeds with markdown embeds in current note"})}async replaceAllWikilinksWithMarkdownLinks(){await this.saveAllOpenNotes();let e=0,n=0;await gt({abortSignal:this.abortSignal,buildNoticeMessage:i((r,o)=>`Replacing wikilinks with markdown links ${o} - ${r.path}`,"buildNoticeMessage"),items:Un(this.app),processItem:i(async r=>{if(this.settings.isPathIgnored(r.path))return;let o=await this.linksHandler.replaceAllNoteWikilinksWithMarkdownLinks(r.path,!1,this.abortSignal);e+=o,n++},"processItem"),progressBarTitle:"Consistent Attachments and Links: Replacing wikilinks with markdown links...",shouldContinueOnError:!0,shouldShowProgressBar:!0}),e===0?new $e.Notice("No wiki links found that need to be replaced"):new $e.Notice(`Replaced ${String(e)} wikilink${e>1?"s":""} from ${String(n)} note${n>1?"s":""}`)}replaceAllWikilinksWithMarkdownLinksCurrentNote(e){Ue({abortSignal:this.abortSignal,app:this.app,operationFn:or(n=>this.linksHandler.replaceAllNoteWikilinksWithMarkdownLinks(e.path,!1,n)),operationName:"Replace all wiki embeds with markdown embeds in current note"})}createSettingsManager(){return new Ro(this)}createSettingsTab(){return new cs(this)}createTranslationsMap(){return _p}async onLayoutReady(){await this.showBackupWarning(),this.registerEvent(this.app.metadataCache.on("deleted",(e,n)=>{n&&this.handleDeletedMetadata(e,n)})),this.registerEvent(this.app.metadataCache.on("changed",e=>{Ue({abortSignal:this.abortSignal,app:this.app,operationFn:i(n=>this.handleMetadataCacheChanged(e,n),"operationFn"),operationName:"handleMetadataCacheChanged"})}))}async onloadImpl(){await super.onloadImpl(),Sp(this,()=>({emptyFolderBehavior:this.settings.emptyFolderBehavior,isNote:i(n=>this.filesHandler.isNoteEx(n),"isNote"),isPathIgnored:i(n=>this.settings.isPathIgnored(n),"isPathIgnored"),shouldDeleteConflictingAttachments:this.settings.shouldDeleteExistingFilesWhenMovingNote,shouldHandleDeletions:this.settings.shouldDeleteAttachmentsWithNote,shouldHandleRenames:this.settings.shouldUpdateLinks,shouldRenameAttachmentFolder:this.settings.shouldMoveAttachmentsWithNote,shouldUpdateFileNameAliases:this.settings.shouldChangeNoteBacklinksDisplayText})),new ho(this).register(),new po(this).register(),new lo(this).register(),new yo(this).register(),new wo(this).register(),new go(this).register(),new bo(this).register(),new fo(this).register(),new mo(this).register(),new vo(this).register(),new Eo(this).register(),new Ao(this).register(),new xo(this).register(),new Co(this).register(),new ao(this).register(),this.linksHandler=new Xn(this),this.filesHandler=new Zn(this,this.linksHandler)}handleDeletedMetadata(e,n){!this.settings.shouldDeleteAttachmentsWithNote||this.settings.isPathIgnored(e.path)||!Ye(this.app,e)||this.deletedNoteCache.set(e.path,n)}async handleMetadataCacheChanged(e,n){n.throwIfAborted(),!(!this.settings.shouldCollectAttachmentsAutomatically||activeDocument.querySelector(".suggestion-container")?.isShown())&&Yn(this,[e])}async saveAllOpenNotes(){for(let e of this.app.workspace.getLeavesOfType("markdown"))e.view instanceof $e.MarkdownView&&await e.view.save()}async showBackupWarning(){this.settings.shouldShowBackupWarning&&(await pi({app:this.app,message:createFragment(e=>{e.createDiv({cls:"community-modal-readme"},n=>{n.appendText("Using 'Consistent Attachments and Links' plugin without proper configuration might lead to inconvenient attachment rearrangements or even data loss in your vault."),n.createEl("br"),n.appendText("It is "),n.createEl("strong",{text:"STRONGLY"}),n.appendText(" recommended to backup your vault before using the plugin."),n.createEl("br"),this.settings.hadDangerousSettingsReverted&&(n.appendText("Some of your plugin settings has been changed to their safe values."),n.createEl("br")),n.createEl("a",{href:"https://github.com/dy-sh/obsidian-consistent-attachments-and-links?tab=readme-ov-file",text:"Read more"}),n.appendText(" about how to use the plugin."),n.createEl("br"),n.appendText("This warning will not appear again.")})}),title:createFragment(e=>{(0,$e.setIcon)(e.createSpan(),"triangle-alert"),e.appendText(" Consistent Attachments and Links")})}),await this.settingsManager.editAndSave(e=>{e.shouldShowBackupWarning=!1}))}};var iw=us; + +/* nosourcemap */ \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/manifest.json b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/manifest.json new file mode 100644 index 00000000..dd260e3b --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "consistent-attachments-and-links", + "name": "Consistent Attachments and Links", + "version": "3.33.4", + "minAppVersion": "1.12.4", + "description": "This plugin ensures the consistency of attachments and links", + "author": "Dmitry Savosh", + "authorUrl": "https://github.com/dy-sh/", + "isDesktopOnly": false, + "fundingUrl": "https://www.buymeacoffee.com/mnaoumov" +} diff --git a/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/styles.css b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/styles.css new file mode 100644 index 00000000..ff938193 --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/consistent-attachments-and-links/styles.css @@ -0,0 +1 @@ +.consistent-attachments-and-links.obsidian-dev-utils.multiple-text-component textarea{height:6em;width:20em} diff --git a/10_Wiki/Topics/.obsidian/plugins/janitor/main.js b/10_Wiki/Topics/.obsidian/plugins/janitor/main.js new file mode 100644 index 00000000..98d631ad --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/janitor/main.js @@ -0,0 +1,63 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +var NC=Object.create;var io=Object.defineProperty,MC=Object.defineProperties,PC=Object.getOwnPropertyDescriptor,DC=Object.getOwnPropertyDescriptors,OC=Object.getOwnPropertyNames,vp=Object.getOwnPropertySymbols,RC=Object.getPrototypeOf,bp=Object.prototype.hasOwnProperty,_C=Object.prototype.propertyIsEnumerable;var yp=(e,t,n)=>t in e?io(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,j=(e,t)=>{for(var n in t||(t={}))bp.call(t,n)&&yp(e,n,t[n]);if(vp)for(var n of vp(t))_C.call(t,n)&&yp(e,n,t[n]);return e},ne=(e,t)=>MC(e,DC(t));var re=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),WC=(e,t)=>{for(var n in t)io(e,n,{get:t[n],enumerable:!0})},Ip=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of OC(t))!bp.call(e,i)&&i!==n&&io(e,i,{get:()=>t[i],enumerable:!(r=PC(t,i))||r.enumerable});return e};var he=(e,t,n)=>(n=e!=null?NC(RC(e)):{},Ip(t||!e||!e.__esModule?io(n,"default",{value:e,enumerable:!0}):n,e)),GC=e=>Ip(io({},"__esModule",{value:!0}),e);var ae=(e,t,n)=>new Promise((r,i)=>{var s=d=>{try{u(n.next(d))}catch(p){i(p)}},l=d=>{try{u(n.throw(d))}catch(p){i(p)}},u=d=>d.done?r(d.value):Promise.resolve(d.value).then(s,l);u((n=n.apply(e,t)).next())});var Mp=re(ee=>{"use strict";var oo=Symbol.for("react.element"),LC=Symbol.for("react.portal"),VC=Symbol.for("react.fragment"),BC=Symbol.for("react.strict_mode"),HC=Symbol.for("react.profiler"),YC=Symbol.for("react.provider"),ZC=Symbol.for("react.context"),zC=Symbol.for("react.forward_ref"),XC=Symbol.for("react.suspense"),jC=Symbol.for("react.memo"),UC=Symbol.for("react.lazy"),Cp=Symbol.iterator;function JC(e){return e===null||typeof e!="object"?null:(e=Cp&&e[Cp]||e["@@iterator"],typeof e=="function"?e:null)}var xp={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Ep=Object.assign,Ap={};function pi(e,t,n){this.props=e,this.context=t,this.refs=Ap,this.updater=n||xp}pi.prototype.isReactComponent={};pi.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};pi.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function kp(){}kp.prototype=pi.prototype;function iu(e,t,n){this.props=e,this.context=t,this.refs=Ap,this.updater=n||xp}var ou=iu.prototype=new kp;ou.constructor=iu;Ep(ou,pi.prototype);ou.isPureReactComponent=!0;var Sp=Array.isArray,Fp=Object.prototype.hasOwnProperty,su={current:null},Tp={key:!0,ref:!0,__self:!0,__source:!0};function Np(e,t,n){var r,i={},s=null,l=null;if(t!=null)for(r in t.ref!==void 0&&(l=t.ref),t.key!==void 0&&(s=""+t.key),t)Fp.call(t,r)&&!Tp.hasOwnProperty(r)&&(i[r]=t[r]);var u=arguments.length-2;if(u===1)i.children=n;else if(1{"use strict";Pp.exports=Mp()});var Hp=re(Ce=>{"use strict";function du(e,t){var n=e.length;e.push(t);e:for(;0>>1,i=e[r];if(0>>1;rMs(u,n))dMs(p,u)?(e[r]=p,e[d]=n,r=d):(e[r]=u,e[l]=n,r=l);else if(dMs(p,n))e[r]=p,e[d]=n,r=d;else break e}}return t}function Ms(e,t){var n=e.sortIndex-t.sortIndex;return n!==0?n:e.id-t.id}typeof performance=="object"&&typeof performance.now=="function"?(Dp=performance,Ce.unstable_now=function(){return Dp.now()}):(lu=Date,Op=lu.now(),Ce.unstable_now=function(){return lu.now()-Op});var Dp,lu,Op,An=[],dr=[],eS=1,qt=null,vt=3,Os=!1,Yr=!1,ao=!1,Wp=typeof setTimeout=="function"?setTimeout:null,Gp=typeof clearTimeout=="function"?clearTimeout:null,Rp=typeof setImmediate!="undefined"?setImmediate:null;typeof navigator!="undefined"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function fu(e){for(var t=mn(dr);t!==null;){if(t.callback===null)Ds(dr);else if(t.startTime<=e)Ds(dr),t.sortIndex=t.expirationTime,du(An,t);else break;t=mn(dr)}}function pu(e){if(ao=!1,fu(e),!Yr)if(mn(An)!==null)Yr=!0,mu(hu);else{var t=mn(dr);t!==null&&gu(pu,t.startTime-e)}}function hu(e,t){Yr=!1,ao&&(ao=!1,Gp(lo),lo=-1),Os=!0;var n=vt;try{for(fu(t),qt=mn(An);qt!==null&&(!(qt.expirationTime>t)||e&&!Bp());){var r=qt.callback;if(typeof r=="function"){qt.callback=null,vt=qt.priorityLevel;var i=r(qt.expirationTime<=t);t=Ce.unstable_now(),typeof i=="function"?qt.callback=i:qt===mn(An)&&Ds(An),fu(t)}else Ds(An);qt=mn(An)}if(qt!==null)var s=!0;else{var l=mn(dr);l!==null&&gu(pu,l.startTime-t),s=!1}return s}finally{qt=null,vt=n,Os=!1}}var Rs=!1,Ps=null,lo=-1,Lp=5,Vp=-1;function Bp(){return!(Ce.unstable_now()-Vpe||125r?(e.sortIndex=n,du(dr,e),mn(An)===null&&e===mn(dr)&&(ao?(Gp(lo),lo=-1):ao=!0,gu(pu,n-r))):(e.sortIndex=i,du(An,e),Yr||Os||(Yr=!0,mu(hu))),e};Ce.unstable_shouldYield=Bp;Ce.unstable_wrapCallback=function(e){var t=vt;return function(){var n=vt;vt=t;try{return e.apply(this,arguments)}finally{vt=n}}}});var Zp=re((lA,Yp)=>{"use strict";Yp.exports=Hp()});var Qg=re(Qt=>{"use strict";var $h=Ne(),Ut=Zp();function R(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;nt}return!1}function Tt(e,t,n,r,i,s,l){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=i,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=s,this.removeEmptyString=l}var at={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){at[e]=new Tt(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];at[t]=new Tt(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){at[e]=new Tt(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){at[e]=new Tt(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){at[e]=new Tt(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){at[e]=new Tt(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){at[e]=new Tt(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){at[e]=new Tt(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){at[e]=new Tt(e,5,!1,e.toLowerCase(),null,!1,!1)});var Mc=/[\-:]([a-z])/g;function Pc(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Mc,Pc);at[t]=new Tt(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Mc,Pc);at[t]=new Tt(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Mc,Pc);at[t]=new Tt(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){at[e]=new Tt(e,1,!1,e.toLowerCase(),null,!1,!1)});at.xlinkHref=new Tt("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){at[e]=new Tt(e,1,!1,e.toLowerCase(),null,!0,!0)});function Dc(e,t,n,r){var i=at.hasOwnProperty(t)?at[t]:null;(i!==null?i.type!==0:r||!(2u||i[l]!==s[u]){var d=` +`+i[l].replace(" at new "," at ");return e.displayName&&d.includes("")&&(d=d.replace("",e.displayName)),d}while(1<=l&&0<=u);break}}}finally{yu=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?yo(e):""}function oS(e){switch(e.tag){case 5:return yo(e.type);case 16:return yo("Lazy");case 13:return yo("Suspense");case 19:return yo("SuspenseList");case 0:case 2:case 15:return e=bu(e.type,!1),e;case 11:return e=bu(e.type.render,!1),e;case 1:return e=bu(e.type,!0),e;default:return""}}function Yu(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case vi:return"Fragment";case gi:return"Portal";case Vu:return"Profiler";case Oc:return"StrictMode";case Bu:return"Suspense";case Hu:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case em:return(e.displayName||"Context")+".Consumer";case qh:return(e._context.displayName||"Context")+".Provider";case Rc:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case _c:return t=e.displayName||null,t!==null?t:Yu(e.type)||"Memo";case pr:t=e._payload,e=e._init;try{return Yu(e(t))}catch(n){}}return null}function sS(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Yu(t);case 8:return t===Oc?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function kr(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function nm(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function aS(e){var t=nm(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n!="undefined"&&typeof n.get=="function"&&typeof n.set=="function"){var i=n.get,s=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return i.call(this)},set:function(l){r=""+l,s.call(this,l)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(l){r=""+l},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function Ws(e){e._valueTracker||(e._valueTracker=aS(e))}function rm(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=nm(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function da(e){if(e=e||(typeof document!="undefined"?document:void 0),typeof e=="undefined")return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Zu(e,t){var n=t.checked;return Oe({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n!=null?n:e._wrapperState.initialChecked})}function Up(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=kr(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function im(e,t){t=t.checked,t!=null&&Dc(e,"checked",t,!1)}function zu(e,t){im(e,t);var n=kr(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Xu(e,t.type,n):t.hasOwnProperty("defaultValue")&&Xu(e,t.type,kr(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Jp(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Xu(e,t,n){(t!=="number"||da(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var bo=Array.isArray;function Fi(e,t,n,r){if(e=e.options,t){t={};for(var i=0;i"+t.valueOf().toString()+"",t=Gs.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Po(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var So={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},lS=["Webkit","ms","Moz","O"];Object.keys(So).forEach(function(e){lS.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),So[t]=So[e]})});function lm(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||So.hasOwnProperty(e)&&So[e]?(""+t).trim():t+"px"}function um(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,i=lm(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,i):e[n]=i}}var uS=Oe({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Ju(e,t){if(t){if(uS[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(R(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(R(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(R(61))}if(t.style!=null&&typeof t.style!="object")throw Error(R(62))}}function Qu(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var $u=null;function Wc(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Ku=null,Ti=null,Ni=null;function Kp(e){if(e=Qo(e)){if(typeof Ku!="function")throw Error(R(280));var t=e.stateNode;t&&(t=La(t),Ku(e.stateNode,e.type,t))}}function cm(e){Ti?Ni?Ni.push(e):Ni=[e]:Ti=e}function dm(){if(Ti){var e=Ti,t=Ni;if(Ni=Ti=null,Kp(e),t)for(e=0;e>>=0,e===0?32:31-(IS(e)/CS|0)|0}var Ls=64,Vs=4194304;function Io(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function ma(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,i=e.suspendedLanes,s=e.pingedLanes,l=n&268435455;if(l!==0){var u=l&~i;u!==0?r=Io(u):(s&=l,s!==0&&(r=Io(s)))}else l=n&~i,l!==0?r=Io(l):s!==0&&(r=Io(s));if(r===0)return 0;if(t!==0&&t!==r&&(t&i)===0&&(i=r&-r,s=t&-t,i>=s||i===16&&(s&4194240)!==0))return t;if((r&4)!==0&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Uo(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-In(t),e[t]=n}function ES(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=xo),ah=String.fromCharCode(32),lh=!1;function Mm(e,t){switch(e){case"keyup":return qS.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Pm(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var yi=!1;function tw(e,t){switch(e){case"compositionend":return Pm(t);case"keypress":return t.which!==32?null:(lh=!0,ah);case"textInput":return e=t.data,e===ah&&lh?null:e;default:return null}}function nw(e,t){if(yi)return e==="compositionend"||!zc&&Mm(e,t)?(e=Tm(),na=Hc=vr=null,yi=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=dh(n)}}function _m(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?_m(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Wm(){for(var e=window,t=da();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch(r){n=!1}if(n)e=t.contentWindow;else break;t=da(e.document)}return t}function Xc(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function dw(e){var t=Wm(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&_m(n.ownerDocument.documentElement,n)){if(r!==null&&Xc(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var i=n.textContent.length,s=Math.min(r.start,i);r=r.end===void 0?s:Math.min(r.end,i),!e.extend&&s>r&&(i=r,r=s,s=i),i=fh(n,s);var l=fh(n,r);i&&l&&(e.rangeCount!==1||e.anchorNode!==i.node||e.anchorOffset!==i.offset||e.focusNode!==l.node||e.focusOffset!==l.offset)&&(t=t.createRange(),t.setStart(i.node,i.offset),e.removeAllRanges(),s>r?(e.addRange(t),e.extend(l.node,l.offset)):(t.setEnd(l.node,l.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,bi=null,ic=null,Ao=null,oc=!1;function ph(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;oc||bi==null||bi!==da(r)||(r=bi,"selectionStart"in r&&Xc(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Ao&&Go(Ao,r)||(Ao=r,r=ya(ic,"onSelect"),0Si||(e.current=dc[Si],dc[Si]=null,Si--)}function Se(e,t){Si++,dc[Si]=e.current,e.current=t}var Fr={},Ct=Nr(Fr),Rt=Nr(!1),$r=Fr;function Ri(e,t){var n=e.type.contextTypes;if(!n)return Fr;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var i={},s;for(s in n)i[s]=t[s];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function _t(e){return e=e.childContextTypes,e!=null}function Ia(){ke(Rt),ke(Ct)}function Sh(e,t,n){if(Ct.current!==Fr)throw Error(R(168));Se(Ct,t),Se(Rt,n)}function Xm(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var i in r)if(!(i in t))throw Error(R(108,sS(e)||"Unknown",i));return Oe({},n,r)}function Ca(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Fr,$r=Ct.current,Se(Ct,e),Se(Rt,Rt.current),!0}function wh(e,t,n){var r=e.stateNode;if(!r)throw Error(R(169));n?(e=Xm(e,t,$r),r.__reactInternalMemoizedMergedChildContext=e,ke(Rt),ke(Ct),Se(Ct,e)):ke(Rt),Se(Rt,n)}var Jn=null,Va=!1,Nu=!1;function jm(e){Jn===null?Jn=[e]:Jn.push(e)}function Cw(e){Va=!0,jm(e)}function Mr(){if(!Nu&&Jn!==null){Nu=!0;var e=0,t=ge;try{var n=Jn;for(ge=1;e>=l,i-=l,Qn=1<<32-In(t)+i|n<P?(O=D,D=null):O=D.sibling;var B=I(m,D,C[P],k);if(B===null){D===null&&(D=O);break}e&&D&&B.alternate===null&&t(m,D),y=s(B,y,P),N===null?M=B:N.sibling=B,N=B,D=O}if(P===C.length)return n(m,D),Me&&Zr(m,P),M;if(D===null){for(;PP?(O=D,D=null):O=D.sibling;var Z=I(m,D,B.value,k);if(Z===null){D===null&&(D=O);break}e&&D&&Z.alternate===null&&t(m,D),y=s(Z,y,P),N===null?M=Z:N.sibling=Z,N=Z,D=O}if(B.done)return n(m,D),Me&&Zr(m,P),M;if(D===null){for(;!B.done;P++,B=C.next())B=v(m,B.value,k),B!==null&&(y=s(B,y,P),N===null?M=B:N.sibling=B,N=B);return Me&&Zr(m,P),M}for(D=r(m,D);!B.done;P++,B=C.next())B=E(D,m,P,B.value,k),B!==null&&(e&&B.alternate!==null&&D.delete(B.key===null?P:B.key),y=s(B,y,P),N===null?M=B:N.sibling=B,N=B);return e&&D.forEach(function(ie){return t(m,ie)}),Me&&Zr(m,P),M}function x(m,y,C,k){if(typeof C=="object"&&C!==null&&C.type===vi&&C.key===null&&(C=C.props.children),typeof C=="object"&&C!==null){switch(C.$$typeof){case _s:e:{for(var M=C.key,N=y;N!==null;){if(N.key===M){if(M=C.type,M===vi){if(N.tag===7){n(m,N.sibling),y=i(N,C.props.children),y.return=m,m=y;break e}}else if(N.elementType===M||typeof M=="object"&&M!==null&&M.$$typeof===pr&&Nh(M)===N.type){n(m,N.sibling),y=i(N,C.props),y.ref=ho(m,N,C),y.return=m,m=y;break e}n(m,N);break}else t(m,N);N=N.sibling}C.type===vi?(y=Qr(C.props.children,m.mode,k,C.key),y.return=m,m=y):(k=ca(C.type,C.key,C.props,null,m.mode,k),k.ref=ho(m,y,C),k.return=m,m=k)}return l(m);case gi:e:{for(N=C.key;y!==null;){if(y.key===N)if(y.tag===4&&y.stateNode.containerInfo===C.containerInfo&&y.stateNode.implementation===C.implementation){n(m,y.sibling),y=i(y,C.children||[]),y.return=m,m=y;break e}else{n(m,y);break}else t(m,y);y=y.sibling}y=Gu(C,m.mode,k),y.return=m,m=y}return l(m);case pr:return N=C._init,x(m,y,N(C._payload),k)}if(bo(C))return w(m,y,C,k);if(uo(C))return A(m,y,C,k);$s(m,C)}return typeof C=="string"&&C!==""||typeof C=="number"?(C=""+C,y!==null&&y.tag===6?(n(m,y.sibling),y=i(y,C),y.return=m,m=y):(n(m,y),y=Wu(C,m.mode,k),y.return=m,m=y),l(m)):n(m,y)}return x}var Wi=tg(!0),ng=tg(!1),$o={},Mn=Nr($o),Ho=Nr($o),Yo=Nr($o);function Ur(e){if(e===$o)throw Error(R(174));return e}function td(e,t){switch(Se(Yo,t),Se(Ho,e),Se(Mn,$o),e=t.nodeType,e){case 9:case 11:t=(t=t.documentElement)?t.namespaceURI:Uu(null,"");break;default:e=e===8?t.parentNode:t,t=e.namespaceURI||null,e=e.tagName,t=Uu(t,e)}ke(Mn),Se(Mn,t)}function Gi(){ke(Mn),ke(Ho),ke(Yo)}function rg(e){Ur(Yo.current);var t=Ur(Mn.current),n=Uu(t,e.type);t!==n&&(Se(Ho,e),Se(Mn,n))}function nd(e){Ho.current===e&&(ke(Mn),ke(Ho))}var Pe=Nr(0);function ka(e){for(var t=e;t!==null;){if(t.tag===13){var n=t.memoizedState;if(n!==null&&(n=n.dehydrated,n===null||n.data==="$?"||n.data==="$!"))return t}else if(t.tag===19&&t.memoizedProps.revealOrder!==void 0){if((t.flags&128)!==0)return t}else if(t.child!==null){t.child.return=t,t=t.child;continue}if(t===e)break;for(;t.sibling===null;){if(t.return===null||t.return===e)return null;t=t.return}t.sibling.return=t.return,t=t.sibling}return null}var Mu=[];function rd(){for(var e=0;en?n:4,e(!0);var r=Pu.transition;Pu.transition={};try{e(!1),t()}finally{ge=n,Pu.transition=r}}function bg(){return sn().memoizedState}function Ew(e,t,n){var r=Er(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Ig(e))Cg(t,n);else if(n=$m(e,t,n,r),n!==null){var i=Ft();Cn(n,e,r,i),Sg(n,t,r)}}function Aw(e,t,n){var r=Er(e),i={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Ig(e))Cg(t,i);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var l=t.lastRenderedState,u=s(l,n);if(i.hasEagerState=!0,i.eagerState=u,Sn(u,l)){var d=t.interleaved;d===null?(i.next=i,qc(t)):(i.next=d.next,d.next=i),t.interleaved=i;return}}catch(p){}finally{}n=$m(e,t,i,r),n!==null&&(i=Ft(),Cn(n,e,r,i),Sg(n,t,r))}}function Ig(e){var t=e.alternate;return e===De||t!==null&&t===De}function Cg(e,t){ko=Fa=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Sg(e,t,n){if((n&4194240)!==0){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Lc(e,n)}}var Ta={readContext:on,useCallback:yt,useContext:yt,useEffect:yt,useImperativeHandle:yt,useInsertionEffect:yt,useLayoutEffect:yt,useMemo:yt,useReducer:yt,useRef:yt,useState:yt,useDebugValue:yt,useDeferredValue:yt,useTransition:yt,useMutableSource:yt,useSyncExternalStore:yt,useId:yt,unstable_isNewReconciler:!1},kw={readContext:on,useCallback:function(e,t){return Fn().memoizedState=[e,t===void 0?null:t],e},useContext:on,useEffect:Ph,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,sa(4194308,4,hg.bind(null,t,e),n)},useLayoutEffect:function(e,t){return sa(4194308,4,e,t)},useInsertionEffect:function(e,t){return sa(4,2,e,t)},useMemo:function(e,t){var n=Fn();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=Fn();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Ew.bind(null,De,e),[r.memoizedState,e]},useRef:function(e){var t=Fn();return e={current:e},t.memoizedState=e},useState:Mh,useDebugValue:ld,useDeferredValue:function(e){return Fn().memoizedState=e},useTransition:function(){var e=Mh(!1),t=e[0];return e=xw.bind(null,e[1]),Fn().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=De,i=Fn();if(Me){if(n===void 0)throw Error(R(407));n=n()}else{if(n=t(),et===null)throw Error(R(349));(qr&30)!==0||sg(r,t,n)}i.memoizedState=n;var s={value:n,getSnapshot:t};return i.queue=s,Ph(lg.bind(null,r,s,e),[e]),r.flags|=2048,Xo(9,ag.bind(null,r,s,n,t),void 0,null),n},useId:function(){var e=Fn(),t=et.identifierPrefix;if(Me){var n=$n,r=Qn;n=(r&~(1<<32-In(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Zo++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=l.createElement(n,{is:r.is}):(e=l.createElement(n),n==="select"&&(l=e,r.multiple?l.multiple=!0:r.size&&(l.size=r.size))):e=l.createElementNS(e,n),e[Tn]=t,e[Bo]=r,Mg(e,t,!1,!1),t.stateNode=e;e:{switch(l=Qu(n,r),n){case"dialog":Ae("cancel",e),Ae("close",e),i=r;break;case"iframe":case"object":case"embed":Ae("load",e),i=r;break;case"video":case"audio":for(i=0;iVi&&(t.flags|=128,r=!0,mo(s,!1),t.lanes=4194304)}else{if(!r)if(e=ka(l),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),mo(s,!0),s.tail===null&&s.tailMode==="hidden"&&!l.alternate&&!Me)return bt(t),null}else 2*Ge()-s.renderingStartTime>Vi&&n!==1073741824&&(t.flags|=128,r=!0,mo(s,!1),t.lanes=4194304);s.isBackwards?(l.sibling=t.child,t.child=l):(n=s.last,n!==null?n.sibling=l:t.child=l,s.last=l)}return s.tail!==null?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=Ge(),t.sibling=null,n=Pe.current,Se(Pe,r?n&1|2:n&1),t):(bt(t),null);case 22:case 23:return hd(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&(t.mode&1)!==0?(zt&1073741824)!==0&&(bt(t),t.subtreeFlags&6&&(t.flags|=8192)):bt(t),null;case 24:return null;case 25:return null}throw Error(R(156,t.tag))}function Rw(e,t){switch(Uc(t),t.tag){case 1:return _t(t.type)&&Ia(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Gi(),ke(Rt),ke(Ct),rd(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return nd(t),null;case 13:if(ke(Pe),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(R(340));_i()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ke(Pe),null;case 4:return Gi(),null;case 10:return Kc(t.type._context),null;case 22:case 23:return hd(),null;case 24:return null;default:return null}}var qs=!1,It=!1,_w=typeof WeakSet=="function"?WeakSet:Set,V=null;function Ai(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){Re(e,t,r)}else n.current=null}function wc(e,t,n){try{n()}catch(r){Re(e,t,r)}}var Bh=!1;function Ww(e,t){if(sc=ga,e=Wm(),Xc(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,s=r.focusNode;r=r.focusOffset;try{n.nodeType,s.nodeType}catch(k){n=null;break e}var l=0,u=-1,d=-1,p=0,g=0,v=e,I=null;t:for(;;){for(var E;v!==n||i!==0&&v.nodeType!==3||(u=l+i),v!==s||r!==0&&v.nodeType!==3||(d=l+r),v.nodeType===3&&(l+=v.nodeValue.length),(E=v.firstChild)!==null;)I=v,v=E;for(;;){if(v===e)break t;if(I===n&&++p===i&&(u=l),I===s&&++g===r&&(d=l),(E=v.nextSibling)!==null)break;v=I,I=v.parentNode}v=E}n=u===-1||d===-1?null:{start:u,end:d}}else n=null}n=n||{start:0,end:0}}else n=null;for(ac={focusedElem:e,selectionRange:n},ga=!1,V=t;V!==null;)if(t=V,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,V=e;else for(;V!==null;){t=V;try{var w=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(w!==null){var A=w.memoizedProps,x=w.memoizedState,m=t.stateNode,y=m.getSnapshotBeforeUpdate(t.elementType===t.type?A:vn(t.type,A),x);m.__reactInternalSnapshotBeforeUpdate=y}break;case 3:var C=t.stateNode.containerInfo;C.nodeType===1?C.textContent="":C.nodeType===9&&C.documentElement&&C.removeChild(C.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(R(163))}}catch(k){Re(t,t.return,k)}if(e=t.sibling,e!==null){e.return=t.return,V=e;break}V=t.return}return w=Bh,Bh=!1,w}function Fo(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var i=r=r.next;do{if((i.tag&e)===e){var s=i.destroy;i.destroy=void 0,s!==void 0&&wc(t,n,s)}i=i.next}while(i!==r)}}function Ya(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function xc(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function Og(e){var t=e.alternate;t!==null&&(e.alternate=null,Og(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Tn],delete t[Bo],delete t[cc],delete t[bw],delete t[Iw])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Rg(e){return e.tag===5||e.tag===3||e.tag===4}function Hh(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Rg(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Ec(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ba));else if(r!==4&&(e=e.child,e!==null))for(Ec(e,t,n),e=e.sibling;e!==null;)Ec(e,t,n),e=e.sibling}function Ac(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(Ac(e,t,n),e=e.sibling;e!==null;)Ac(e,t,n),e=e.sibling}var ot=null,yn=!1;function fr(e,t,n){for(n=n.child;n!==null;)_g(e,t,n),n=n.sibling}function _g(e,t,n){if(Nn&&typeof Nn.onCommitFiberUnmount=="function")try{Nn.onCommitFiberUnmount(Ra,n)}catch(u){}switch(n.tag){case 5:It||Ai(n,t);case 6:var r=ot,i=yn;ot=null,fr(e,t,n),ot=r,yn=i,ot!==null&&(yn?(e=ot,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):ot.removeChild(n.stateNode));break;case 18:ot!==null&&(yn?(e=ot,n=n.stateNode,e.nodeType===8?Tu(e.parentNode,n):e.nodeType===1&&Tu(e,n),_o(e)):Tu(ot,n.stateNode));break;case 4:r=ot,i=yn,ot=n.stateNode.containerInfo,yn=!0,fr(e,t,n),ot=r,yn=i;break;case 0:case 11:case 14:case 15:if(!It&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){i=r=r.next;do{var s=i,l=s.destroy;s=s.tag,l!==void 0&&((s&2)!==0||(s&4)!==0)&&wc(n,t,l),i=i.next}while(i!==r)}fr(e,t,n);break;case 1:if(!It&&(Ai(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(u){Re(n,t,u)}fr(e,t,n);break;case 21:fr(e,t,n);break;case 22:n.mode&1?(It=(r=It)||n.memoizedState!==null,fr(e,t,n),It=r):fr(e,t,n);break;default:fr(e,t,n)}}function Yh(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new _w),t.forEach(function(r){var i=Xw.bind(null,e,r);n.has(r)||(n.add(r),r.then(i,i))})}}function gn(e,t){var n=t.deletions;if(n!==null)for(var r=0;ri&&(i=l),r&=~s}if(r=i,r=Ge()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*Lw(r/1960))-r,10e?16:e,yr===null)var r=!1;else{if(e=yr,yr=null,Pa=0,(le&6)!==0)throw Error(R(331));var i=le;for(le|=4,V=e.current;V!==null;){var s=V,l=s.child;if((V.flags&16)!==0){var u=s.deletions;if(u!==null){for(var d=0;dGe()-fd?Jr(e,0):dd|=n),Wt(e,t)}function Zg(e,t){t===0&&((e.mode&1)===0?t=1:(t=Vs,Vs<<=1,(Vs&130023424)===0&&(Vs=4194304)));var n=Ft();e=tr(e,t),e!==null&&(Uo(e,t,n),Wt(e,n))}function zw(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Zg(e,n)}function Xw(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(R(314))}r!==null&&r.delete(t),Zg(e,n)}var zg;zg=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||Rt.current)Ot=!0;else{if((e.lanes&n)===0&&(t.flags&128)===0)return Ot=!1,Dw(e,t,n);Ot=(e.flags&131072)!==0}else Ot=!1,Me&&(t.flags&1048576)!==0&&Um(t,wa,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;aa(e,t),e=t.pendingProps;var i=Ri(t,Ct.current);Pi(t,n),i=od(null,t,r,e,i,n);var s=sd();return t.flags|=1,typeof i=="object"&&i!==null&&typeof i.render=="function"&&i.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,_t(r)?(s=!0,Ca(t)):s=!1,t.memoizedState=i.state!==null&&i.state!==void 0?i.state:null,ed(t),i.updater=Ba,t.stateNode=i,i._reactInternals=t,gc(t,r,e,n),t=bc(null,t,r,!0,s,n)):(t.tag=0,Me&&s&&jc(t),kt(null,t,i,n),t=t.child),t;case 16:r=t.elementType;e:{switch(aa(e,t),e=t.pendingProps,i=r._init,r=i(r._payload),t.type=r,i=t.tag=Uw(r),e=vn(r,e),i){case 0:t=yc(null,t,r,e,n);break e;case 1:t=Gh(null,t,r,e,n);break e;case 11:t=_h(null,t,r,e,n);break e;case 14:t=Wh(null,t,r,vn(r.type,e),n);break e}throw Error(R(306,r,""))}return t;case 0:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:vn(r,i),yc(e,t,r,i,n);case 1:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:vn(r,i),Gh(e,t,r,i,n);case 3:e:{if(Fg(t),e===null)throw Error(R(387));r=t.pendingProps,s=t.memoizedState,i=s.element,Km(e,t),Aa(t,r,null,n);var l=t.memoizedState;if(r=l.element,s.isDehydrated)if(s={element:r,isDehydrated:!1,cache:l.cache,pendingSuspenseBoundaries:l.pendingSuspenseBoundaries,transitions:l.transitions},t.updateQueue.baseState=s,t.memoizedState=s,t.flags&256){i=Li(Error(R(423)),t),t=Lh(e,t,r,n,i);break e}else if(r!==i){i=Li(Error(R(424)),t),t=Lh(e,t,r,n,i);break e}else for(Xt=Sr(t.stateNode.containerInfo.firstChild),jt=t,Me=!0,bn=null,n=ng(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(_i(),r===i){t=nr(e,t,n);break e}kt(e,t,r,n)}t=t.child}return t;case 5:return rg(t),e===null&&pc(t),r=t.type,i=t.pendingProps,s=e!==null?e.memoizedProps:null,l=i.children,lc(r,i)?l=null:s!==null&&lc(r,s)&&(t.flags|=32),kg(e,t),kt(e,t,l,n),t.child;case 6:return e===null&&pc(t),null;case 13:return Tg(e,t,n);case 4:return td(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Wi(t,null,r,n):kt(e,t,r,n),t.child;case 11:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:vn(r,i),_h(e,t,r,i,n);case 7:return kt(e,t,t.pendingProps,n),t.child;case 8:return kt(e,t,t.pendingProps.children,n),t.child;case 12:return kt(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,i=t.pendingProps,s=t.memoizedProps,l=i.value,Se(xa,r._currentValue),r._currentValue=l,s!==null)if(Sn(s.value,l)){if(s.children===i.children&&!Rt.current){t=nr(e,t,n);break e}}else for(s=t.child,s!==null&&(s.return=t);s!==null;){var u=s.dependencies;if(u!==null){l=s.child;for(var d=u.firstContext;d!==null;){if(d.context===r){if(s.tag===1){d=Kn(-1,n&-n),d.tag=2;var p=s.updateQueue;if(p!==null){p=p.shared;var g=p.pending;g===null?d.next=d:(d.next=g.next,g.next=d),p.pending=d}}s.lanes|=n,d=s.alternate,d!==null&&(d.lanes|=n),hc(s.return,n,t),u.lanes|=n;break}d=d.next}}else if(s.tag===10)l=s.type===t.type?null:s.child;else if(s.tag===18){if(l=s.return,l===null)throw Error(R(341));l.lanes|=n,u=l.alternate,u!==null&&(u.lanes|=n),hc(l,n,t),l=s.sibling}else l=s.child;if(l!==null)l.return=s;else for(l=s;l!==null;){if(l===t){l=null;break}if(s=l.sibling,s!==null){s.return=l.return,l=s;break}l=l.return}s=l}kt(e,t,i.children,n),t=t.child}return t;case 9:return i=t.type,r=t.pendingProps.children,Pi(t,n),i=on(i),r=r(i),t.flags|=1,kt(e,t,r,n),t.child;case 14:return r=t.type,i=vn(r,t.pendingProps),i=vn(r.type,i),Wh(e,t,r,i,n);case 15:return Eg(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:vn(r,i),aa(e,t),t.tag=1,_t(r)?(e=!0,Ca(t)):e=!1,Pi(t,n),eg(t,r,i),gc(t,r,i,n),bc(null,t,r,!0,e,n);case 19:return Ng(e,t,n);case 22:return Ag(e,t,n)}throw Error(R(156,t.tag))};function Xg(e,t){return ym(e,t)}function jw(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function nn(e,t,n,r){return new jw(e,t,n,r)}function gd(e){return e=e.prototype,!(!e||!e.isReactComponent)}function Uw(e){if(typeof e=="function")return gd(e)?1:0;if(e!=null){if(e=e.$$typeof,e===Rc)return 11;if(e===_c)return 14}return 2}function Ar(e,t){var n=e.alternate;return n===null?(n=nn(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function ca(e,t,n,r,i,s){var l=2;if(r=e,typeof e=="function")gd(e)&&(l=1);else if(typeof e=="string")l=5;else e:switch(e){case vi:return Qr(n.children,i,s,t);case Oc:l=8,i|=8;break;case Vu:return e=nn(12,n,t,i|2),e.elementType=Vu,e.lanes=s,e;case Bu:return e=nn(13,n,t,i),e.elementType=Bu,e.lanes=s,e;case Hu:return e=nn(19,n,t,i),e.elementType=Hu,e.lanes=s,e;case tm:return za(n,i,s,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case qh:l=10;break e;case em:l=9;break e;case Rc:l=11;break e;case _c:l=14;break e;case pr:l=16,r=null;break e}throw Error(R(130,e==null?e:typeof e,""))}return t=nn(l,n,t,i),t.elementType=e,t.type=r,t.lanes=s,t}function Qr(e,t,n,r){return e=nn(7,e,r,t),e.lanes=n,e}function za(e,t,n,r){return e=nn(22,e,r,t),e.elementType=tm,e.lanes=n,e.stateNode={isHidden:!1},e}function Wu(e,t,n){return e=nn(6,e,null,t),e.lanes=n,e}function Gu(e,t,n){return t=nn(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Jw(e,t,n,r,i){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Cu(0),this.expirationTimes=Cu(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Cu(0),this.identifierPrefix=r,this.onRecoverableError=i,this.mutableSourceEagerHydrationData=null}function vd(e,t,n,r,i,s,l,u,d){return e=new Jw(e,t,n,u,d),t===1?(t=1,s===!0&&(t|=8)):t=0,s=nn(3,null,null,t),e.current=s,s.stateNode=e,s.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},ed(s),e}function Qw(e,t,n){var r=3{"use strict";function $g(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__=="undefined"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE($g)}catch(e){console.error(e)}}$g(),Kg.exports=Qg()});var qo=re(Cd=>{"use strict";var qg=Ko();Cd.createRoot=qg.createRoot,Cd.hydrateRoot=qg.hydrateRoot;var dA});var hv=re(_d=>{"use strict";Object.defineProperty(_d,"__esModule",{value:!0});function ax(e){if(e.sheet)return e.sheet;for(var t=0;t{"use strict";mv.exports=hv()});var yv=re((sl,vv)=>{(function(e,t){typeof sl=="object"&&typeof vv!="undefined"?t(sl):typeof define=="function"&&define.amd?define(["exports"],t):(e=e||self,t(e.stylis={}))})(sl,function(e){"use strict";var t="-ms-",n="-moz-",r="-webkit-",i="comm",s="rule",l="decl",u="@page",d="@media",p="@import",g="@charset",v="@viewport",I="@supports",E="@document",w="@namespace",A="@keyframes",x="@font-face",m="@counter-style",y="@font-feature-values",C=Math.abs,k=String.fromCharCode,M=Object.assign;function N(b,L){return Z(b,0)^45?(((L<<2^Z(b,0))<<2^Z(b,1))<<2^Z(b,2))<<2^Z(b,3):0}function D(b){return b.trim()}function P(b,L){return(b=L.exec(b))?b[0]:b}function O(b,L,X){return b.replace(L,X)}function B(b,L){return b.indexOf(L)}function Z(b,L){return b.charCodeAt(L)|0}function ie(b,L,X){return b.slice(L,X)}function pe(b){return b.length}function ue(b){return b.length}function te(b,L){return L.push(b),b}function Ve(b,L){return b.map(L).join("")}e.line=1,e.column=1,e.length=0,e.position=0,e.character=0,e.characters="";function Qe(b,L,X,J,q,ft,xe){return{value:b,root:L,parent:X,type:J,props:q,children:ft,line:e.line,column:e.column,length:xe,return:""}}function ye(b,L){return M(Qe("",null,null,"",null,null,0),b,{length:-b.length},L)}function wt(){return e.character}function lt(){return e.character=e.position>0?Z(e.characters,--e.position):0,e.column--,e.character===10&&(e.column=1,e.line--),e.character}function we(){return e.character=e.position2||ct(e.character)>3?"":" "}function Or(b){for(;we();)switch(ct(e.character)){case 0:te(Wr(e.position-1),b);break;case 2:te(Vt(e.character),b);break;default:te(k(e.character),b)}return b}function Rr(b,L){for(;--L&&we()&&!(e.character<48||e.character>102||e.character>57&&e.character<65||e.character>70&&e.character<97););return ut(b,G()+(L<6&&ce()==32&&we()==32))}function ar(b){for(;we();)switch(e.character){case b:return e.position;case 34:case 39:b!==34&&b!==39&&ar(e.character);break;case 40:b===41&&ar(b);break;case 92:we();break}return e.position}function _r(b,L){for(;we()&&b+e.character!==47+10;)if(b+e.character===42+42&&ce()===47)break;return"/*"+ut(L,e.position-1)+"*"+k(b===47?b:we())}function Wr(b){for(;!ct(ce());)we();return ut(b,e.position)}function Wl(b){return rt(Gr("",null,null,null,[""],b=Be(b),0,[0],b))}function Gr(b,L,X,J,q,ft,xe,Ke,Kt){for(var Pt=0,oe=0,it=xe,xn=0,dn=0,Bt=0,pt=1,fn=1,ht=1,mt=0,Ht="",ai=q,Yt=ft,xt=J,W=Ht;fn;)switch(Bt=mt,mt=we()){case 40:if(Bt!=108&&Z(W,it-1)==58){B(W+=O(Vt(mt),"&","&\f"),"&\f")!=-1&&(ht=-1);break}case 34:case 39:case 91:W+=Vt(mt);break;case 9:case 10:case 13:case 32:W+=oi(Bt);break;case 92:W+=Rr(G()-1,7);continue;case 47:switch(ce()){case 42:case 47:te(He(_r(we(),G()),L,X),Kt);break;default:W+="/"}break;case 123*pt:Ke[Pt++]=pe(W)*ht;case 125*pt:case 59:case 0:switch(mt){case 0:case 125:fn=0;case 59+oe:dn>0&&pe(W)-it&&te(dn>32?dt(W+";",J,X,it-1):dt(O(W," ","")+";",J,X,it-2),Kt);break;case 59:W+=";";default:if(te(xt=Gn(W,L,X,Pt,oe,q,Ke,Ht,ai=[],Yt=[],it),ft),mt===123)if(oe===0)Gr(W,L,xt,xt,ai,ft,it,Ke,Yt);else switch(xn===99&&Z(W,3)===110?100:xn){case 100:case 109:case 115:Gr(b,xt,xt,J&&te(Gn(b,xt,xt,0,0,q,Ke,Ht,q,ai=[],it),Yt),q,Yt,it,Ke,J?ai:Yt);break;default:Gr(W,xt,xt,xt,[""],Yt,0,Ke,Yt)}}Pt=oe=dn=0,pt=ht=1,Ht=W="",it=xe;break;case 58:it=1+pe(W),dn=Bt;default:if(pt<1){if(mt==123)--pt;else if(mt==125&&pt++==0&<()==125)continue}switch(W+=k(mt),mt*pt){case 38:ht=oe>0?1:(W+="\f",-1);break;case 44:Ke[Pt++]=(pe(W)-1)*ht,ht=1;break;case 64:ce()===45&&(W+=Vt(we())),xn=ce(),oe=it=pe(Ht=W+=Wr(G())),mt++;break;case 45:Bt===45&&pe(W)==2&&(pt=0)}}return ft}function Gn(b,L,X,J,q,ft,xe,Ke,Kt,Pt,oe){for(var it=q-1,xn=q===0?ft:[""],dn=ue(xn),Bt=0,pt=0,fn=0;Bt0?xn[ht]+" "+mt:O(mt,/&\f/g,xn[ht])))&&(Kt[fn++]=Ht);return Qe(b,L,X,q===0?s:Ke,Kt,Pt,oe)}function He(b,L,X){return Qe(b,L,X,i,k(wt()),ie(b,2,-2),0)}function dt(b,L,X,J){return Qe(b,L,X,l,ie(b,0,J),ie(b,J+1,-1),J)}function Lr(b,L,X){switch(N(b,L)){case 5103:return r+"print-"+b+b;case 5737:case 4201:case 3177:case 3433:case 1641:case 4457:case 2921:case 5572:case 6356:case 5844:case 3191:case 6645:case 3005:case 6391:case 5879:case 5623:case 6135:case 4599:case 4855:case 4215:case 6389:case 5109:case 5365:case 5621:case 3829:return r+b+b;case 4789:return n+b+b;case 5349:case 4246:case 4810:case 6968:case 2756:return r+b+n+b+t+b+b;case 5936:switch(Z(b,L+11)){case 114:return r+b+t+O(b,/[svh]\w+-[tblr]{2}/,"tb")+b;case 108:return r+b+t+O(b,/[svh]\w+-[tblr]{2}/,"tb-rl")+b;case 45:return r+b+t+O(b,/[svh]\w+-[tblr]{2}/,"lr")+b}case 6828:case 4268:case 2903:return r+b+t+b+b;case 6165:return r+b+t+"flex-"+b+b;case 5187:return r+b+O(b,/(\w+).+(:[^]+)/,r+"box-$1$2"+t+"flex-$1$2")+b;case 5443:return r+b+t+"flex-item-"+O(b,/flex-|-self/g,"")+(P(b,/flex-|baseline/)?"":t+"grid-row-"+O(b,/flex-|-self/g,""))+b;case 4675:return r+b+t+"flex-line-pack"+O(b,/align-content|flex-|-self/g,"")+b;case 5548:return r+b+t+O(b,"shrink","negative")+b;case 5292:return r+b+t+O(b,"basis","preferred-size")+b;case 6060:return r+"box-"+O(b,"-grow","")+r+b+t+O(b,"grow","positive")+b;case 4554:return r+O(b,/([^-])(transform)/g,"$1"+r+"$2")+b;case 6187:return O(O(O(b,/(zoom-|grab)/,r+"$1"),/(image-set)/,r+"$1"),b,"")+b;case 5495:case 3959:return O(b,/(image-set\([^]*)/,r+"$1$`$1");case 4968:return O(O(b,/(.+:)(flex-)?(.*)/,r+"box-pack:$3"+t+"flex-pack:$3"),/s.+-b[^;]+/,"justify")+r+b+b;case 4200:if(!P(b,/flex-|baseline/))return t+"grid-column-align"+ie(b,L)+b;break;case 2592:case 3360:return t+O(b,"template-","")+b;case 4384:case 3616:return X&&X.some(function(J,q){return L=q,P(J.props,/grid-\w+-end/)})?~B(b+(X=X[L].value),"span")?b:t+O(b,"-start","")+b+t+"grid-row-span:"+(~B(X,"span")?P(X,/\d+/):+P(X,/\d+/)-+P(b,/\d+/))+";":t+O(b,"-start","")+b;case 4896:case 4128:return X&&X.some(function(J){return P(J.props,/grid-\w+-start/)})?b:t+O(O(b,"-end","-span"),"span ","")+b;case 4095:case 3583:case 4068:case 2532:return O(b,/(.+)-inline(.+)/,r+"$1$2")+b;case 8116:case 7059:case 5753:case 5535:case 5445:case 5701:case 4933:case 4677:case 5533:case 5789:case 5021:case 4765:if(pe(b)-1-L>6)switch(Z(b,L+1)){case 109:if(Z(b,L+4)!==45)break;case 102:return O(b,/(.+:)(.+)-([^]+)/,"$1"+r+"$2-$3$1"+n+(Z(b,L+3)==108?"$3":"$2-$3"))+b;case 115:return~B(b,"stretch")?Lr(O(b,"stretch","fill-available"),L,X)+b:b}break;case 5152:case 5920:return O(b,/(.+?):(\d+)(\s*\/\s*(span)?\s*(\d+))?(.*)/,function(J,q,ft,xe,Ke,Kt,Pt){return t+q+":"+ft+Pt+(xe?t+q+"-span:"+(Ke?Kt:+Kt-+ft)+Pt:"")+b});case 4949:if(Z(b,L+6)===121)return O(b,":",":"+r)+b;break;case 6444:switch(Z(b,Z(b,14)===45?18:11)){case 120:return O(b,/(.+:)([^;\s!]+)(;|(\s+)?!.+)?/,"$1"+r+(Z(b,14)===45?"inline-":"")+"box$3$1"+r+"$2$3$1"+t+"$2box$3")+b;case 100:return O(b,":",":"+t)+b}break;case 5719:case 2647:case 2135:case 3927:case 2391:return O(b,"scroll-","scroll-snap-")+b}return b}function Ln(b,L){for(var X="",J=ue(b),q=0;q-1&&!b.return)switch(b.type){case l:b.return=Lr(b.value,b.length,X);return;case A:return Ln([ye(b,{value:O(b.value,"@","@"+r)})],J);case s:if(b.length)return Ve(b.props,function(q){switch(P(q,/(::plac\w+|:read-\w+)/)){case":read-only":case":read-write":return Ln([ye(b,{props:[O(q,/:(read-\w+)/,":"+n+"$1")]})],J);case"::placeholder":return Ln([ye(b,{props:[O(q,/:(plac\w+)/,":"+r+"input-$1")]}),ye(b,{props:[O(q,/:(plac\w+)/,":"+n+"$1")]}),ye(b,{props:[O(q,/:(plac\w+)/,t+"input-$1")]})],J)}return""})}}function Q(b){switch(b.type){case s:b.props=b.props.map(function(L){return Ve(Wn(L),function(X,J,q){switch(Z(X,0)){case 12:return ie(X,1,pe(X));case 0:case 40:case 43:case 62:case 126:return X;case 58:q[++J]==="global"&&(q[J]="",q[++J]="\f"+ie(q[J],J=1,-1));case 32:return J===1?"":X;default:switch(J){case 0:return b=X,ue(q)>1?"":X;case(J=ue(q)-1):case 2:return J===2?X+b+b:X+b;default:return X}}})})}}e.CHARSET=g,e.COMMENT=i,e.COUNTER_STYLE=m,e.DECLARATION=l,e.DOCUMENT=E,e.FONT_FACE=x,e.FONT_FEATURE_VALUES=y,e.IMPORT=p,e.KEYFRAMES=A,e.MEDIA=d,e.MOZ=n,e.MS=t,e.NAMESPACE=w,e.PAGE=u,e.RULESET=s,e.SUPPORTS=I,e.VIEWPORT=v,e.WEBKIT=r,e.abs=C,e.alloc=Be,e.append=te,e.assign=M,e.caret=G,e.char=wt,e.charat=Z,e.combine=Ve,e.comment=He,e.commenter=_r,e.compile=Wl,e.copy=ye,e.dealloc=rt,e.declaration=dt,e.delimit=Vt,e.delimiter=ar,e.escaping=Rr,e.from=k,e.hash=N,e.identifier=Wr,e.indexof=B,e.match=P,e.middleware=Gl,e.namespace=Q,e.next=we,e.node=Qe,e.parse=Gr,e.peek=ce,e.prefix=Lr,e.prefixer=Mt,e.prev=lt,e.replace=O,e.ruleset=Gn,e.rulesheet=si,e.serialize=Ln,e.sizeof=ue,e.slice=ut,e.stringify=$e,e.strlen=pe,e.substr=ie,e.token=ct,e.tokenize=Wn,e.tokenizer=Or,e.trim=D,e.whitespace=oi,Object.defineProperty(e,"__esModule",{value:!0})})});var bv=re(Wd=>{"use strict";Object.defineProperty(Wd,"__esModule",{value:!0});var cx=function(t){var n=new WeakMap;return function(r){if(n.has(r))return n.get(r);var i=t(r);return n.set(r,i),i}};Wd.default=cx});var al=re((kk,Iv)=>{"use strict";Iv.exports=bv()});var Cv=re(Gd=>{"use strict";Object.defineProperty(Gd,"__esModule",{value:!0});function dx(e){var t=Object.create(null);return function(n){return t[n]===void 0&&(t[n]=e(n)),t[n]}}Gd.default=dx});var Ld=re((Tk,Sv)=>{"use strict";Sv.exports=Cv()});var Av=re(Vd=>{"use strict";Object.defineProperty(Vd,"__esModule",{value:!0});var fx=gv(),T=yv(),px=al(),hx=Ld();function xv(e){return e&&e.__esModule?e:{default:e}}var mx=xv(px),gx=xv(hx),vx=function(t,n,r){for(var i=0,s=0;i=s,s=T.peek(),i===38&&s===12&&(n[r]=1),!T.token(s);)T.next();return T.slice(t,T.position)},yx=function(t,n){var r=-1,i=44;do switch(T.token(i)){case 0:i===38&&T.peek()===12&&(n[r]=1),t[r]+=vx(T.position-1,n,r);break;case 2:t[r]+=T.delimit(i);break;case 4:if(i===44){t[++r]=T.peek()===58?"&\f":"",n[r]=t[r].length;break}default:t[r]+=T.from(i)}while(i=T.next());return t},bx=function(t,n){return T.dealloc(yx(T.alloc(t),n))},wv=new WeakMap,Ix=function(t){if(!(t.type!=="rule"||!t.parent||t.length<1)){for(var n=t.value,r=t.parent,i=t.column===r.column&&t.line===r.line;r.type!=="rule";)if(r=r.parent,!r)return;if(!(t.props.length===1&&n.charCodeAt(0)!==58&&!wv.get(r))&&!i){wv.set(t,!0);for(var s=[],l=bx(n,s),u=r.props,d=0,p=0;d6)switch(T.charat(e,t+1)){case 109:if(T.charat(e,t+4)!==45)break;case 102:return T.replace(e,/(.+:)(.+)-([^]+)/,"$1"+T.WEBKIT+"$2-$3$1"+T.MOZ+(T.charat(e,t+3)==108?"$3":"$2-$3"))+e;case 115:return~T.indexof(e,"stretch")?Ev(T.replace(e,"stretch","fill-available"),t)+e:e}break;case 4949:if(T.charat(e,t+1)!==115)break;case 6444:switch(T.charat(e,T.strlen(e)-3-(~T.indexof(e,"!important")&&10))){case 107:return T.replace(e,":",":"+T.WEBKIT)+e;case 101:return T.replace(e,/(.+:)([^;!]+)(;|!.+)?/,"$1"+T.WEBKIT+(T.charat(e,14)===45?"inline-":"")+"box$3$1"+T.WEBKIT+"$2$3$1"+T.MS+"$2box$3")+e}break;case 5936:switch(T.charat(e,t+11)){case 114:return T.WEBKIT+e+T.MS+T.replace(e,/[svh]\w+-[tblr]{2}/,"tb")+e;case 108:return T.WEBKIT+e+T.MS+T.replace(e,/[svh]\w+-[tblr]{2}/,"tb-rl")+e;case 45:return T.WEBKIT+e+T.MS+T.replace(e,/[svh]\w+-[tblr]{2}/,"lr")+e}return T.WEBKIT+e+T.MS+e+e}return e}var Sx=function(t,n,r,i){if(t.length>-1&&!t.return)switch(t.type){case T.DECLARATION:t.return=Ev(t.value,t.length);break;case T.KEYFRAMES:return T.serialize([T.copy(t,{value:T.replace(t.value,"@","@"+T.WEBKIT)})],i);case T.RULESET:if(t.length)return T.combine(t.props,function(s){switch(T.match(s,/(::plac\w+|:read-\w+)/)){case":read-only":case":read-write":return T.serialize([T.copy(t,{props:[T.replace(s,/:(read-\w+)/,":"+T.MOZ+"$1")]})],i);case"::placeholder":return T.serialize([T.copy(t,{props:[T.replace(s,/:(plac\w+)/,":"+T.WEBKIT+"input-$1")]}),T.copy(t,{props:[T.replace(s,/:(plac\w+)/,":"+T.MOZ+"$1")]}),T.copy(t,{props:[T.replace(s,/:(plac\w+)/,T.MS+"input-$1")]})],i)}return""})}},ll=typeof document!="undefined",wx=ll?void 0:mx.default(function(){return gx.default(function(){var e={};return function(t){return e[t]}})}),xx=[Sx],Ex=function(t){var n=t.key;if(ll&&n==="css"){var r=document.querySelectorAll("style[data-emotion]:not([data-s])");Array.prototype.forEach.call(r,function(k){var M=k.getAttribute("data-emotion");M.indexOf(" ")!==-1&&(document.head.appendChild(k),k.setAttribute("data-s",""))})}var i=t.stylisPlugins||xx,s={},l,u=[];ll&&(l=t.container||document.head,Array.prototype.forEach.call(document.querySelectorAll('style[data-emotion^="'+n+' "]'),function(k){for(var M=k.getAttribute("data-emotion").split(" "),N=1;N{"use strict";kv.exports=Av()});var Yd=re((Pk,or)=>{function Hd(){return or.exports=Hd=Object.assign?Object.assign.bind():function(e){for(var t=1;t{"use strict";var tt=typeof Symbol=="function"&&Symbol.for,Zd=tt?Symbol.for("react.element"):60103,zd=tt?Symbol.for("react.portal"):60106,ul=tt?Symbol.for("react.fragment"):60107,cl=tt?Symbol.for("react.strict_mode"):60108,dl=tt?Symbol.for("react.profiler"):60114,fl=tt?Symbol.for("react.provider"):60109,pl=tt?Symbol.for("react.context"):60110,Xd=tt?Symbol.for("react.async_mode"):60111,hl=tt?Symbol.for("react.concurrent_mode"):60111,ml=tt?Symbol.for("react.forward_ref"):60112,gl=tt?Symbol.for("react.suspense"):60113,Ax=tt?Symbol.for("react.suspense_list"):60120,vl=tt?Symbol.for("react.memo"):60115,yl=tt?Symbol.for("react.lazy"):60116,kx=tt?Symbol.for("react.block"):60121,Fx=tt?Symbol.for("react.fundamental"):60117,Tx=tt?Symbol.for("react.responder"):60118,Nx=tt?Symbol.for("react.scope"):60119;function $t(e){if(typeof e=="object"&&e!==null){var t=e.$$typeof;switch(t){case Zd:switch(e=e.type,e){case Xd:case hl:case ul:case dl:case cl:case gl:return e;default:switch(e=e&&e.$$typeof,e){case pl:case ml:case yl:case vl:case fl:return e;default:return t}}case zd:return t}}}function Fv(e){return $t(e)===hl}ve.AsyncMode=Xd;ve.ConcurrentMode=hl;ve.ContextConsumer=pl;ve.ContextProvider=fl;ve.Element=Zd;ve.ForwardRef=ml;ve.Fragment=ul;ve.Lazy=yl;ve.Memo=vl;ve.Portal=zd;ve.Profiler=dl;ve.StrictMode=cl;ve.Suspense=gl;ve.isAsyncMode=function(e){return Fv(e)||$t(e)===Xd};ve.isConcurrentMode=Fv;ve.isContextConsumer=function(e){return $t(e)===pl};ve.isContextProvider=function(e){return $t(e)===fl};ve.isElement=function(e){return typeof e=="object"&&e!==null&&e.$$typeof===Zd};ve.isForwardRef=function(e){return $t(e)===ml};ve.isFragment=function(e){return $t(e)===ul};ve.isLazy=function(e){return $t(e)===yl};ve.isMemo=function(e){return $t(e)===vl};ve.isPortal=function(e){return $t(e)===zd};ve.isProfiler=function(e){return $t(e)===dl};ve.isStrictMode=function(e){return $t(e)===cl};ve.isSuspense=function(e){return $t(e)===gl};ve.isValidElementType=function(e){return typeof e=="string"||typeof e=="function"||e===ul||e===hl||e===dl||e===cl||e===gl||e===Ax||typeof e=="object"&&e!==null&&(e.$$typeof===yl||e.$$typeof===vl||e.$$typeof===fl||e.$$typeof===pl||e.$$typeof===ml||e.$$typeof===Fx||e.$$typeof===Tx||e.$$typeof===Nx||e.$$typeof===kx)};ve.typeOf=$t});var Mv=re((Ok,Nv)=>{"use strict";Nv.exports=Tv()});var Jd=re((Rk,Wv)=>{"use strict";var jd=Mv(),Mx={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},Px={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},Dx={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},Rv={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},Ud={};Ud[jd.ForwardRef]=Dx;Ud[jd.Memo]=Rv;function Pv(e){return jd.isMemo(e)?Rv:Ud[e.$$typeof]||Mx}var Ox=Object.defineProperty,Rx=Object.getOwnPropertyNames,Dv=Object.getOwnPropertySymbols,_x=Object.getOwnPropertyDescriptor,Wx=Object.getPrototypeOf,Ov=Object.prototype;function _v(e,t,n){if(typeof t!="string"){if(Ov){var r=Wx(t);r&&r!==Ov&&_v(e,r,n)}var i=Rx(t);Dv&&(i=i.concat(Dv(t)));for(var s=Pv(e),l=Pv(t),u=0;u{"use strict";Object.defineProperty(Qd,"__esModule",{value:!0});var Gx=Jd();function Lx(e){return e&&e.__esModule?e:{default:e}}var Vx=Lx(Gx),Bx=function(e,t){return Vx.default(e,t)};Qd.default=Bx});var Lv=re(as=>{"use strict";Object.defineProperty(as,"__esModule",{value:!0});var Kd=typeof document!="undefined";function Hx(e,t,n){var r="";return n.split(" ").forEach(function(i){e[i]!==void 0?t.push(e[i]+";"):r+=i+" "}),r}var Gv=function(t,n,r){var i=t.key+"-"+n.name;(r===!1||Kd===!1&&t.compat!==void 0)&&t.registered[i]===void 0&&(t.registered[i]=n.styles)},Yx=function(t,n,r){Gv(t,n,r);var i=t.key+"-"+n.name;if(t.inserted[n.name]===void 0){var s="",l=n;do{var u=t.insert(n===l?"."+i:"",l,t.sheet,!0);!Kd&&u!==void 0&&(s+=u),l=l.next}while(l!==void 0);if(!Kd&&s.length!==0)return s}};as.getRegisteredStyles=Hx;as.insertStyles=Yx;as.registerStyles=Gv});var qd=re((Gk,Vv)=>{"use strict";Vv.exports=Lv()});var Bv=re(ef=>{"use strict";Object.defineProperty(ef,"__esModule",{value:!0});function Zx(e){for(var t=0,n,r=0,i=e.length;i>=4;++r,i-=4)n=e.charCodeAt(r)&255|(e.charCodeAt(++r)&255)<<8|(e.charCodeAt(++r)&255)<<16|(e.charCodeAt(++r)&255)<<24,n=(n&65535)*1540483477+((n>>>16)*59797<<16),n^=n>>>24,t=(n&65535)*1540483477+((n>>>16)*59797<<16)^(t&65535)*1540483477+((t>>>16)*59797<<16);switch(i){case 3:t^=(e.charCodeAt(r+2)&255)<<16;case 2:t^=(e.charCodeAt(r+1)&255)<<8;case 1:t^=e.charCodeAt(r)&255,t=(t&65535)*1540483477+((t>>>16)*59797<<16)}return t^=t>>>13,t=(t&65535)*1540483477+((t>>>16)*59797<<16),((t^t>>>15)>>>0).toString(36)}ef.default=Zx});var Yv=re((Vk,Hv)=>{"use strict";Hv.exports=Bv()});var Zv=re(tf=>{"use strict";Object.defineProperty(tf,"__esModule",{value:!0});var zx={animationIterationCount:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};tf.default=zx});var Xv=re((Hk,zv)=>{"use strict";zv.exports=Zv()});var $v=re(of=>{"use strict";Object.defineProperty(of,"__esModule",{value:!0});var Xx=Yv(),jx=Xv(),Ux=Ld();function rf(e){return e&&e.__esModule?e:{default:e}}var Jx=rf(Xx),Qx=rf(jx),$x=rf(Ux),Kx=/[A-Z]|^ms/g,qx=/_EMO_([^_]+?)_([^]*?)_EMO_/g,Qv=function(t){return t.charCodeAt(1)===45},jv=function(t){return t!=null&&typeof t!="boolean"},nf=$x.default(function(e){return Qv(e)?e:e.replace(Kx,"-$&").toLowerCase()}),Uv=function(t,n){switch(t){case"animation":case"animationName":if(typeof n=="string")return n.replace(qx,function(r,i,s){return Pn={name:i,styles:s,next:Pn},i})}return Qx.default[t]!==1&&!Qv(t)&&typeof n=="number"&&n!==0?n+"px":n};function ls(e,t,n){if(n==null)return"";if(n.__emotion_styles!==void 0)return n;switch(typeof n){case"boolean":return"";case"object":{if(n.anim===1)return Pn={name:n.name,styles:n.styles,next:Pn},n.name;if(n.styles!==void 0){var r=n.next;if(r!==void 0)for(;r!==void 0;)Pn={name:r.name,styles:r.styles,next:Pn},r=r.next;var i=n.styles+";";return i}return e2(e,t,n)}case"function":{if(e!==void 0){var s=Pn,l=n(e);return Pn=s,ls(e,t,l)}break}}if(t==null)return n;var u=t[n];return u!==void 0?u:n}function e2(e,t,n){var r="";if(Array.isArray(n))for(var i=0;i{"use strict";Kv.exports=$v()});var r0=re(bl=>{"use strict";Object.defineProperty(bl,"__esModule",{value:!0});var t0=Ne();function n2(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach(function(n){if(n!=="default"){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}}),t.default=e,Object.freeze(t)}var qv=n2(t0),r2=typeof document!="undefined",e0=function(t){return t()},n0=qv["useInsertionEffect"]?qv["useInsertionEffect"]:!1,i2=r2&&n0||e0,o2=n0||t0.useLayoutEffect;bl.useInsertionEffectAlwaysWithSyncFallback=i2;bl.useInsertionEffectWithLayoutFallback=o2});var af=re((Xk,i0)=>{"use strict";i0.exports=r0()});var u0=re(Gt=>{"use strict";var Xe=Ne(),s2=Bd(),s0=Yd(),a2=al(),l2=$d(),lf=qd(),u2=sf(),c2=af();function a0(e){return e&&e.__esModule?e:{default:e}}var l0=a0(s2),o0=a0(a2),cf=typeof document!="undefined",df={}.hasOwnProperty,us=Xe.createContext(typeof HTMLElement!="undefined"?l0.default({key:"css"}):null),d2=us.Provider,f2=function(){return Xe.useContext(us)};Gt.withEmotionCache=function(t){return Xe.forwardRef(function(n,r){var i=Xe.useContext(us);return t(n,i,r)})};cf||(Gt.withEmotionCache=function(t){return function(n){var r=Xe.useContext(us);return r===null?(r=l0.default({key:"css"}),Xe.createElement(us.Provider,{value:r},t(n,r))):t(n,r)}});var Xi=Xe.createContext({}),p2=function(){return Xe.useContext(Xi)},h2=function(t,n){if(typeof n=="function"){var r=n(t);return r}return s0({},t,n)},m2=o0.default(function(e){return o0.default(function(t){return h2(e,t)})}),g2=function(t){var n=Xe.useContext(Xi);return t.theme!==n&&(n=m2(n)(t.theme)),Xe.createElement(Xi.Provider,{value:n},t.children)};function v2(e){var t=e.displayName||e.name||"Component",n=function(s,l){var u=Xe.useContext(Xi);return Xe.createElement(e,s0({theme:u,ref:l},s))},r=Xe.forwardRef(n);return r.displayName="WithTheme("+t+")",l2.default(r,e)}var uf="__EMOTION_TYPE_PLEASE_DO_NOT_USE__",y2=function(t,n){var r={};for(var i in n)df.call(n,i)&&(r[i]=n[i]);return r[uf]=t,r},b2=function(t){var n=t.cache,r=t.serialized,i=t.isStringTag;lf.registerStyles(n,r,i);var s=c2.useInsertionEffectAlwaysWithSyncFallback(function(){return lf.insertStyles(n,r,i)});if(!cf&&s!==void 0){for(var l,u=r.name,d=r.next;d!==void 0;)u+=" "+d.name,d=d.next;return Xe.createElement("style",(l={},l["data-emotion"]=n.key+" "+u,l.dangerouslySetInnerHTML={__html:s},l.nonce=n.sheet.nonce,l))}return null},I2=Gt.withEmotionCache(function(e,t,n){var r=e.css;typeof r=="string"&&t.registered[r]!==void 0&&(r=t.registered[r]);var i=e[uf],s=[r],l="";typeof e.className=="string"?l=lf.getRegisteredStyles(t.registered,s,e.className):e.className!=null&&(l=e.className+" ");var u=u2.serializeStyles(s,void 0,Xe.useContext(Xi));l+=t.key+"-"+u.name;var d={};for(var p in e)df.call(e,p)&&p!=="css"&&p!==uf&&(d[p]=e[p]);return d.ref=n,d.className=l,Xe.createElement(Xe.Fragment,null,Xe.createElement(b2,{cache:t,serialized:u,isStringTag:typeof i=="string"}),Xe.createElement(i,d))});Gt.CacheProvider=d2;Gt.Emotion=I2;Gt.ThemeContext=Xi;Gt.ThemeProvider=g2;Gt.__unsafe_useEmotionCache=f2;Gt.createEmotionProps=y2;Gt.hasOwnProperty=df;Gt.isBrowser=cf;Gt.useTheme=p2;Gt.withTheme=v2});var f0=re(Nt=>{"use strict";Object.defineProperty(Nt,"__esModule",{value:!0});var Dn=Ne();Bd();var nt=u0();Yd();al();Jd();$d();var Il=qd(),pf=sf(),ff=af(),c0=function(t,n){var r=arguments;if(n==null||!nt.hasOwnProperty.call(n,"css"))return Dn.createElement.apply(void 0,r);var i=r.length,s=new Array(i);s[0]=nt.Emotion,s[1]=nt.createEmotionProps(t,n);for(var l=2;l{"use strict";p0.exports=f0()});var Qy=re((Df,Qi)=>{(function(e,t){typeof Df=="object"&&typeof Qi!="undefined"?Qi.exports=t():typeof define=="function"&&define.amd?define(t):e.moment=t()})(Df,function(){"use strict";var e;function t(){return e.apply(null,arguments)}function n(o){e=o}function r(o){return o instanceof Array||Object.prototype.toString.call(o)==="[object Array]"}function i(o){return o!=null&&Object.prototype.toString.call(o)==="[object Object]"}function s(o,a){return Object.prototype.hasOwnProperty.call(o,a)}function l(o){if(Object.getOwnPropertyNames)return Object.getOwnPropertyNames(o).length===0;var a;for(a in o)if(s(o,a))return!1;return!0}function u(o){return o===void 0}function d(o){return typeof o=="number"||Object.prototype.toString.call(o)==="[object Number]"}function p(o){return o instanceof Date||Object.prototype.toString.call(o)==="[object Date]"}function g(o,a){var c=[],f,h=o.length;for(f=0;f>>0,f;for(f=0;f0)for(c=0;c=0;return(S?c?"+":"":"-")+Math.pow(10,Math.max(0,h)).toString().substr(1)+f}var wt=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,lt=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,we={},ce={};function G(o,a,c,f){var h=f;typeof f=="string"&&(h=function(){return this[f]()}),o&&(ce[o]=h),a&&(ce[a[0]]=function(){return ye(h.apply(this,arguments),a[1],a[2])}),c&&(ce[c]=function(){return this.localeData().ordinal(h.apply(this,arguments),o)})}function ut(o){return o.match(/\[[\s\S]/)?o.replace(/^\[|\]$/g,""):o.replace(/\\/g,"")}function ct(o){var a=o.match(wt),c,f;for(c=0,f=a.length;c=0&<.test(o);)o=o.replace(lt,f),lt.lastIndex=0,c-=1;return o}var Vt={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function Wn(o){var a=this._longDateFormat[o],c=this._longDateFormat[o.toUpperCase()];return a||!c?a:(this._longDateFormat[o]=c.match(wt).map(function(f){return f==="MMMM"||f==="MM"||f==="DD"||f==="dddd"?f.slice(1):f}).join(""),this._longDateFormat[o])}var oi="Invalid date";function Or(){return this._invalidDate}var Rr="%d",ar=/\d{1,2}/;function _r(o){return this._ordinal.replace("%d",o)}var Wr={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function Wl(o,a,c,f){var h=this._relativeTime[c];return Z(h)?h(o,a,c,f):h.replace(/%d/i,o)}function Gr(o,a){var c=this._relativeTime[o>0?"future":"past"];return Z(c)?c(a):c.replace(/%s/i,a)}var Gn={};function He(o,a){var c=o.toLowerCase();Gn[c]=Gn[c+"s"]=Gn[a]=o}function dt(o){return typeof o=="string"?Gn[o]||Gn[o.toLowerCase()]:void 0}function Lr(o){var a={},c,f;for(f in o)s(o,f)&&(c=dt(f),c&&(a[c]=o[f]));return a}var Ln={};function $e(o,a){Ln[o]=a}function Gl(o){var a=[],c;for(c in o)s(o,c)&&a.push({unit:c,priority:Ln[c]});return a.sort(function(f,h){return f.priority-h.priority}),a}function si(o){return o%4===0&&o%100!==0||o%400===0}function Mt(o){return o<0?Math.ceil(o)||0:Math.floor(o)}function Q(o){var a=+o,c=0;return a!==0&&isFinite(a)&&(c=Mt(a)),c}function b(o,a){return function(c){return c!=null?(X(this,o,c),t.updateOffset(this,a),this):L(this,o)}}function L(o,a){return o.isValid()?o._d["get"+(o._isUTC?"UTC":"")+a]():NaN}function X(o,a,c){o.isValid()&&!isNaN(c)&&(a==="FullYear"&&si(o.year())&&o.month()===1&&o.date()===29?(c=Q(c),o._d["set"+(o._isUTC?"UTC":"")+a](c,o.month(),gs(c,o.month()))):o._d["set"+(o._isUTC?"UTC":"")+a](c))}function J(o){return o=dt(o),Z(this[o])?this[o]():this}function q(o,a){if(typeof o=="object"){o=Lr(o);var c=Gl(o),f,h=c.length;for(f=0;f68?1900:2e3)};var Lf=b("FullYear",!0);function h1(){return si(this.year())}function m1(o,a,c,f,h,S,F){var H;return o<100&&o>=0?(H=new Date(o+400,a,c,f,h,S,F),isFinite(H.getFullYear())&&H.setFullYear(o)):H=new Date(o,a,c,f,h,S,F),H}function qi(o){var a,c;return o<100&&o>=0?(c=Array.prototype.slice.call(arguments),c[0]=o+400,a=new Date(Date.UTC.apply(null,c)),isFinite(a.getUTCFullYear())&&a.setUTCFullYear(o)):a=new Date(Date.UTC.apply(null,arguments)),a}function vs(o,a,c){var f=7+a-c,h=(7+qi(o,0,f).getUTCDay()-a)%7;return-h+f-1}function Vf(o,a,c,f,h){var S=(7+c-f)%7,F=vs(o,f,h),H=1+7*(a-1)+S+F,$,Ie;return H<=0?($=o-1,Ie=Ki($)+H):H>Ki(o)?($=o+1,Ie=H-Ki(o)):($=o,Ie=H),{year:$,dayOfYear:Ie}}function eo(o,a,c){var f=vs(o.year(),a,c),h=Math.floor((o.dayOfYear()-f-1)/7)+1,S,F;return h<1?(F=o.year()-1,S=h+Hn(F,a,c)):h>Hn(o.year(),a,c)?(S=h-Hn(o.year(),a,c),F=o.year()+1):(F=o.year(),S=h),{week:S,year:F}}function Hn(o,a,c){var f=vs(o,a,c),h=vs(o+1,a,c);return(Ki(o)-f+h)/7}G("w",["ww",2],"wo","week"),G("W",["WW",2],"Wo","isoWeek"),He("week","w"),He("isoWeek","W"),$e("week",5),$e("isoWeek",5),W("w",oe),W("ww",oe,xe),W("W",oe),W("WW",oe,xe),$i(["w","ww","W","WW"],function(o,a,c,f){a[f.substr(0,1)]=Q(o)});function g1(o){return eo(o,this._week.dow,this._week.doy).week}var v1={dow:0,doy:6};function y1(){return this._week.dow}function b1(){return this._week.doy}function I1(o){var a=this.localeData().week(this);return o==null?a:this.add((o-a)*7,"d")}function C1(o){var a=eo(this,1,4).week;return o==null?a:this.add((o-a)*7,"d")}G("d",0,"do","day"),G("dd",0,0,function(o){return this.localeData().weekdaysMin(this,o)}),G("ddd",0,0,function(o){return this.localeData().weekdaysShort(this,o)}),G("dddd",0,0,function(o){return this.localeData().weekdays(this,o)}),G("e",0,0,"weekday"),G("E",0,0,"isoWeekday"),He("day","d"),He("weekday","e"),He("isoWeekday","E"),$e("day",11),$e("weekday",11),$e("isoWeekday",11),W("d",oe),W("e",oe),W("E",oe),W("dd",function(o,a){return a.weekdaysMinRegex(o)}),W("ddd",function(o,a){return a.weekdaysShortRegex(o)}),W("dddd",function(o,a){return a.weekdaysRegex(o)}),$i(["dd","ddd","dddd"],function(o,a,c,f){var h=c._locale.weekdaysParse(o,f,c._strict);h!=null?a.d=h:w(c).invalidWeekday=o}),$i(["d","e","E"],function(o,a,c,f){a[f]=Q(o)});function S1(o,a){return typeof o!="string"?o:isNaN(o)?(o=a.weekdaysParse(o),typeof o=="number"?o:null):parseInt(o,10)}function w1(o,a){return typeof o=="string"?a.weekdaysParse(o)%7||7:isNaN(o)?null:o}function Vl(o,a){return o.slice(a,7).concat(o.slice(0,a))}var x1="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Bf="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),E1="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),A1=Yt,k1=Yt,F1=Yt;function T1(o,a){var c=r(this._weekdays)?this._weekdays:this._weekdays[o&&o!==!0&&this._weekdays.isFormat.test(a)?"format":"standalone"];return o===!0?Vl(c,this._week.dow):o?c[o.day()]:c}function N1(o){return o===!0?Vl(this._weekdaysShort,this._week.dow):o?this._weekdaysShort[o.day()]:this._weekdaysShort}function M1(o){return o===!0?Vl(this._weekdaysMin,this._week.dow):o?this._weekdaysMin[o.day()]:this._weekdaysMin}function P1(o,a,c){var f,h,S,F=o.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],f=0;f<7;++f)S=I([2e3,1]).day(f),this._minWeekdaysParse[f]=this.weekdaysMin(S,"").toLocaleLowerCase(),this._shortWeekdaysParse[f]=this.weekdaysShort(S,"").toLocaleLowerCase(),this._weekdaysParse[f]=this.weekdays(S,"").toLocaleLowerCase();return c?a==="dddd"?(h=We.call(this._weekdaysParse,F),h!==-1?h:null):a==="ddd"?(h=We.call(this._shortWeekdaysParse,F),h!==-1?h:null):(h=We.call(this._minWeekdaysParse,F),h!==-1?h:null):a==="dddd"?(h=We.call(this._weekdaysParse,F),h!==-1||(h=We.call(this._shortWeekdaysParse,F),h!==-1)?h:(h=We.call(this._minWeekdaysParse,F),h!==-1?h:null)):a==="ddd"?(h=We.call(this._shortWeekdaysParse,F),h!==-1||(h=We.call(this._weekdaysParse,F),h!==-1)?h:(h=We.call(this._minWeekdaysParse,F),h!==-1?h:null)):(h=We.call(this._minWeekdaysParse,F),h!==-1||(h=We.call(this._weekdaysParse,F),h!==-1)?h:(h=We.call(this._shortWeekdaysParse,F),h!==-1?h:null))}function D1(o,a,c){var f,h,S;if(this._weekdaysParseExact)return P1.call(this,o,a,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),f=0;f<7;f++){if(h=I([2e3,1]).day(f),c&&!this._fullWeekdaysParse[f]&&(this._fullWeekdaysParse[f]=new RegExp("^"+this.weekdays(h,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[f]=new RegExp("^"+this.weekdaysShort(h,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[f]=new RegExp("^"+this.weekdaysMin(h,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[f]||(S="^"+this.weekdays(h,"")+"|^"+this.weekdaysShort(h,"")+"|^"+this.weekdaysMin(h,""),this._weekdaysParse[f]=new RegExp(S.replace(".",""),"i")),c&&a==="dddd"&&this._fullWeekdaysParse[f].test(o))return f;if(c&&a==="ddd"&&this._shortWeekdaysParse[f].test(o))return f;if(c&&a==="dd"&&this._minWeekdaysParse[f].test(o))return f;if(!c&&this._weekdaysParse[f].test(o))return f}}function O1(o){if(!this.isValid())return o!=null?this:NaN;var a=this._isUTC?this._d.getUTCDay():this._d.getDay();return o!=null?(o=S1(o,this.localeData()),this.add(o-a,"d")):a}function R1(o){if(!this.isValid())return o!=null?this:NaN;var a=(this.day()+7-this.localeData()._week.dow)%7;return o==null?a:this.add(o-a,"d")}function _1(o){if(!this.isValid())return o!=null?this:NaN;if(o!=null){var a=w1(o,this.localeData());return this.day(this.day()%7?a:a-7)}else return this.day()||7}function W1(o){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Bl.call(this),o?this._weekdaysStrictRegex:this._weekdaysRegex):(s(this,"_weekdaysRegex")||(this._weekdaysRegex=A1),this._weekdaysStrictRegex&&o?this._weekdaysStrictRegex:this._weekdaysRegex)}function G1(o){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Bl.call(this),o?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(s(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=k1),this._weekdaysShortStrictRegex&&o?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function L1(o){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Bl.call(this),o?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(s(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=F1),this._weekdaysMinStrictRegex&&o?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Bl(){function o(Et,jn){return jn.length-Et.length}var a=[],c=[],f=[],h=[],S,F,H,$,Ie;for(S=0;S<7;S++)F=I([2e3,1]).day(S),H=Zt(this.weekdaysMin(F,"")),$=Zt(this.weekdaysShort(F,"")),Ie=Zt(this.weekdays(F,"")),a.push(H),c.push($),f.push(Ie),h.push(H),h.push($),h.push(Ie);a.sort(o),c.sort(o),f.sort(o),h.sort(o),this._weekdaysRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+f.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+c.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Hl(){return this.hours()%12||12}function V1(){return this.hours()||24}G("H",["HH",2],0,"hour"),G("h",["hh",2],0,Hl),G("k",["kk",2],0,V1),G("hmm",0,0,function(){return""+Hl.apply(this)+ye(this.minutes(),2)}),G("hmmss",0,0,function(){return""+Hl.apply(this)+ye(this.minutes(),2)+ye(this.seconds(),2)}),G("Hmm",0,0,function(){return""+this.hours()+ye(this.minutes(),2)}),G("Hmmss",0,0,function(){return""+this.hours()+ye(this.minutes(),2)+ye(this.seconds(),2)});function Hf(o,a){G(o,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),a)})}Hf("a",!0),Hf("A",!1),He("hour","h"),$e("hour",13);function Yf(o,a){return a._meridiemParse}W("a",Yf),W("A",Yf),W("H",oe),W("h",oe),W("k",oe),W("HH",oe,xe),W("hh",oe,xe),W("kk",oe,xe),W("hmm",it),W("hmmss",xn),W("Hmm",it),W("Hmmss",xn),be(["H","HH"],Ye),be(["k","kk"],function(o,a,c){var f=Q(o);a[Ye]=f===24?0:f}),be(["a","A"],function(o,a,c){c._isPm=c._locale.isPM(o),c._meridiem=o}),be(["h","hh"],function(o,a,c){a[Ye]=Q(o),w(c).bigHour=!0}),be("hmm",function(o,a,c){var f=o.length-2;a[Ye]=Q(o.substr(0,f)),a[pn]=Q(o.substr(f)),w(c).bigHour=!0}),be("hmmss",function(o,a,c){var f=o.length-4,h=o.length-2;a[Ye]=Q(o.substr(0,f)),a[pn]=Q(o.substr(f,2)),a[Bn]=Q(o.substr(h)),w(c).bigHour=!0}),be("Hmm",function(o,a,c){var f=o.length-2;a[Ye]=Q(o.substr(0,f)),a[pn]=Q(o.substr(f))}),be("Hmmss",function(o,a,c){var f=o.length-4,h=o.length-2;a[Ye]=Q(o.substr(0,f)),a[pn]=Q(o.substr(f,2)),a[Bn]=Q(o.substr(h))});function B1(o){return(o+"").toLowerCase().charAt(0)==="p"}var H1=/[ap]\.?m?\.?/i,Y1=b("Hours",!0);function Z1(o,a,c){return o>11?c?"pm":"PM":c?"am":"AM"}var Zf={calendar:Ve,longDateFormat:Vt,invalidDate:oi,ordinal:Rr,dayOfMonthOrdinalParse:ar,relativeTime:Wr,months:i1,monthsShort:Of,week:v1,weekdays:x1,weekdaysMin:E1,weekdaysShort:Bf,meridiemParse:H1},Te={},to={},no;function z1(o,a){var c,f=Math.min(o.length,a.length);for(c=0;c0;){if(h=ys(S.slice(0,c).join("-")),h)return h;if(f&&f.length>=c&&z1(S,f)>=c-1)break;c--}a++}return no}function j1(o){return o.match("^[^/\\\\]*$")!=null}function ys(o){var a=null,c;if(Te[o]===void 0&&typeof Qi!="undefined"&&Qi&&Qi.exports&&j1(o))try{a=no._abbr,c=require,c("./locale/"+o),lr(a)}catch(f){Te[o]=null}return Te[o]}function lr(o,a){var c;return o&&(u(a)?c=Yn(o):c=Yl(o,a),c?no=c:typeof console!="undefined"&&console.warn&&console.warn("Locale "+o+" not found. Did you forget to load it?")),no._abbr}function Yl(o,a){if(a!==null){var c,f=Zf;if(a.abbr=o,Te[o]!=null)B("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),f=Te[o]._config;else if(a.parentLocale!=null)if(Te[a.parentLocale]!=null)f=Te[a.parentLocale]._config;else if(c=ys(a.parentLocale),c!=null)f=c._config;else return to[a.parentLocale]||(to[a.parentLocale]=[]),to[a.parentLocale].push({name:o,config:a}),null;return Te[o]=new ue(pe(f,a)),to[o]&&to[o].forEach(function(h){Yl(h.name,h.config)}),lr(o),Te[o]}else return delete Te[o],null}function U1(o,a){if(a!=null){var c,f,h=Zf;Te[o]!=null&&Te[o].parentLocale!=null?Te[o].set(pe(Te[o]._config,a)):(f=ys(o),f!=null&&(h=f._config),a=pe(h,a),f==null&&(a.abbr=o),c=new ue(a),c.parentLocale=Te[o],Te[o]=c),lr(o)}else Te[o]!=null&&(Te[o].parentLocale!=null?(Te[o]=Te[o].parentLocale,o===lr()&&lr(o)):Te[o]!=null&&delete Te[o]);return Te[o]}function Yn(o){var a;if(o&&o._locale&&o._locale._abbr&&(o=o._locale._abbr),!o)return no;if(!r(o)){if(a=ys(o),a)return a;o=[o]}return X1(o)}function J1(){return te(Te)}function Zl(o){var a,c=o._a;return c&&w(o).overflow===-2&&(a=c[Vn]<0||c[Vn]>11?Vn:c[En]<1||c[En]>gs(c[gt],c[Vn])?En:c[Ye]<0||c[Ye]>24||c[Ye]===24&&(c[pn]!==0||c[Bn]!==0||c[Vr]!==0)?Ye:c[pn]<0||c[pn]>59?pn:c[Bn]<0||c[Bn]>59?Bn:c[Vr]<0||c[Vr]>999?Vr:-1,w(o)._overflowDayOfYear&&(aEn)&&(a=En),w(o)._overflowWeeks&&a===-1&&(a=t1),w(o)._overflowWeekday&&a===-1&&(a=n1),w(o).overflow=a),o}var Q1=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,$1=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,K1=/Z|[+-]\d\d(?::?\d\d)?/,bs=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],zl=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],q1=/^\/?Date\((-?\d+)/i,eb=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,tb={UT:0,GMT:0,EDT:-4*60,EST:-5*60,CDT:-5*60,CST:-6*60,MDT:-6*60,MST:-7*60,PDT:-7*60,PST:-8*60};function Xf(o){var a,c,f=o._i,h=Q1.exec(f)||$1.exec(f),S,F,H,$,Ie=bs.length,Et=zl.length;if(h){for(w(o).iso=!0,a=0,c=Ie;aKi(F)||o._dayOfYear===0)&&(w(o)._overflowDayOfYear=!0),c=qi(F,0,o._dayOfYear),o._a[Vn]=c.getUTCMonth(),o._a[En]=c.getUTCDate()),a=0;a<3&&o._a[a]==null;++a)o._a[a]=f[a]=h[a];for(;a<7;a++)o._a[a]=f[a]=o._a[a]==null?a===2?1:0:o._a[a];o._a[Ye]===24&&o._a[pn]===0&&o._a[Bn]===0&&o._a[Vr]===0&&(o._nextDay=!0,o._a[Ye]=0),o._d=(o._useUTC?qi:m1).apply(null,f),S=o._useUTC?o._d.getUTCDay():o._d.getDay(),o._tzm!=null&&o._d.setUTCMinutes(o._d.getUTCMinutes()-o._tzm),o._nextDay&&(o._a[Ye]=24),o._w&&typeof o._w.d!="undefined"&&o._w.d!==S&&(w(o).weekdayMismatch=!0)}}function ub(o){var a,c,f,h,S,F,H,$,Ie;a=o._w,a.GG!=null||a.W!=null||a.E!=null?(S=1,F=4,c=li(a.GG,o._a[gt],eo(Ee(),1,4).year),f=li(a.W,1),h=li(a.E,1),(h<1||h>7)&&($=!0)):(S=o._locale._week.dow,F=o._locale._week.doy,Ie=eo(Ee(),S,F),c=li(a.gg,o._a[gt],Ie.year),f=li(a.w,Ie.week),a.d!=null?(h=a.d,(h<0||h>6)&&($=!0)):a.e!=null?(h=a.e+S,(a.e<0||a.e>6)&&($=!0)):h=S),f<1||f>Hn(c,S,F)?w(o)._overflowWeeks=!0:$!=null?w(o)._overflowWeekday=!0:(H=Vf(c,f,h,S,F),o._a[gt]=H.year,o._dayOfYear=H.dayOfYear)}t.ISO_8601=function(){},t.RFC_2822=function(){};function jl(o){if(o._f===t.ISO_8601){Xf(o);return}if(o._f===t.RFC_2822){jf(o);return}o._a=[],w(o).empty=!0;var a=""+o._i,c,f,h,S,F,H=a.length,$=0,Ie,Et;for(h=rt(o._f,o._locale).match(wt)||[],Et=h.length,c=0;c0&&w(o).unusedInput.push(F),a=a.slice(a.indexOf(f)+f.length),$+=f.length),ce[S]?(f?w(o).empty=!1:w(o).unusedTokens.push(S),e1(S,f,o)):o._strict&&!f&&w(o).unusedTokens.push(S);w(o).charsLeftOver=H-$,a.length>0&&w(o).unusedInput.push(a),o._a[Ye]<=12&&w(o).bigHour===!0&&o._a[Ye]>0&&(w(o).bigHour=void 0),w(o).parsedDateParts=o._a.slice(0),w(o).meridiem=o._meridiem,o._a[Ye]=cb(o._locale,o._a[Ye],o._meridiem),Ie=w(o).era,Ie!==null&&(o._a[gt]=o._locale.erasConvertYear(Ie,o._a[gt])),Xl(o),Zl(o)}function cb(o,a,c){var f;return c==null?a:o.meridiemHour!=null?o.meridiemHour(a,c):(o.isPM!=null&&(f=o.isPM(c),f&&a<12&&(a+=12),!f&&a===12&&(a=0)),a)}function db(o){var a,c,f,h,S,F,H=!1,$=o._f.length;if($===0){w(o).invalidFormat=!0,o._d=new Date(NaN);return}for(h=0;h<$;h++)S=0,F=!1,a=k({},o),o._useUTC!=null&&(a._useUTC=o._useUTC),a._f=o._f[h],jl(a),x(a)&&(F=!0),S+=w(a).charsLeftOver,S+=w(a).unusedTokens.length*10,w(a).score=S,H?Sthis?this:o:m()});function Qf(o,a){var c,f;if(a.length===1&&r(a[0])&&(a=a[0]),!a.length)return Ee();for(c=a[0],f=1;fthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Pb(){if(!u(this._isDSTShifted))return this._isDSTShifted;var o={},a;return k(o,this),o=Uf(o),o._a?(a=o._isUTC?I(o._a):Ee(o._a),this._isDSTShifted=this.isValid()&&wb(o._a,a.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Db(){return this.isValid()?!this._isUTC:!1}function Ob(){return this.isValid()?this._isUTC:!1}function Kf(){return this.isValid()?this._isUTC&&this._offset===0:!1}var Rb=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,_b=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function hn(o,a){var c=o,f=null,h,S,F;return Cs(o)?c={ms:o._milliseconds,d:o._days,M:o._months}:d(o)||!isNaN(+o)?(c={},a?c[a]=+o:c.milliseconds=+o):(f=Rb.exec(o))?(h=f[1]==="-"?-1:1,c={y:0,d:Q(f[En])*h,h:Q(f[Ye])*h,m:Q(f[pn])*h,s:Q(f[Bn])*h,ms:Q(Ul(f[Vr]*1e3))*h}):(f=_b.exec(o))?(h=f[1]==="-"?-1:1,c={y:Br(f[2],h),M:Br(f[3],h),w:Br(f[4],h),d:Br(f[5],h),h:Br(f[6],h),m:Br(f[7],h),s:Br(f[8],h)}):c==null?c={}:typeof c=="object"&&("from"in c||"to"in c)&&(F=Wb(Ee(c.from),Ee(c.to)),c={},c.ms=F.milliseconds,c.M=F.months),S=new Is(c),Cs(o)&&s(o,"_locale")&&(S._locale=o._locale),Cs(o)&&s(o,"_isValid")&&(S._isValid=o._isValid),S}hn.fn=Is.prototype,hn.invalid=Sb;function Br(o,a){var c=o&&parseFloat(o.replace(",","."));return(isNaN(c)?0:c)*a}function qf(o,a){var c={};return c.months=a.month()-o.month()+(a.year()-o.year())*12,o.clone().add(c.months,"M").isAfter(a)&&--c.months,c.milliseconds=+a-+o.clone().add(c.months,"M"),c}function Wb(o,a){var c;return o.isValid()&&a.isValid()?(a=Ql(a,o),o.isBefore(a)?c=qf(o,a):(c=qf(a,o),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function ep(o,a){return function(c,f){var h,S;return f!==null&&!isNaN(+f)&&(B(a,"moment()."+a+"(period, number) is deprecated. Please use moment()."+a+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),S=c,c=f,f=S),h=hn(c,f),tp(this,h,o),this}}function tp(o,a,c,f){var h=a._milliseconds,S=Ul(a._days),F=Ul(a._months);!o.isValid()||(f=f==null?!0:f,F&&_f(o,L(o,"Month")+F*c),S&&X(o,"Date",L(o,"Date")+S*c),h&&o._d.setTime(o._d.valueOf()+h*c),f&&t.updateOffset(o,S||F))}var Gb=ep(1,"add"),Lb=ep(-1,"subtract");function np(o){return typeof o=="string"||o instanceof String}function Vb(o){return N(o)||p(o)||np(o)||d(o)||Hb(o)||Bb(o)||o===null||o===void 0}function Bb(o){var a=i(o)&&!l(o),c=!1,f=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],h,S,F=f.length;for(h=0;hc.valueOf():c.valueOf()9999?Be(c,a?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):Z(Date.prototype.toISOString)?a?this.toDate().toISOString():new Date(this.valueOf()+this.utcOffset()*60*1e3).toISOString().replace("Z",Be(c,"Z")):Be(c,a?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function nI(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var o="moment",a="",c,f,h,S;return this.isLocal()||(o=this.utcOffset()===0?"moment.utc":"moment.parseZone",a="Z"),c="["+o+'("]',f=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",h="-MM-DD[T]HH:mm:ss.SSS",S=a+'[")]',this.format(c+f+h+S)}function rI(o){o||(o=this.isUtc()?t.defaultFormatUtc:t.defaultFormat);var a=Be(this,o);return this.localeData().postformat(a)}function iI(o,a){return this.isValid()&&(N(o)&&o.isValid()||Ee(o).isValid())?hn({to:this,from:o}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function oI(o){return this.from(Ee(),o)}function sI(o,a){return this.isValid()&&(N(o)&&o.isValid()||Ee(o).isValid())?hn({from:this,to:o}).locale(this.locale()).humanize(!a):this.localeData().invalidDate()}function aI(o){return this.to(Ee(),o)}function rp(o){var a;return o===void 0?this._locale._abbr:(a=Yn(o),a!=null&&(this._locale=a),this)}var ip=P("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(o){return o===void 0?this.localeData():this.locale(o)});function op(){return this._locale}var ws=1e3,ui=60*ws,xs=60*ui,sp=(365*400+97)*24*xs;function ci(o,a){return(o%a+a)%a}function ap(o,a,c){return o<100&&o>=0?new Date(o+400,a,c)-sp:new Date(o,a,c).valueOf()}function lp(o,a,c){return o<100&&o>=0?Date.UTC(o+400,a,c)-sp:Date.UTC(o,a,c)}function lI(o){var a,c;if(o=dt(o),o===void 0||o==="millisecond"||!this.isValid())return this;switch(c=this._isUTC?lp:ap,o){case"year":a=c(this.year(),0,1);break;case"quarter":a=c(this.year(),this.month()-this.month()%3,1);break;case"month":a=c(this.year(),this.month(),1);break;case"week":a=c(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":a=c(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":a=c(this.year(),this.month(),this.date());break;case"hour":a=this._d.valueOf(),a-=ci(a+(this._isUTC?0:this.utcOffset()*ui),xs);break;case"minute":a=this._d.valueOf(),a-=ci(a,ui);break;case"second":a=this._d.valueOf(),a-=ci(a,ws);break}return this._d.setTime(a),t.updateOffset(this,!0),this}function uI(o){var a,c;if(o=dt(o),o===void 0||o==="millisecond"||!this.isValid())return this;switch(c=this._isUTC?lp:ap,o){case"year":a=c(this.year()+1,0,1)-1;break;case"quarter":a=c(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":a=c(this.year(),this.month()+1,1)-1;break;case"week":a=c(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":a=c(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":a=c(this.year(),this.month(),this.date()+1)-1;break;case"hour":a=this._d.valueOf(),a+=xs-ci(a+(this._isUTC?0:this.utcOffset()*ui),xs)-1;break;case"minute":a=this._d.valueOf(),a+=ui-ci(a,ui)-1;break;case"second":a=this._d.valueOf(),a+=ws-ci(a,ws)-1;break}return this._d.setTime(a),t.updateOffset(this,!0),this}function cI(){return this._d.valueOf()-(this._offset||0)*6e4}function dI(){return Math.floor(this.valueOf()/1e3)}function fI(){return new Date(this.valueOf())}function pI(){var o=this;return[o.year(),o.month(),o.date(),o.hour(),o.minute(),o.second(),o.millisecond()]}function hI(){var o=this;return{years:o.year(),months:o.month(),date:o.date(),hours:o.hours(),minutes:o.minutes(),seconds:o.seconds(),milliseconds:o.milliseconds()}}function mI(){return this.isValid()?this.toISOString():null}function gI(){return x(this)}function vI(){return v({},w(this))}function yI(){return w(this).overflow}function bI(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}G("N",0,0,"eraAbbr"),G("NN",0,0,"eraAbbr"),G("NNN",0,0,"eraAbbr"),G("NNNN",0,0,"eraName"),G("NNNNN",0,0,"eraNarrow"),G("y",["y",1],"yo","eraYear"),G("y",["yy",2],0,"eraYear"),G("y",["yyy",3],0,"eraYear"),G("y",["yyyy",4],0,"eraYear"),W("N",Kl),W("NN",Kl),W("NNN",Kl),W("NNNN",NI),W("NNNNN",MI),be(["N","NN","NNN","NNNN","NNNNN"],function(o,a,c,f){var h=c._locale.erasParse(o,f,c._strict);h?w(c).era=h:w(c).invalidEra=o}),W("y",fn),W("yy",fn),W("yyy",fn),W("yyyy",fn),W("yo",PI),be(["y","yy","yyy","yyyy"],gt),be(["yo"],function(o,a,c,f){var h;c._locale._eraYearOrdinalRegex&&(h=o.match(c._locale._eraYearOrdinalRegex)),c._locale.eraYearOrdinalParse?a[gt]=c._locale.eraYearOrdinalParse(o,h):a[gt]=parseInt(o,10)});function II(o,a){var c,f,h,S=this._eras||Yn("en")._eras;for(c=0,f=S.length;c=0)return S[f]}function SI(o,a){var c=o.since<=o.until?1:-1;return a===void 0?t(o.since).year():t(o.since).year()+(a-o.offset)*c}function wI(){var o,a,c,f=this.localeData().eras();for(o=0,a=f.length;oS&&(a=S),LI.call(this,o,a,c,f,h))}function LI(o,a,c,f,h){var S=Vf(o,a,c,f,h),F=qi(S.year,0,S.dayOfYear);return this.year(F.getUTCFullYear()),this.month(F.getUTCMonth()),this.date(F.getUTCDate()),this}G("Q",0,"Qo","quarter"),He("quarter","Q"),$e("quarter",7),W("Q",ft),be("Q",function(o,a){a[Vn]=(Q(o)-1)*3});function VI(o){return o==null?Math.ceil((this.month()+1)/3):this.month((o-1)*3+this.month()%3)}G("D",["DD",2],"Do","date"),He("date","D"),$e("date",9),W("D",oe),W("DD",oe,xe),W("Do",function(o,a){return o?a._dayOfMonthOrdinalParse||a._ordinalParse:a._dayOfMonthOrdinalParseLenient}),be(["D","DD"],En),be("Do",function(o,a){a[En]=Q(o.match(oe)[0])});var cp=b("Date",!0);G("DDD",["DDDD",3],"DDDo","dayOfYear"),He("dayOfYear","DDD"),$e("dayOfYear",4),W("DDD",dn),W("DDDD",Ke),be(["DDD","DDDD"],function(o,a,c){c._dayOfYear=Q(o)});function BI(o){var a=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return o==null?a:this.add(o-a,"d")}G("m",["mm",2],0,"minute"),He("minute","m"),$e("minute",14),W("m",oe),W("mm",oe,xe),be(["m","mm"],pn);var HI=b("Minutes",!1);G("s",["ss",2],0,"second"),He("second","s"),$e("second",15),W("s",oe),W("ss",oe,xe),be(["s","ss"],Bn);var YI=b("Seconds",!1);G("S",0,0,function(){return~~(this.millisecond()/100)}),G(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),G(0,["SSS",3],0,"millisecond"),G(0,["SSSS",4],0,function(){return this.millisecond()*10}),G(0,["SSSSS",5],0,function(){return this.millisecond()*100}),G(0,["SSSSSS",6],0,function(){return this.millisecond()*1e3}),G(0,["SSSSSSS",7],0,function(){return this.millisecond()*1e4}),G(0,["SSSSSSSS",8],0,function(){return this.millisecond()*1e5}),G(0,["SSSSSSSSS",9],0,function(){return this.millisecond()*1e6}),He("millisecond","ms"),$e("millisecond",16),W("S",dn,ft),W("SS",dn,xe),W("SSS",dn,Ke);var ur,dp;for(ur="SSSS";ur.length<=9;ur+="S")W(ur,fn);function ZI(o,a){a[Vr]=Q(("0."+o)*1e3)}for(ur="S";ur.length<=9;ur+="S")be(ur,ZI);dp=b("Milliseconds",!1),G("z",0,0,"zoneAbbr"),G("zz",0,0,"zoneName");function zI(){return this._isUTC?"UTC":""}function XI(){return this._isUTC?"Coordinated Universal Time":""}var _=M.prototype;_.add=Gb,_.calendar=zb,_.clone=Xb,_.diff=qb,_.endOf=uI,_.format=rI,_.from=iI,_.fromNow=oI,_.to=sI,_.toNow=aI,_.get=J,_.invalidAt=yI,_.isAfter=jb,_.isBefore=Ub,_.isBetween=Jb,_.isSame=Qb,_.isSameOrAfter=$b,_.isSameOrBefore=Kb,_.isValid=gI,_.lang=ip,_.locale=rp,_.localeData=op,_.max=gb,_.min=mb,_.parsingFlags=vI,_.set=q,_.startOf=lI,_.subtract=Lb,_.toArray=pI,_.toObject=hI,_.toDate=fI,_.toISOString=tI,_.inspect=nI,typeof Symbol!="undefined"&&Symbol.for!=null&&(_[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),_.toJSON=mI,_.toString=eI,_.unix=dI,_.valueOf=cI,_.creationData=bI,_.eraName=wI,_.eraNarrow=xI,_.eraAbbr=EI,_.eraYear=AI,_.year=Lf,_.isLeapYear=h1,_.weekYear=DI,_.isoWeekYear=OI,_.quarter=_.quarters=VI,_.month=Wf,_.daysInMonth=d1,_.week=_.weeks=I1,_.isoWeek=_.isoWeeks=C1,_.weeksInYear=WI,_.weeksInWeekYear=GI,_.isoWeeksInYear=RI,_.isoWeeksInISOWeekYear=_I,_.date=cp,_.day=_.days=O1,_.weekday=R1,_.isoWeekday=_1,_.dayOfYear=BI,_.hour=_.hours=Y1,_.minute=_.minutes=HI,_.second=_.seconds=YI,_.millisecond=_.milliseconds=dp,_.utcOffset=Eb,_.utc=kb,_.local=Fb,_.parseZone=Tb,_.hasAlignedHourOffset=Nb,_.isDST=Mb,_.isLocal=Db,_.isUtcOffset=Ob,_.isUtc=Kf,_.isUTC=Kf,_.zoneAbbr=zI,_.zoneName=XI,_.dates=P("dates accessor is deprecated. Use date instead.",cp),_.months=P("months accessor is deprecated. Use month instead",Wf),_.years=P("years accessor is deprecated. Use year instead",Lf),_.zone=P("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Ab),_.isDSTShifted=P("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Pb);function jI(o){return Ee(o*1e3)}function UI(){return Ee.apply(null,arguments).parseZone()}function fp(o){return o}var de=ue.prototype;de.calendar=Qe,de.longDateFormat=Wn,de.invalidDate=Or,de.ordinal=_r,de.preparse=fp,de.postformat=fp,de.relativeTime=Wl,de.pastFuture=Gr,de.set=ie,de.eras=II,de.erasParse=CI,de.erasConvertYear=SI,de.erasAbbrRegex=FI,de.erasNameRegex=kI,de.erasNarrowRegex=TI,de.months=a1,de.monthsShort=l1,de.monthsParse=c1,de.monthsRegex=p1,de.monthsShortRegex=f1,de.week=g1,de.firstDayOfYear=b1,de.firstDayOfWeek=y1,de.weekdays=T1,de.weekdaysMin=M1,de.weekdaysShort=N1,de.weekdaysParse=D1,de.weekdaysRegex=W1,de.weekdaysShortRegex=G1,de.weekdaysMinRegex=L1,de.isPM=B1,de.meridiem=Z1;function As(o,a,c,f){var h=Yn(),S=I().set(f,a);return h[c](S,o)}function pp(o,a,c){if(d(o)&&(a=o,o=void 0),o=o||"",a!=null)return As(o,a,c,"month");var f,h=[];for(f=0;f<12;f++)h[f]=As(o,f,c,"month");return h}function eu(o,a,c,f){typeof o=="boolean"?(d(a)&&(c=a,a=void 0),a=a||""):(a=o,c=a,o=!1,d(a)&&(c=a,a=void 0),a=a||"");var h=Yn(),S=o?h._week.dow:0,F,H=[];if(c!=null)return As(a,(c+S)%7,f,"day");for(F=0;F<7;F++)H[F]=As(a,(F+S)%7,f,"day");return H}function JI(o,a){return pp(o,a,"months")}function QI(o,a){return pp(o,a,"monthsShort")}function $I(o,a,c){return eu(o,a,c,"weekdays")}function KI(o,a,c){return eu(o,a,c,"weekdaysShort")}function qI(o,a,c){return eu(o,a,c,"weekdaysMin")}lr("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(o){var a=o%10,c=Q(o%100/10)===1?"th":a===1?"st":a===2?"nd":a===3?"rd":"th";return o+c}}),t.lang=P("moment.lang is deprecated. Use moment.locale instead.",lr),t.langData=P("moment.langData is deprecated. Use moment.localeData instead.",Yn);var Zn=Math.abs;function eC(){var o=this._data;return this._milliseconds=Zn(this._milliseconds),this._days=Zn(this._days),this._months=Zn(this._months),o.milliseconds=Zn(o.milliseconds),o.seconds=Zn(o.seconds),o.minutes=Zn(o.minutes),o.hours=Zn(o.hours),o.months=Zn(o.months),o.years=Zn(o.years),this}function hp(o,a,c,f){var h=hn(a,c);return o._milliseconds+=f*h._milliseconds,o._days+=f*h._days,o._months+=f*h._months,o._bubble()}function tC(o,a){return hp(this,o,a,1)}function nC(o,a){return hp(this,o,a,-1)}function mp(o){return o<0?Math.floor(o):Math.ceil(o)}function rC(){var o=this._milliseconds,a=this._days,c=this._months,f=this._data,h,S,F,H,$;return o>=0&&a>=0&&c>=0||o<=0&&a<=0&&c<=0||(o+=mp(tu(c)+a)*864e5,a=0,c=0),f.milliseconds=o%1e3,h=Mt(o/1e3),f.seconds=h%60,S=Mt(h/60),f.minutes=S%60,F=Mt(S/60),f.hours=F%24,a+=Mt(F/24),$=Mt(gp(a)),c+=$,a-=mp(tu($)),H=Mt(c/12),c%=12,f.days=a,f.months=c,f.years=H,this}function gp(o){return o*4800/146097}function tu(o){return o*146097/4800}function iC(o){if(!this.isValid())return NaN;var a,c,f=this._milliseconds;if(o=dt(o),o==="month"||o==="quarter"||o==="year")switch(a=this._days+f/864e5,c=this._months+gp(a),o){case"month":return c;case"quarter":return c/3;case"year":return c/12}else switch(a=this._days+Math.round(tu(this._months)),o){case"week":return a/7+f/6048e5;case"day":return a+f/864e5;case"hour":return a*24+f/36e5;case"minute":return a*1440+f/6e4;case"second":return a*86400+f/1e3;case"millisecond":return Math.floor(a*864e5)+f;default:throw new Error("Unknown unit "+o)}}function oC(){return this.isValid()?this._milliseconds+this._days*864e5+this._months%12*2592e6+Q(this._months/12)*31536e6:NaN}function zn(o){return function(){return this.as(o)}}var sC=zn("ms"),aC=zn("s"),lC=zn("m"),uC=zn("h"),cC=zn("d"),dC=zn("w"),fC=zn("M"),pC=zn("Q"),hC=zn("y");function mC(){return hn(this)}function gC(o){return o=dt(o),this.isValid()?this[o+"s"]():NaN}function Hr(o){return function(){return this.isValid()?this._data[o]:NaN}}var vC=Hr("milliseconds"),yC=Hr("seconds"),bC=Hr("minutes"),IC=Hr("hours"),CC=Hr("days"),SC=Hr("months"),wC=Hr("years");function xC(){return Mt(this.days()/7)}var Xn=Math.round,di={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function EC(o,a,c,f,h){return h.relativeTime(a||1,!!c,o,f)}function AC(o,a,c,f){var h=hn(o).abs(),S=Xn(h.as("s")),F=Xn(h.as("m")),H=Xn(h.as("h")),$=Xn(h.as("d")),Ie=Xn(h.as("M")),Et=Xn(h.as("w")),jn=Xn(h.as("y")),cr=S<=c.ss&&["s",S]||S0,cr[4]=f,EC.apply(null,cr)}function kC(o){return o===void 0?Xn:typeof o=="function"?(Xn=o,!0):!1}function FC(o,a){return di[o]===void 0?!1:a===void 0?di[o]:(di[o]=a,o==="s"&&(di.ss=a-1),!0)}function TC(o,a){if(!this.isValid())return this.localeData().invalidDate();var c=!1,f=di,h,S;return typeof o=="object"&&(a=o,o=!1),typeof o=="boolean"&&(c=o),typeof a=="object"&&(f=Object.assign({},di,a),a.s!=null&&a.ss==null&&(f.ss=a.s-1)),h=this.localeData(),S=AC(this,!c,f,h),c&&(S=h.pastFuture(+this,S)),h.postformat(S)}var nu=Math.abs;function fi(o){return(o>0)-(o<0)||+o}function ks(){if(!this.isValid())return this.localeData().invalidDate();var o=nu(this._milliseconds)/1e3,a=nu(this._days),c=nu(this._months),f,h,S,F,H=this.asSeconds(),$,Ie,Et,jn;return H?(f=Mt(o/60),h=Mt(f/60),o%=60,f%=60,S=Mt(c/12),c%=12,F=o?o.toFixed(3).replace(/\.?0+$/,""):"",$=H<0?"-":"",Ie=fi(this._months)!==fi(H)?"-":"",Et=fi(this._days)!==fi(H)?"-":"",jn=fi(this._milliseconds)!==fi(H)?"-":"",$+"P"+(S?Ie+S+"Y":"")+(c?Ie+c+"M":"")+(a?Et+a+"D":"")+(h||f||o?"T":"")+(h?jn+h+"H":"")+(f?jn+f+"M":"")+(o?jn+F+"S":"")):"P0D"}var se=Is.prototype;se.isValid=Cb,se.abs=eC,se.add=tC,se.subtract=nC,se.as=iC,se.asMilliseconds=sC,se.asSeconds=aC,se.asMinutes=lC,se.asHours=uC,se.asDays=cC,se.asWeeks=dC,se.asMonths=fC,se.asQuarters=pC,se.asYears=hC,se.valueOf=oC,se._bubble=rC,se.clone=mC,se.get=gC,se.milliseconds=vC,se.seconds=yC,se.minutes=bC,se.hours=IC,se.days=CC,se.weeks=xC,se.months=SC,se.years=wC,se.humanize=TC,se.toISOString=ks,se.toString=ks,se.toJSON=ks,se.locale=rp,se.localeData=op,se.toIsoString=P("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ks),se.lang=ip,G("X",0,0,"unix"),G("x",0,0,"valueOf"),W("x",ht),W("X",ai),be("X",function(o,a,c){c._d=new Date(parseFloat(o)*1e3)}),be("x",function(o,a,c){c._d=new Date(Q(o))});return t.version="2.29.4",n(Ee),t.fn=_,t.min=vb,t.max=yb,t.now=bb,t.utc=I,t.unix=jI,t.months=JI,t.isDate=p,t.locale=lr,t.invalid=m,t.duration=hn,t.isMoment=N,t.weekdays=$I,t.parseZone=UI,t.localeData=Yn,t.isDuration=Cs,t.monthsShort=QI,t.weekdaysMin=qI,t.defineLocale=Yl,t.updateLocale=U1,t.locales=J1,t.weekdaysShort=KI,t.normalizeUnits=dt,t.relativeTimeRounding=kC,t.relativeTimeThreshold=FC,t.calendarFormat=Zb,t.prototype=_,t.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},t})});var rA={};WC(rA,{default:()=>_l});module.exports=GC(rA);var ev=require("obsidian"),St=he(Ne()),tv=he(qo()),Qa=require("obsidian"),$a=class extends ev.Modal{constructor(n,r,i){super(n);this.plugin=r,this.view=i,this.date=(0,Qa.moment)().format("YYYY-MM-DD")}render(){this.root.render(St.createElement(St.StrictMode,null,St.createElement("div",{className:"janitor-date-picker"},St.createElement("form",{onSubmit:this.onApply.bind(this)},St.createElement("label",null,St.createElement("span",null,"Choose a date:"),St.createElement("input",{type:"date",value:this.date,onChange:this.onDateChange.bind(this)})),St.createElement("div",{className:"janitor-date-picker-buttons"},St.createElement("button",{type:"button",onClick:n=>this.close()},"Cancel "),St.createElement("button",{className:"mod-cta",type:"submit"},"OK")),St.createElement("div",{className:"janitor-date-shortcuts"},St.createElement("button",{onClick:n=>this.dateShortcut(n,1,"weeks"),className:"janitor-date-shortcut=button"},"In a Week"),St.createElement("button",{onClick:n=>this.dateShortcut(n,1,"months"),className:"janitor-date-shortcut=button"},"In a Month"),St.createElement("button",{onClick:n=>this.dateShortcut(n,1,"years"),className:"janitor-date-shortcut=button"},"In a Year"))))))}dateShortcut(n,r,i){this.date=(0,Qa.moment)().add(r,i).format("YYYY-MM-DD"),this.render()}onApply(n){n.preventDefault();let r=(0,Qa.moment)(this.date,"YYYY-MM-DD").format(this.plugin.settings.expiredDateFormat);return this.plugin.updateNoteWithDate(this.view,r),this.close(),!1}onDateChange(n){this.date=n.target.value,this.render()}onOpen(){let{contentEl:n}=this;this.root=(0,tv.createRoot)(n),this.render()}onClose(){this.root.unmount()}};var K=he(Ne()),Fe=he(Ne()),iv=he(Ko()),ov=require("obsidian");var Ka=(r=>(r.Trash="trash",r.TrashSystem="trash-system",r.Delete="delete",r))(Ka||{}),qa={runAtStartup:!1,addRibbonIcon:!0,promptUser:!0,promptForBigFiles:!0,attachmentsExtensions:".jpg|.jpeg|.png|.gif|.svg|.pdf",defaultOperation:"trash",expiredAttribute:"expires",expiredDateFormat:"YYYY-MM-DD",sizeLimitKb:1024,processOrphans:!0,ignoreBaseFiles:!0,processEmpty:!0,emptyIgnoresFrontmatter:!1,processEmptyFolders:!1,processExpired:!0,processBig:!0,honorObsidianExcludedFiles:!0,excludedFilesFilters:[],includedFilesFilters:[]};var sv=e=>{let{scanning:t,onClose:n,onPerform:r}=e,i=[e.orphans,e.empty,e.emptyFolders,e.expired,e.big].some(u=>u&&u.some(d=>d.selected)),s=(0,Fe.useCallback)(u=>(0,Fe.useCallback)(()=>{r(u)},[u,r]),[r]),l=Object.values(Ka).reduce((u,d)=>ne(j({},u),{[d]:s(d)}),{});return K.createElement("div",{className:"janitor-modal-wrapper"},K.createElement("div",{className:"janitor-modal-title"},"Janitor Scan Results"),K.createElement("div",{className:"janitor-modal-content"},t?K.createElement("h4",null,"Scanning..."):K.createElement(tx,j({},e))),K.createElement("div",{className:"janitor-modal-footer"},K.createElement("div",{className:"janitor-footer-buttons"},K.createElement("button",{tabIndex:1,style:{visibility:i?"visible":"hidden"},className:"",onClick:l["trash"],title:"Put files in the Obsidian .trash"},"Trash (Obsidian)"),K.createElement("button",{tabIndex:1,style:{visibility:i?"visible":"hidden"},className:"",onClick:l["trash-system"],title:"Put files in the OS' trash"},"Trash (System)"),K.createElement("button",{tabIndex:1,style:{visibility:i?"visible":"hidden"},className:"",onClick:l["delete"],title:"Permanently delete files"},"Delete"),K.createElement("button",{tabIndex:1,className:"mod-cta",onClick:n},"Cancel"))))};function tx({app:e,orphans:t,empty:n,emptyFolders:r,big:i,expired:s,onSelectionChange:l,onOpen:u}){let d=(0,Fe.useCallback)(g=>(0,Fe.useCallback)(v=>{l(v,g)},[l,g]),[l]),p=(0,Fe.useCallback)(g=>(0,Fe.useCallback)(v=>{u(v,g)},[u,g]),[u]);return K.createElement("div",{className:"janitor-scan-results"},t&&t.length>0&&K.createElement(es,{app:e,files:t,onChange:d("orphans"),onOpen:p("orphans"),title:"Orphans"}),n&&n.length>0&&K.createElement(es,{app:e,title:"Empty",files:n,onChange:d("empty"),onOpen:p("empty")}),r&&r.length>0&&K.createElement(es,{app:e,title:"Empty Folders",files:r,onChange:d("emptyFolders"),onOpen:p("emptyFolders"),showPreview:!1}),s&&s.length>0&&K.createElement(es,{app:e,title:"Expired",files:s,onChange:d("expired"),onOpen:p("expired")}),i&&i.length>0&&K.createElement(es,{app:e,title:"Big",files:i,onChange:d("big"),onOpen:p("big")}))}var nv=({text:e})=>{let t=(0,Fe.useRef)(null),n=(0,Fe.useRef)(null),[r,i]=(0,Fe.useState)(0);return(0,Fe.useEffect)(()=>{if(t.current&&n.current){let s=n.current.scrollWidth-t.current.clientWidth;i(Math.max(0,s))}},[e]),K.createElement("div",{ref:t,className:"janitor-file-name"},K.createElement("span",{ref:n,className:"janitor-file-name-text",style:{"--marquee-offset":`-${r}px`},title:e},e))},rv=({id:e})=>{let t=(0,Fe.useRef)(null);return(0,Fe.useEffect)(()=>{if(t.current){t.current.innerHTML="";let n=(0,ov.getIcon)(e);n&&t.current.appendChild(n)}},[e]),K.createElement("span",{ref:t,className:"janitor-icon"})},es=({app:e,files:t,onChange:n,onOpen:r,title:i,showPreview:s=!0})=>{let[l,u]=(0,Fe.useState)(null),d=(0,Fe.useRef)({hoverPopover:null}).current,p=(0,Fe.useCallback)(x=>(0,Fe.useCallback)(()=>{n(x)},[n,x]),[n]),g=(0,Fe.useCallback)(x=>(0,Fe.useCallback)(()=>{r(x)},[n,x]),[n]),v=(0,Fe.useCallback)(x=>m=>{u({resourcePath:x,x:m.clientX,y:m.clientY})},[]),I=(0,Fe.useCallback)(()=>u(null),[]),E=(0,Fe.useCallback)(x=>m=>{e.workspace.trigger("hover-link",{event:m.nativeEvent,source:"preview",hoverParent:d,targetEl:m.target,linktext:x,sourcePath:"/"})},[e,d]),w=t.every(x=>x.selected),A=t.filter(x=>x.selected).length;return K.createElement("div",{className:"janitor-files-wrapper"},K.createElement("div",{className:"janitor-scan-section-title"},K.createElement("label",{title:`Click to ${w?"unselect":"select"} these ${t.length} items`},K.createElement("input",{type:"checkbox",checked:w,onChange:p(-1)}),i," (",t.length," items)",A>0&&K.createElement(K.Fragment,null,"\xA0 (",A," selected)"))),t.map((x,m)=>K.createElement("div",{key:m,className:"janitor-file"},K.createElement("label",null,K.createElement("input",{checked:x.selected,value:x.name,onChange:p(m),type:"checkbox"}),s&&!x.resourcePath&&x.name.endsWith(".md")?K.createElement("a",{href:"#",className:"internal-link janitor-md-preview-link",onMouseOver:E(x.name.replace(/\.md$/,"")),onClick:y=>y.preventDefault()},K.createElement(nv,{text:x.name})):K.createElement(nv,{text:x.name}),s&&x.resourcePath&&K.createElement("a",{href:"#",className:"previewFileIcon",title:"Preview",onMouseEnter:v(x.resourcePath),onMouseLeave:I},K.createElement(rv,{id:"eye"})),K.createElement("a",{href:"#",className:"openFileIcon",title:"Open",onClick:g(m)},K.createElement(rv,{id:"arrow-up-right"}))))),l&&(0,iv.createPortal)(K.createElement("div",{className:"janitor-preview-overlay",style:{left:`${Math.min(l.x+15,window.innerWidth-220)}px`,top:`${Math.max(10,l.y-150)}px`}},K.createElement("img",{src:l.resourcePath,alt:""})),document.body))};var av=require("obsidian"),ns=he(Ne()),lv=he(qo()),uv=he(require("path"));function ts(e,t,n){return e.map((r,i)=>t.contains(r.name)?ne(j({},r),{selected:n}):r)}var Sd=class extends av.Modal{constructor(n,r){super(n);this.plugin=r,this.state={onClose:()=>{this.close()},scanning:!0,orphans:[],empty:[],emptyFolders:[],big:[],expired:[],onSelectionChange:(i,s)=>{this.handleSelectionChange(i,s)},onPerform:i=>{this.perform(i)},onSettingChange:(i,s)=>{this.onSettingChange(i,s)},onOpen:(i,s)=>{this.handleOpen(i,s)},app:this.app}}perform(n){this.plugin.perform(n,this.extractFiles()),this.close()}onSettingChange(n,r){this.plugin.settings[n]=r,this.plugin.saveSettings(),this.state=j({},this.state),this.render()}handleOpen(n,r){return ae(this,null,function*(){let s=this.state[r][n],l=this.app.vault.adapter.getBasePath(),u=uv.default.join(l,s.name),d=yield this.app.openWithDefaultApp(s.name)})}handleSelectionChange(n,r){let i=this.state[r];if(n>=0){let s=i[n],l=!s.selected;this.applySelectionChangeToAllSections([s.name],l)}else{let s=i.every(u=>u.selected),l=i.map(u=>u.name);this.applySelectionChangeToAllSections(l,!s)}this.render()}applySelectionChangeToAllSections(n,r){this.state=ne(j({},this.state),{orphans:this.state.orphans&&ts(this.state.orphans,n,r),empty:this.state.empty&&ts(this.state.empty,n,r),emptyFolders:this.state.emptyFolders&&ts(this.state.emptyFolders,n,r),big:this.state.big&&ts(this.state.big,n,r),expired:this.state.expired&&ts(this.state.expired,n,r)})}updateState(n){this.state=ne(j({},this.state),{scanning:n.scanning,orphans:this.fileToSelectableItem(n.orphans),empty:this.fileToSelectableItem(n.empty),emptyFolders:this.folderToSelectableItem(n.emptyFolders),expired:this.fileToSelectableItem(n.expired),big:this.fileToSelectableItem(n.big)}),this.render()}fileToSelectableItem(n){return n&&n.map(r=>({name:r.path,selected:!1,resourcePath:Sd.IMAGE_EXTENSIONS.contains(r.extension.toLowerCase())?this.app.vault.getResourcePath(r):void 0}))}folderToSelectableItem(n){return n&&n.map(r=>({name:r.path,selected:!1}))}render(){this.root.render(ns.createElement(ns.StrictMode,null,ns.createElement(sv,j({},this.state))))}onOpen(){let{contentEl:n}=this;this.modalEl.addClass("janitor-main-modal"),this.root=(0,lv.createRoot)(n),this.render()}onClose(){this.root.unmount()}extractFiles(){return[this.state.orphans,this.state.empty,this.state.emptyFolders,this.state.big,this.state.expired].flatMap(n=>n?n.filter(r=>r.selected).map(r=>r.name):[])}},Yi=Sd;Yi.IMAGE_EXTENSIONS=["png","jpg","jpeg","gif","bmp","webp","avif","svg"];var wn=require("obsidian");var tl=require("obsidian");function cv(e,t){return e.reduce(([n,r],i)=>t(i)?[[...n,i],r]:[n,[...r,i]],[[],[]])}function dv(e,t){return ae(this,null,function*(){let n=yield Promise.all(e.map(t));return e.filter((r,i)=>n[i])})}function el(e){let t=e.vault.adapter.files,n=[];for(let r in t)t[r].type==="folder"&&n.push(t[r].realpath);return n}var wd=require("obsidian"),rs=class{constructor(t,n){this.whiteSpaceRegExp=new RegExp("\\S","");this.app=t,this.settings=n}isNote(t){return t.extension.toLowerCase()==="md"||t.extension.toLowerCase()==="canvas"}isCanvas(t){return t.extension.toLowerCase()==="canvas"}scan(){return ae(this,null,function*(){let t=this.app.vault.getFiles(),n=this.settings.excludedFilesFilters||[];this.settings.honorObsidianExcludedFiles&&this.app.vault.config.userIgnoreFilters&&(n=n.concat(this.app.vault.config.userIgnoreFilters));let r=n.map(x=>new RegExp(x,"i")),i=(this.settings.includedFilesFilters||[]).map(x=>new RegExp(x,"i")),s=x=>r.some(y=>y.exec(x))?i.some(y=>y.exec(x)):!0,l=t.filter(x=>s(x.path)),[u,d]=cv(l,this.isNote),p=this.getFrontMatters(u),g=this.settings.processOrphans&&(yield this.findOrphans(u,d,p)),v=this.settings.processEmpty&&(yield this.findEmpty(l)),I=this.settings.processEmptyFolders&&this.findEmptyFolders(s),E=this.settings.processExpired&&this.findExpired(p),w=this.settings.processBig&&this.findBigFiles(l);return{orphans:g,empty:v,emptyFolders:I,expired:E,big:w,scanning:!1}})}findEmptyFolders(t){return this.app.vault.getAllLoadedFiles().filter(n=>n instanceof tl.TFolder&&n.path!=="/"&&n.children.length===0).filter(n=>t(n.path))}findBigFiles(t){return t.filter(n=>n.stat.size>>10>this.settings.sizeLimitKb)}findExpired(t){let n=wd.moment.now();return t.filter(i=>{let s=i.frontMatter[this.settings.expiredAttribute];if(s){let l=(0,wd.moment)(s,this.settings.expiredDateFormat);if(l.isValid()&&l.isBefore(n))return!0}return!1}).map(i=>i.file)}findEmpty(t){return ae(this,null,function*(){return yield dv(t,r=>ae(this,null,function*(){if(r.stat.size===0)return!0;let i=yield this.app.vault.cachedRead(r);return this.whiteSpaceRegExp.test(i)?this.settings.emptyIgnoresFrontmatter?this.isOnlyFrontmatter(r,i):!1:!0}))})}isOnlyFrontmatter(t,n){var l;let r=this.app.metadataCache.getFileCache(t),i=(l=r==null?void 0:r.sections)==null?void 0:l.find(u=>u.type==="yaml");if(!i)return!1;let s=n.slice(i.position.end.offset);return!this.whiteSpaceRegExp.test(s)}findOrphans(t,n,r){return ae(this,null,function*(){this.settings.ignoreBaseFiles&&(n=n.filter(d=>d.extension.toLowerCase()!=="base"));let i=this.getResolvedLinks(),s=yield this.getCanvasResources(t.filter(this.isCanvas)),l=this.combineLinksAndResolvedMetadata(r,j(j({},i),s));return this.getOrphans(n,l)})}getCanvasResources(t){return ae(this,null,function*(){let n=yield Promise.all(t.map(s=>ae(this,null,function*(){let l=yield this.app.vault.cachedRead(s);return JSON.parse(l)}))),r=/\[\[(.*)\]\]/gm;return n.reduce((s,l)=>{var u;return((u=l.nodes)!=null?u:[]).forEach(d=>{let p,g=d;switch(d.type){case"file":s[d.file]=(s[d.file]||0)+1;break;case"link":break;case"text":for(p=null;(p=r.exec(g.text))!==null;){p.index===r.lastIndex&&r.lastIndex++;let v=p[1];if(v){s[v]=(s[v]||0)+1;let I=(0,tl.normalizePath)(`${app.vault.config.attachmentFolderPath}/${v}`);s[I]=(s[I]||0)+1}}break}}),s},{})})}getOrphans(t,n){return t.filter(r=>!n[r.path])}combineLinksAndResolvedMetadata(t,n){return t.reduce((r,i)=>{var s;return(s=i==null?void 0:i.resolvedProps)!=null&&s.length?j(j({},r),i.resolvedProps.reduce((l,u)=>ne(j({},l),{[u]:1}),{})):r},n)}getFrontMatters(t){return t.map(n=>{var i;let r=(i=app.metadataCache.getFileCache(n))==null?void 0:i.frontmatter;if(r){let s=nx(r);if(s!=null&&s.length){let l=s.map(u=>{let d=app.metadataCache.getFirstLinkpathDest(u,n.path);if(d)return d.path}).filter(u=>!!u);return{frontMatter:r,stringProps:s,resolvedProps:l,file:n}}}}).filter(n=>!!n)}getResolvedLinks(){return Object.keys(app.metadataCache.resolvedLinks).reduce((n,r)=>Object.assign(n,app.metadataCache.resolvedLinks[r]),{})}};function nx(e){return Object.values(e).filter(t=>typeof t=="string")}var Ue=he(Ne()),Xy=require("obsidian"),jy=he(qo());var xd=he(Ne()),rx=e=>xd.createElement("svg",j({viewBox:"0 0 100 100",className:"cross",width:16,height:16},e),xd.createElement("path",{fill:"currentColor",stroke:"currentColor",d:"M15.4,12.6l-2.9,2.9L47.1,50L12.6,84.6l2.9,2.9L50,52.9l34.6,34.6l2.9-2.9L52.9,50l34.6-34.6l-2.9-2.9L50,47.1L15.4,12.6z "})),nl=rx;var Rn=he(Ne());var ir=he(Ne()),rl=({name:e,description:t})=>ir.default.createElement(ix,null,ir.default.createElement(ox,null,e),ir.default.createElement(sx,null,t)),ix=({children:e})=>ir.default.createElement("div",{className:"setting-item-info"},e),ox=({children:e})=>ir.default.createElement("div",{className:"setting-item-name"},e),sx=({children:e})=>ir.default.createElement("div",{className:"setting-item-description"},e),il=({children:e})=>ir.default.createElement("div",{className:"setting-item-control"},e),ol=({children:e})=>ir.default.createElement("div",{className:"setting-item"},e);var hs=he(Ne());function Y(){return Y=Object.assign?Object.assign.bind():function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0)&&(n[i]=e[i]);return n}function un(e,t){if(e==null)return{};var n=yf(e,t),r,i;if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(i=0;i=0)&&(!Object.prototype.propertyIsEnumerable.call(e,r)||(n[r]=e[r]))}return n}function bf(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}var je=he(Ne()),k0=he(Ko());function On(e){var t;return((t=e.ownerDocument)==null?void 0:t.defaultView)||window}function g0(e){return On(e).getComputedStyle(e)}function v0(e){return b0(e)?(e.nodeName||"").toLowerCase():""}var Cl;function k2(){if(Cl)return Cl;let e=navigator.userAgentData;return e&&Array.isArray(e.brands)?(Cl=e.brands.map(t=>t.brand+"/"+t.version).join(" "),Cl):navigator.userAgent}function y0(e){return e instanceof On(e).HTMLElement}function ji(e){return e instanceof On(e).Element}function b0(e){return e instanceof On(e).Node}function h0(e){return typeof ShadowRoot=="undefined"?!1:e instanceof On(e).ShadowRoot||e instanceof ShadowRoot}function I0(e){let{overflow:t,overflowX:n,overflowY:r,display:i}=g0(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&!["inline","contents"].includes(i)}function F2(){return!/^((?!chrome|android).)*safari/i.test(k2())}function T2(e){return["html","body","#document"].includes(v0(e))}var wl=Math.round;function N2(e){let t=g0(e),n=parseFloat(t.width),r=parseFloat(t.height),i=e.offsetWidth,s=e.offsetHeight,l=wl(n)!==i||wl(r)!==s;return l&&(n=i,r=s),{width:n,height:r,fallback:l}}function C0(e){return ji(e)?e:e.contextElement}var S0={x:1,y:1};function If(e){let t=C0(e);if(!y0(t))return S0;let n=t.getBoundingClientRect(),{width:r,height:i,fallback:s}=N2(t),l=(s?wl(n.width):n.width)/r,u=(s?wl(n.height):n.height)/i;return l&&Number.isFinite(l)||(l=1),u&&Number.isFinite(u)||(u=1),{x:l,y:u}}function m0(e,t,n,r){var i,s;t===void 0&&(t=!1),n===void 0&&(n=!1);let l=e.getBoundingClientRect(),u=C0(e),d=S0;t&&(r?ji(r)&&(d=If(r)):d=If(e));let p=u?On(u):window,g=!F2()&&n,v=(l.left+(g&&((i=p.visualViewport)==null?void 0:i.offsetLeft)||0))/d.x,I=(l.top+(g&&((s=p.visualViewport)==null?void 0:s.offsetTop)||0))/d.y,E=l.width/d.x,w=l.height/d.y;if(u){let A=On(u),x=r&&ji(r)?On(r):r,m=A.frameElement;for(;m&&r&&x!==A;){let y=If(m),C=m.getBoundingClientRect(),k=getComputedStyle(m);C.x+=(m.clientLeft+parseFloat(k.paddingLeft))*y.x,C.y+=(m.clientTop+parseFloat(k.paddingTop))*y.y,v*=y.x,I*=y.y,E*=y.x,w*=y.y,v+=C.x,I+=C.y,m=On(m).frameElement}}return{width:E,height:w,top:I,right:v+E,bottom:I+w,left:v,x:v,y:I}}function M2(e){return((b0(e)?e.ownerDocument:e.document)||window.document).documentElement}function P2(e){if(v0(e)==="html")return e;let t=e.assignedSlot||e.parentNode||(h0(e)?e.host:null)||M2(e);return h0(t)?t.host:t}function w0(e){let t=P2(e);return T2(t)?e.ownerDocument.body:y0(t)&&I0(t)?t:w0(t)}function Sl(e,t){var n;t===void 0&&(t=[]);let r=w0(e),i=r===((n=e.ownerDocument)==null?void 0:n.body),s=On(r);return i?t.concat(s,s.visualViewport||[],I0(r)?r:[]):t.concat(r,Sl(r))}function x0(e,t,n,r){r===void 0&&(r={});let{ancestorScroll:i=!0,ancestorResize:s=!0,elementResize:l=!0,animationFrame:u=!1}=r,d=i&&!u,p=d||s?[...ji(e)?Sl(e):e.contextElement?Sl(e.contextElement):[],...Sl(t)]:[];p.forEach(E=>{d&&E.addEventListener("scroll",n,{passive:!0}),s&&E.addEventListener("resize",n)});let g,v=null;if(l){let E=!0;v=new ResizeObserver(()=>{E||n(),E=!1}),ji(e)&&!u&&v.observe(e),ji(e)||!e.contextElement||u||v.observe(e.contextElement),v.observe(t)}let I=u?m0(e):null;return u&&function E(){let w=m0(e);!I||w.x===I.x&&w.y===I.y&&w.width===I.width&&w.height===I.height||n(),I=w,g=requestAnimationFrame(E)}(),n(),()=>{var E;p.forEach(w=>{d&&w.removeEventListener("scroll",n),s&&w.removeEventListener("resize",n)}),(E=v)==null||E.disconnect(),v=null,u&&cancelAnimationFrame(g)}}var E0=he(Ne()),D2=E0.useLayoutEffect,xl=D2;var O2=["className","clearValue","cx","getStyles","getClassNames","getValue","hasValue","isMulti","isRtl","options","selectOption","selectProps","setValue","theme"],cs=function(){};function R2(e,t){return t?t[0]==="-"?e+t:e+"__"+t:e}function F0(e,t){for(var n=arguments.length,r=new Array(n>2?n-2:0),i=2;i-1}function _2(e){return ds(e)?window.innerHeight:e.clientHeight}function N0(e){return ds(e)?window.pageYOffset:e.scrollTop}function kl(e,t){if(ds(e)){window.scrollTo(0,t);return}e.scrollTop=t}function W2(e){var t=getComputedStyle(e),n=t.position==="absolute",r=/(auto|scroll)/;if(t.position==="fixed")return document.documentElement;for(var i=e;i=i.parentElement;)if(t=getComputedStyle(i),!(n&&t.position==="static")&&r.test(t.overflow+t.overflowY+t.overflowX))return i;return document.documentElement}function G2(e,t,n,r){return n*((e=e/r-1)*e*e+1)+t}function El(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:200,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:cs,i=N0(e),s=t-i,l=10,u=0;function d(){u+=l;var p=G2(u,i,s,n);kl(e,p),un.bottom?kl(e,Math.min(t.offsetTop+t.clientHeight-e.offsetHeight+i,e.scrollHeight)):r.top-i1?n-1:0),i=1;i=w)return{placement:"bottom",maxHeight:t};if(O>=w&&!l)return s&&El(d,B,ie),{placement:"bottom",maxHeight:t};if(!l&&O>=r||l&&D>=r){s&&El(d,B,ie);var pe=l?D-k:O-k;return{placement:"bottom",maxHeight:pe}}if(i==="auto"||l){var ue=t,te=l?N:P;return te>=r&&(ue=Math.min(te-k-u,t)),{placement:"top",maxHeight:ue}}if(i==="bottom")return s&&kl(d,B),{placement:"bottom",maxHeight:t};break;case"top":if(N>=w)return{placement:"top",maxHeight:t};if(P>=w&&!l)return s&&El(d,Z,ie),{placement:"top",maxHeight:t};if(!l&&P>=r||l&&N>=r){var Ve=t;return(!l&&P>=r||l&&N>=r)&&(Ve=l?N-M:P-M),s&&El(d,Z,ie),{placement:"top",maxHeight:Ve}}return{placement:"bottom",maxHeight:t};default:throw new Error('Invalid placement provided "'.concat(i,'".'))}return p}function Y2(e){var t={bottom:"top",top:"bottom"};return e?t[e]:"bottom"}var _0=function(t){return t==="auto"?"bottom":t},W0=function(t,n){var r,i=t.placement,s=t.theme,l=s.borderRadius,u=s.spacing,d=s.colors;return z((r={label:"menu"},Pr(r,Y2(i),"100%"),Pr(r,"position","absolute"),Pr(r,"width","100%"),Pr(r,"zIndex",1),r),n?{}:{backgroundColor:d.neutral0,borderRadius:l,boxShadow:"0 0 0 1px hsla(0, 0%, 0%, 0.1), 0 4px 11px hsla(0, 0%, 0%, 0.1)",marginBottom:u.menuGutter,marginTop:u.menuGutter})},G0=(0,je.createContext)(null),L0=function(t){var n=t.children,r=t.minMenuHeight,i=t.maxMenuHeight,s=t.menuPlacement,l=t.menuPosition,u=t.menuShouldScrollIntoView,d=t.theme,p=(0,je.useContext)(G0)||{},g=p.setPortalPlacement,v=(0,je.useRef)(null),I=(0,je.useState)(i),E=ln(I,2),w=E[0],A=E[1],x=(0,je.useState)(null),m=ln(x,2),y=m[0],C=m[1],k=d.spacing.controlHeight;return xl(function(){var M=v.current;if(!!M){var N=l==="fixed",D=u&&!N,P=H2({maxHeight:i,menuEl:M,minHeight:r,placement:s,shouldScroll:D,isFixedPosition:N,controlHeight:k});A(P.maxHeight),C(P.placement),g==null||g(P.placement)}},[i,s,l,u,r,g,k]),n({ref:v,placerProps:z(z({},t),{},{placement:y||_0(s),maxHeight:w})})},Z2=function(t){var n=t.children,r=t.innerRef,i=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"menu",{menu:!0}),{ref:r},i),n)},V0=function(t,n){var r=t.maxHeight,i=t.theme.spacing.baseUnit;return z({maxHeight:r,overflowY:"auto",position:"relative",WebkitOverflowScrolling:"touch"},n?{}:{paddingBottom:i,paddingTop:i})},z2=function(t){var n=t.children,r=t.innerProps,i=t.innerRef,s=t.isMulti;return(0,U.jsx)("div",Y({},_e(t,"menuList",{"menu-list":!0,"menu-list--is-multi":s}),{ref:i},r),n)},B0=function(t,n){var r=t.theme,i=r.spacing.baseUnit,s=r.colors;return z({textAlign:"center"},n?{}:{color:s.neutral40,padding:"".concat(i*2,"px ").concat(i*3,"px")})},H0=B0,Y0=B0,Z0=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"noOptionsMessage",{"menu-notice":!0,"menu-notice--no-options":!0}),r),n)};Z0.defaultProps={children:"No options"};var z0=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"loadingMessage",{"menu-notice":!0,"menu-notice--loading":!0}),r),n)};z0.defaultProps={children:"Loading..."};var X0=function(t){var n=t.rect,r=t.offset,i=t.position;return{left:n.left,position:i,top:r,width:n.width,zIndex:1}},X2=function(t){var n=t.appendTo,r=t.children,i=t.controlElement,s=t.innerProps,l=t.menuPlacement,u=t.menuPosition,d=(0,je.useRef)(null),p=(0,je.useRef)(null),g=(0,je.useState)(_0(l)),v=ln(g,2),I=v[0],E=v[1],w=(0,je.useMemo)(function(){return{setPortalPlacement:E}},[]),A=(0,je.useState)(null),x=ln(A,2),m=x[0],y=x[1],C=(0,je.useCallback)(function(){if(!!i){var D=L2(i),P=u==="fixed"?0:window.pageYOffset,O=D[I]+P;(O!==(m==null?void 0:m.offset)||D.left!==(m==null?void 0:m.rect.left)||D.width!==(m==null?void 0:m.rect.width))&&y({offset:O,rect:D})}},[i,u,I,m==null?void 0:m.offset,m==null?void 0:m.rect.left,m==null?void 0:m.rect.width]);xl(function(){C()},[C]);var k=(0,je.useCallback)(function(){typeof p.current=="function"&&(p.current(),p.current=null),i&&d.current&&(p.current=x0(i,d.current,C,{elementResize:"ResizeObserver"in window}))},[i,C]);xl(function(){k()},[k]);var M=(0,je.useCallback)(function(D){d.current=D,k()},[k]);if(!n&&u!=="fixed"||!m)return null;var N=(0,U.jsx)("div",Y({ref:M},_e(z(z({},t),{},{offset:m.offset,position:u,rect:m.rect}),"menuPortal",{"menu-portal":!0}),s),r);return(0,U.jsx)(G0.Provider,{value:w},n?(0,k0.createPortal)(N,n):N)},j0=function(t){var n=t.isDisabled,r=t.isRtl;return{label:"container",direction:r?"rtl":void 0,pointerEvents:n?"none":void 0,position:"relative"}},j2=function(t){var n=t.children,r=t.innerProps,i=t.isDisabled,s=t.isRtl;return(0,U.jsx)("div",Y({},_e(t,"container",{"--is-disabled":i,"--is-rtl":s}),r),n)},U0=function(t,n){var r=t.theme.spacing,i=t.isMulti,s=t.hasValue,l=t.selectProps.controlShouldRenderValue;return z({alignItems:"center",display:i&&s&&l?"flex":"grid",flex:1,flexWrap:"wrap",WebkitOverflowScrolling:"touch",position:"relative",overflow:"hidden"},n?{}:{padding:"".concat(r.baseUnit/2,"px ").concat(r.baseUnit*2,"px")})},U2=function(t){var n=t.children,r=t.innerProps,i=t.isMulti,s=t.hasValue;return(0,U.jsx)("div",Y({},_e(t,"valueContainer",{"value-container":!0,"value-container--is-multi":i,"value-container--has-value":s}),r),n)},J0=function(){return{alignItems:"center",alignSelf:"stretch",display:"flex",flexShrink:0}},J2=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"indicatorsContainer",{indicators:!0}),r),n)},A0,Q2=["size"];var $2={name:"8mmkcg",styles:"display:inline-block;fill:currentColor;line-height:1;stroke:currentColor;stroke-width:0"},Q0=function(t){var n=t.size,r=un(t,Q2);return(0,U.jsx)("svg",Y({height:n,width:n,viewBox:"0 0 20 20","aria-hidden":"true",focusable:"false",css:$2},r))},xf=function(t){return(0,U.jsx)(Q0,Y({size:20},t),(0,U.jsx)("path",{d:"M14.348 14.849c-0.469 0.469-1.229 0.469-1.697 0l-2.651-3.030-2.651 3.029c-0.469 0.469-1.229 0.469-1.697 0-0.469-0.469-0.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-0.469-0.469-0.469-1.228 0-1.697s1.228-0.469 1.697 0l2.652 3.031 2.651-3.031c0.469-0.469 1.228-0.469 1.697 0s0.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c0.469 0.469 0.469 1.229 0 1.698z"}))},$0=function(t){return(0,U.jsx)(Q0,Y({size:20},t),(0,U.jsx)("path",{d:"M4.516 7.548c0.436-0.446 1.043-0.481 1.576 0l3.908 3.747 3.908-3.747c0.533-0.481 1.141-0.446 1.574 0 0.436 0.445 0.408 1.197 0 1.615-0.406 0.418-4.695 4.502-4.695 4.502-0.217 0.223-0.502 0.335-0.787 0.335s-0.57-0.112-0.789-0.335c0 0-4.287-4.084-4.695-4.502s-0.436-1.17 0-1.615z"}))},K0=function(t,n){var r=t.isFocused,i=t.theme,s=i.spacing.baseUnit,l=i.colors;return z({label:"indicatorContainer",display:"flex",transition:"color 150ms"},n?{}:{color:r?l.neutral60:l.neutral20,padding:s*2,":hover":{color:r?l.neutral80:l.neutral40}})},q0=K0,K2=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"dropdownIndicator",{indicator:!0,"dropdown-indicator":!0}),r),n||(0,U.jsx)($0,null))},ey=K0,q2=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"clearIndicator",{indicator:!0,"clear-indicator":!0}),r),n||(0,U.jsx)(xf,null))},ty=function(t,n){var r=t.isDisabled,i=t.theme,s=i.spacing.baseUnit,l=i.colors;return z({label:"indicatorSeparator",alignSelf:"stretch",width:1},n?{}:{backgroundColor:r?l.neutral10:l.neutral20,marginBottom:s*2,marginTop:s*2})},eE=function(t){var n=t.innerProps;return(0,U.jsx)("span",Y({},n,_e(t,"indicatorSeparator",{"indicator-separator":!0})))},tE=(0,U.keyframes)(A0||(A0=bf([` + 0%, 80%, 100% { opacity: 0; } + 40% { opacity: 1; } +`]))),ny=function(t,n){var r=t.isFocused,i=t.size,s=t.theme,l=s.colors,u=s.spacing.baseUnit;return z({label:"loadingIndicator",display:"flex",transition:"color 150ms",alignSelf:"center",fontSize:i,lineHeight:1,marginRight:i,textAlign:"center",verticalAlign:"middle"},n?{}:{color:r?l.neutral60:l.neutral20,padding:u*2})},Cf=function(t){var n=t.delay,r=t.offset;return(0,U.jsx)("span",{css:(0,U.css)({animation:"".concat(tE," 1s ease-in-out ").concat(n,"ms infinite;"),backgroundColor:"currentColor",borderRadius:"1em",display:"inline-block",marginLeft:r?"1em":void 0,height:"1em",verticalAlign:"top",width:"1em"},"","")})},ry=function(t){var n=t.innerProps,r=t.isRtl;return(0,U.jsx)("div",Y({},_e(t,"loadingIndicator",{indicator:!0,"loading-indicator":!0}),n),(0,U.jsx)(Cf,{delay:0,offset:r}),(0,U.jsx)(Cf,{delay:160,offset:!0}),(0,U.jsx)(Cf,{delay:320,offset:!r}))};ry.defaultProps={size:4};var iy=function(t,n){var r=t.isDisabled,i=t.isFocused,s=t.theme,l=s.colors,u=s.borderRadius,d=s.spacing;return z({label:"control",alignItems:"center",cursor:"default",display:"flex",flexWrap:"wrap",justifyContent:"space-between",minHeight:d.controlHeight,outline:"0 !important",position:"relative",transition:"all 100ms"},n?{}:{backgroundColor:r?l.neutral5:l.neutral0,borderColor:r?l.neutral10:i?l.primary:l.neutral20,borderRadius:u,borderStyle:"solid",borderWidth:1,boxShadow:i?"0 0 0 1px ".concat(l.primary):void 0,"&:hover":{borderColor:i?l.primary:l.neutral30}})},nE=function(t){var n=t.children,r=t.isDisabled,i=t.isFocused,s=t.innerRef,l=t.innerProps,u=t.menuIsOpen;return(0,U.jsx)("div",Y({ref:s},_e(t,"control",{control:!0,"control--is-disabled":r,"control--is-focused":i,"control--menu-is-open":u}),l),n)},rE=["data"],oy=function(t,n){var r=t.theme.spacing;return n?{}:{paddingBottom:r.baseUnit*2,paddingTop:r.baseUnit*2}},iE=function(t){var n=t.children,r=t.cx,i=t.getStyles,s=t.getClassNames,l=t.Heading,u=t.headingProps,d=t.innerProps,p=t.label,g=t.theme,v=t.selectProps;return(0,U.jsx)("div",Y({},_e(t,"group",{group:!0}),d),(0,U.jsx)(l,Y({},u,{selectProps:v,theme:g,getStyles:i,getClassNames:s,cx:r}),p),(0,U.jsx)("div",null,n))},sy=function(t,n){var r=t.theme,i=r.colors,s=r.spacing;return z({label:"group",cursor:"default",display:"block"},n?{}:{color:i.neutral40,fontSize:"75%",fontWeight:500,marginBottom:"0.25em",paddingLeft:s.baseUnit*3,paddingRight:s.baseUnit*3,textTransform:"uppercase"})},oE=function(t){var n=T0(t);n.data;var r=un(n,rE);return(0,U.jsx)("div",Y({},_e(t,"groupHeading",{"group-heading":!0}),r))},sE=["innerRef","isDisabled","isHidden","inputClassName"],ay=function(t,n){var r=t.isDisabled,i=t.value,s=t.theme,l=s.spacing,u=s.colors;return z(z({visibility:r?"hidden":"visible",transform:i?"translateZ(0)":""},aE),n?{}:{margin:l.baseUnit/2,paddingBottom:l.baseUnit/2,paddingTop:l.baseUnit/2,color:u.neutral80})},ly={gridArea:"1 / 2",font:"inherit",minWidth:"2px",border:0,margin:0,outline:0,padding:0},aE={flex:"1 1 auto",display:"inline-grid",gridArea:"1 / 1 / 2 / 3",gridTemplateColumns:"0 min-content","&:after":z({content:'attr(data-value) " "',visibility:"hidden",whiteSpace:"pre"},ly)},lE=function(t){return z({label:"input",color:"inherit",background:0,opacity:t?0:1,width:"100%"},ly)},uE=function(t){var n=t.cx,r=t.value,i=T0(t),s=i.innerRef,l=i.isDisabled,u=i.isHidden,d=i.inputClassName,p=un(i,sE);return(0,U.jsx)("div",Y({},_e(t,"input",{"input-container":!0}),{"data-value":r||""}),(0,U.jsx)("input",Y({className:n({input:!0},d),ref:s,style:lE(u),disabled:l},p)))},uy=function(t,n){var r=t.theme,i=r.spacing,s=r.borderRadius,l=r.colors;return z({label:"multiValue",display:"flex",minWidth:0},n?{}:{backgroundColor:l.neutral10,borderRadius:s/2,margin:i.baseUnit/2})},cy=function(t,n){var r=t.theme,i=r.borderRadius,s=r.colors,l=t.cropWithEllipsis;return z({overflow:"hidden",textOverflow:l||l===void 0?"ellipsis":void 0,whiteSpace:"nowrap"},n?{}:{borderRadius:i/2,color:s.neutral80,fontSize:"85%",padding:3,paddingLeft:6})},dy=function(t,n){var r=t.theme,i=r.spacing,s=r.borderRadius,l=r.colors,u=t.isFocused;return z({alignItems:"center",display:"flex"},n?{}:{borderRadius:s/2,backgroundColor:u?l.dangerLight:void 0,paddingLeft:i.baseUnit,paddingRight:i.baseUnit,":hover":{backgroundColor:l.dangerLight,color:l.danger}})},fy=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",r,n)},cE=fy,dE=fy;function fE(e){var t=e.children,n=e.innerProps;return(0,U.jsx)("div",Y({role:"button"},n),t||(0,U.jsx)(xf,{size:14}))}var pE=function(t){var n=t.children,r=t.components,i=t.data,s=t.innerProps,l=t.isDisabled,u=t.removeProps,d=t.selectProps,p=r.Container,g=r.Label,v=r.Remove;return(0,U.jsx)(p,{data:i,innerProps:z(z({},_e(t,"multiValue",{"multi-value":!0,"multi-value--is-disabled":l})),s),selectProps:d},(0,U.jsx)(g,{data:i,innerProps:z({},_e(t,"multiValueLabel",{"multi-value__label":!0})),selectProps:d},n),(0,U.jsx)(v,{data:i,innerProps:z(z({},_e(t,"multiValueRemove",{"multi-value__remove":!0})),{},{"aria-label":"Remove ".concat(n||"option")},u),selectProps:d}))},py=function(t,n){var r=t.isDisabled,i=t.isFocused,s=t.isSelected,l=t.theme,u=l.spacing,d=l.colors;return z({label:"option",cursor:"default",display:"block",fontSize:"inherit",width:"100%",userSelect:"none",WebkitTapHighlightColor:"rgba(0, 0, 0, 0)"},n?{}:{backgroundColor:s?d.primary:i?d.primary25:"transparent",color:r?d.neutral20:s?d.neutral0:"inherit",padding:"".concat(u.baseUnit*2,"px ").concat(u.baseUnit*3,"px"),":active":{backgroundColor:r?void 0:s?d.primary:d.primary50}})},hE=function(t){var n=t.children,r=t.isDisabled,i=t.isFocused,s=t.isSelected,l=t.innerRef,u=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"option",{option:!0,"option--is-disabled":r,"option--is-focused":i,"option--is-selected":s}),{ref:l,"aria-disabled":r},u),n)},hy=function(t,n){var r=t.theme,i=r.spacing,s=r.colors;return z({label:"placeholder",gridArea:"1 / 1 / 2 / 3"},n?{}:{color:s.neutral50,marginLeft:i.baseUnit/2,marginRight:i.baseUnit/2})},mE=function(t){var n=t.children,r=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"placeholder",{placeholder:!0}),r),n)},my=function(t,n){var r=t.isDisabled,i=t.theme,s=i.spacing,l=i.colors;return z({label:"singleValue",gridArea:"1 / 1 / 2 / 3",maxWidth:"100%",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},n?{}:{color:r?l.neutral40:l.neutral80,marginLeft:s.baseUnit/2,marginRight:s.baseUnit/2})},gE=function(t){var n=t.children,r=t.isDisabled,i=t.innerProps;return(0,U.jsx)("div",Y({},_e(t,"singleValue",{"single-value":!0,"single-value--is-disabled":r}),i),n)},vE={ClearIndicator:q2,Control:nE,DropdownIndicator:K2,DownChevron:$0,CrossIcon:xf,Group:iE,GroupHeading:oE,IndicatorsContainer:J2,IndicatorSeparator:eE,Input:uE,LoadingIndicator:ry,Menu:Z2,MenuList:z2,MenuPortal:X2,LoadingMessage:z0,NoOptionsMessage:Z0,MultiValue:pE,MultiValueContainer:cE,MultiValueLabel:dE,MultiValueRemove:fE,Option:hE,Placeholder:mE,SelectContainer:j2,SingleValue:gE,ValueContainer:U2},gy=function(t){return z(z({},vE),t.components)};var Lt=he(hf());var vy=Number.isNaN||function(t){return typeof t=="number"&&t!==t};function yE(e,t){return!!(e===t||vy(e)&&vy(t))}function bE(e,t){if(e.length!==t.length)return!1;for(var n=0;n1?"s":""," ").concat(s.join(","),", selected.");case"select-option":return l?"option ".concat(i," is disabled. Select another option."):"option ".concat(i,", selected.");default:return""}},onFocus:function(t){var n=t.context,r=t.focused,i=t.options,s=t.label,l=s===void 0?"":s,u=t.selectValue,d=t.isDisabled,p=t.isSelected,g=function(w,A){return w&&w.length?"".concat(w.indexOf(A)+1," of ").concat(w.length):""};if(n==="value"&&u)return"value ".concat(l," focused, ").concat(g(u,r),".");if(n==="menu"){var v=d?" disabled":"",I="".concat(p?"selected":"focused").concat(v);return"option ".concat(l," ").concat(I,", ").concat(g(i,r),".")}return""},onFilter:function(t){var n=t.inputValue,r=t.resultsMessage;return"".concat(r).concat(n?" for search term "+n:"",".")}},SE=function(t){var n=t.ariaSelection,r=t.focusedOption,i=t.focusedValue,s=t.focusableOptions,l=t.isFocused,u=t.selectValue,d=t.selectProps,p=t.id,g=d.ariaLiveMessages,v=d.getOptionLabel,I=d.inputValue,E=d.isMulti,w=d.isOptionDisabled,A=d.isSearchable,x=d.menuIsOpen,m=d.options,y=d.screenReaderStatus,C=d.tabSelectsValue,k=d["aria-label"],M=d["aria-live"],N=(0,fe.useMemo)(function(){return z(z({},CE),g||{})},[g]),D=(0,fe.useMemo)(function(){var ue="";if(n&&N.onChange){var te=n.option,Ve=n.options,Qe=n.removedValue,ye=n.removedValues,wt=n.value,lt=function(rt){return Array.isArray(rt)?null:rt},we=Qe||te||lt(wt),ce=we?v(we):"",G=Ve||ye||void 0,ut=G?G.map(v):[],ct=z({isDisabled:we&&w(we,u),label:ce,labels:ut},n);ue=N.onChange(ct)}return ue},[n,N,w,u,v]),P=(0,fe.useMemo)(function(){var ue="",te=r||i,Ve=!!(r&&u&&u.includes(r));if(te&&N.onFocus){var Qe={focused:te,label:v(te),isDisabled:w(te,u),isSelected:Ve,options:s,context:te===r?"menu":"value",selectValue:u};ue=N.onFocus(Qe)}return ue},[r,i,v,w,N,s,u]),O=(0,fe.useMemo)(function(){var ue="";if(x&&m.length&&N.onFilter){var te=y({count:s.length});ue=N.onFilter({inputValue:I,resultsMessage:te})}return ue},[s,I,x,N,m,y]),B=(0,fe.useMemo)(function(){var ue="";if(N.guidance){var te=i?"value":x?"menu":"input";ue=N.guidance({"aria-label":k,context:te,isDisabled:r&&w(r,u),isMulti:E,isSearchable:A,tabSelectsValue:C})}return ue},[k,r,i,E,w,A,x,N,u,C]),Z="".concat(P," ").concat(O," ").concat(B),ie=(0,Lt.jsx)(fe.Fragment,null,(0,Lt.jsx)("span",{id:"aria-selection"},D),(0,Lt.jsx)("span",{id:"aria-context"},Z)),pe=(n==null?void 0:n.action)==="initial-input-focus";return(0,Lt.jsx)(fe.Fragment,null,(0,Lt.jsx)(by,{id:p},pe&&ie),(0,Lt.jsx)(by,{"aria-live":M,"aria-atomic":"false","aria-relevant":"additions text"},l&&!pe&&ie))},Af=[{base:"A",letters:"A\u24B6\uFF21\xC0\xC1\xC2\u1EA6\u1EA4\u1EAA\u1EA8\xC3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\xC4\u01DE\u1EA2\xC5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"},{base:"AA",letters:"\uA732"},{base:"AE",letters:"\xC6\u01FC\u01E2"},{base:"AO",letters:"\uA734"},{base:"AU",letters:"\uA736"},{base:"AV",letters:"\uA738\uA73A"},{base:"AY",letters:"\uA73C"},{base:"B",letters:"B\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181"},{base:"C",letters:"C\u24B8\uFF23\u0106\u0108\u010A\u010C\xC7\u1E08\u0187\u023B\uA73E"},{base:"D",letters:"D\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779"},{base:"DZ",letters:"\u01F1\u01C4"},{base:"Dz",letters:"\u01F2\u01C5"},{base:"E",letters:"E\u24BA\uFF25\xC8\xC9\xCA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\xCB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E"},{base:"F",letters:"F\u24BB\uFF26\u1E1E\u0191\uA77B"},{base:"G",letters:"G\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E"},{base:"H",letters:"H\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"},{base:"I",letters:"I\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"},{base:"J",letters:"J\u24BF\uFF2A\u0134\u0248"},{base:"K",letters:"K\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"},{base:"L",letters:"L\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"},{base:"LJ",letters:"\u01C7"},{base:"Lj",letters:"\u01C8"},{base:"M",letters:"M\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C"},{base:"N",letters:"N\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4"},{base:"NJ",letters:"\u01CA"},{base:"Nj",letters:"\u01CB"},{base:"O",letters:"O\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C"},{base:"OI",letters:"\u01A2"},{base:"OO",letters:"\uA74E"},{base:"OU",letters:"\u0222"},{base:"P",letters:"P\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"},{base:"Q",letters:"Q\u24C6\uFF31\uA756\uA758\u024A"},{base:"R",letters:"R\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"},{base:"S",letters:"S\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"},{base:"T",letters:"T\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"},{base:"TZ",letters:"\uA728"},{base:"U",letters:"U\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"},{base:"V",letters:"V\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"},{base:"VY",letters:"\uA760"},{base:"W",letters:"W\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"},{base:"X",letters:"X\u24CD\uFF38\u1E8A\u1E8C"},{base:"Y",letters:"Y\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"},{base:"Z",letters:"Z\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"},{base:"a",letters:"a\u24D0\uFF41\u1E9A\xE0\xE1\xE2\u1EA7\u1EA5\u1EAB\u1EA9\xE3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\xE4\u01DF\u1EA3\xE5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250"},{base:"aa",letters:"\uA733"},{base:"ae",letters:"\xE6\u01FD\u01E3"},{base:"ao",letters:"\uA735"},{base:"au",letters:"\uA737"},{base:"av",letters:"\uA739\uA73B"},{base:"ay",letters:"\uA73D"},{base:"b",letters:"b\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253"},{base:"c",letters:"c\u24D2\uFF43\u0107\u0109\u010B\u010D\xE7\u1E09\u0188\u023C\uA73F\u2184"},{base:"d",letters:"d\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A"},{base:"dz",letters:"\u01F3\u01C6"},{base:"e",letters:"e\u24D4\uFF45\xE8\xE9\xEA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\xEB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD"},{base:"f",letters:"f\u24D5\uFF46\u1E1F\u0192\uA77C"},{base:"g",letters:"g\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F"},{base:"h",letters:"h\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"},{base:"hv",letters:"\u0195"},{base:"i",letters:"i\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"},{base:"j",letters:"j\u24D9\uFF4A\u0135\u01F0\u0249"},{base:"k",letters:"k\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"},{base:"l",letters:"l\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747"},{base:"lj",letters:"\u01C9"},{base:"m",letters:"m\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"},{base:"n",letters:"n\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5"},{base:"nj",letters:"\u01CC"},{base:"o",letters:"o\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\u0254\uA74B\uA74D\u0275"},{base:"oi",letters:"\u01A3"},{base:"ou",letters:"\u0223"},{base:"oo",letters:"\uA74F"},{base:"p",letters:"p\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755"},{base:"q",letters:"q\u24E0\uFF51\u024B\uA757\uA759"},{base:"r",letters:"r\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"},{base:"s",letters:"s\u24E2\uFF53\xDF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B"},{base:"t",letters:"t\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"},{base:"tz",letters:"\uA729"},{base:"u",letters:"u\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"},{base:"v",letters:"v\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"},{base:"vy",letters:"\uA761"},{base:"w",letters:"w\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"},{base:"x",letters:"x\u24E7\uFF58\u1E8B\u1E8D"},{base:"y",letters:"y\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"},{base:"z",letters:"z\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"}],wE=new RegExp("["+Af.map(function(e){return e.letters}).join("")+"]","g"),Ny={};for(Fl=0;Fl-1}},kE=["innerRef"];function FE(e){var t=e.innerRef,n=un(e,kE),r=R0(n,"onExited","in","enter","exit","appear");return(0,Lt.jsx)("input",Y({ref:t},r,{css:(0,Lt.css)({label:"dummyInput",background:0,border:0,caretColor:"transparent",fontSize:"inherit",gridArea:"1 / 1 / 2 / 3",outline:0,padding:0,width:1,color:"transparent",left:-100,opacity:0,position:"relative",transform:"scale(.01)"},"","")}))}var TE=function(t){t.preventDefault(),t.stopPropagation()};function NE(e){var t=e.isEnabled,n=e.onBottomArrive,r=e.onBottomLeave,i=e.onTopArrive,s=e.onTopLeave,l=(0,fe.useRef)(!1),u=(0,fe.useRef)(!1),d=(0,fe.useRef)(0),p=(0,fe.useRef)(null),g=(0,fe.useCallback)(function(x,m){if(p.current!==null){var y=p.current,C=y.scrollTop,k=y.scrollHeight,M=y.clientHeight,N=p.current,D=m>0,P=k-M-C,O=!1;P>m&&l.current&&(r&&r(x),l.current=!1),D&&u.current&&(s&&s(x),u.current=!1),D&&m>P?(n&&!l.current&&n(x),N.scrollTop=k,O=!0,l.current=!0):!D&&-m>C&&(i&&!u.current&&i(x),N.scrollTop=0,O=!0,u.current=!0),O&&TE(x)}},[n,r,i,s]),v=(0,fe.useCallback)(function(x){g(x,x.deltaY)},[g]),I=(0,fe.useCallback)(function(x){d.current=x.changedTouches[0].clientY},[]),E=(0,fe.useCallback)(function(x){var m=d.current-x.changedTouches[0].clientY;g(x,m)},[g]),w=(0,fe.useCallback)(function(x){if(!!x){var m=D0?{passive:!1}:!1;x.addEventListener("wheel",v,m),x.addEventListener("touchstart",I,m),x.addEventListener("touchmove",E,m)}},[E,I,v]),A=(0,fe.useCallback)(function(x){!x||(x.removeEventListener("wheel",v,!1),x.removeEventListener("touchstart",I,!1),x.removeEventListener("touchmove",E,!1))},[E,I,v]);return(0,fe.useEffect)(function(){if(!!t){var x=p.current;return w(x),function(){A(x)}}},[t,w,A]),function(x){p.current=x}}var Cy=["boxSizing","height","overflow","paddingRight","position"],Sy={boxSizing:"border-box",overflow:"hidden",position:"relative",height:"100%"};function wy(e){e.preventDefault()}function xy(e){e.stopPropagation()}function Ey(){var e=this.scrollTop,t=this.scrollHeight,n=e+this.offsetHeight;e===0?this.scrollTop=1:n===t&&(this.scrollTop=e-1)}function Ay(){return"ontouchstart"in window||navigator.maxTouchPoints}var ky=!!(typeof window!="undefined"&&window.document&&window.document.createElement),fs=0,Ji={capture:!1,passive:!1};function ME(e){var t=e.isEnabled,n=e.accountForScrollbars,r=n===void 0?!0:n,i=(0,fe.useRef)({}),s=(0,fe.useRef)(null),l=(0,fe.useCallback)(function(d){if(!!ky){var p=document.body,g=p&&p.style;if(r&&Cy.forEach(function(w){var A=g&&g[w];i.current[w]=A}),r&&fs<1){var v=parseInt(i.current.paddingRight,10)||0,I=document.body?document.body.clientWidth:0,E=window.innerWidth-I+v||0;Object.keys(Sy).forEach(function(w){var A=Sy[w];g&&(g[w]=A)}),g&&(g.paddingRight="".concat(E,"px"))}p&&Ay()&&(p.addEventListener("touchmove",wy,Ji),d&&(d.addEventListener("touchstart",Ey,Ji),d.addEventListener("touchmove",xy,Ji))),fs+=1}},[r]),u=(0,fe.useCallback)(function(d){if(!!ky){var p=document.body,g=p&&p.style;fs=Math.max(fs-1,0),r&&fs<1&&Cy.forEach(function(v){var I=i.current[v];g&&(g[v]=I)}),p&&Ay()&&(p.removeEventListener("touchmove",wy,Ji),d&&(d.removeEventListener("touchstart",Ey,Ji),d.removeEventListener("touchmove",xy,Ji)))}},[r]);return(0,fe.useEffect)(function(){if(!!t){var d=s.current;return l(d),function(){u(d)}}},[t,l,u]),function(d){s.current=d}}var PE=function(){return document.activeElement&&document.activeElement.blur()},DE={name:"1kfdb0e",styles:"position:fixed;left:0;bottom:0;right:0;top:0"};function OE(e){var t=e.children,n=e.lockEnabled,r=e.captureEnabled,i=r===void 0?!0:r,s=e.onBottomArrive,l=e.onBottomLeave,u=e.onTopArrive,d=e.onTopLeave,p=NE({isEnabled:i,onBottomArrive:s,onBottomLeave:l,onTopArrive:u,onTopLeave:d}),g=ME({isEnabled:n}),v=function(E){p(E),g(E)};return(0,Lt.jsx)(fe.Fragment,null,n&&(0,Lt.jsx)("div",{onClick:PE,css:DE}),t(v))}var RE={name:"1a0ro4n-requiredInput",styles:"label:requiredInput;opacity:0;pointer-events:none;position:absolute;bottom:0;left:0;right:0;width:100%"},_E=function(t){var n=t.name,r=t.onFocus;return(0,Lt.jsx)("input",{required:!0,name:n,tabIndex:-1,onFocus:r,css:RE,value:"",onChange:function(){}})},WE=function(t){return t.label},kf=function(t){return t.label},Ff=function(t){return t.value},GE=function(t){return!!t.isDisabled},LE={clearIndicator:ey,container:j0,control:iy,dropdownIndicator:q0,group:oy,groupHeading:sy,indicatorsContainer:J0,indicatorSeparator:ty,input:ay,loadingIndicator:ny,loadingMessage:Y0,menu:W0,menuList:V0,menuPortal:X0,multiValue:uy,multiValueLabel:cy,multiValueRemove:dy,noOptionsMessage:H0,option:py,placeholder:hy,singleValue:my,valueContainer:U0};var VE={primary:"#2684FF",primary75:"#4C9AFF",primary50:"#B2D4FF",primary25:"#DEEBFF",danger:"#DE350B",dangerLight:"#FFBDAD",neutral0:"hsl(0, 0%, 100%)",neutral5:"hsl(0, 0%, 95%)",neutral10:"hsl(0, 0%, 90%)",neutral20:"hsl(0, 0%, 80%)",neutral30:"hsl(0, 0%, 70%)",neutral40:"hsl(0, 0%, 60%)",neutral50:"hsl(0, 0%, 50%)",neutral60:"hsl(0, 0%, 40%)",neutral70:"hsl(0, 0%, 30%)",neutral80:"hsl(0, 0%, 20%)",neutral90:"hsl(0, 0%, 10%)"},BE=4,Py=4,HE=38,YE=Py*2,ZE={baseUnit:Py,controlHeight:HE,menuGutter:YE},Ef={borderRadius:BE,colors:VE,spacing:ZE},zE={"aria-live":"polite",backspaceRemovesValue:!0,blurInputOnSelect:wf(),captureMenuScroll:!wf(),classNames:{},closeMenuOnSelect:!0,closeMenuOnScroll:!1,components:{},controlShouldRenderValue:!0,escapeClearsValue:!1,filterOption:AE(),formatGroupLabel:WE,getOptionLabel:kf,getOptionValue:Ff,isDisabled:!1,isLoading:!1,isMulti:!1,isRtl:!1,isSearchable:!0,isOptionDisabled:GE,loadingMessage:function(){return"Loading..."},maxMenuHeight:300,minMenuHeight:140,menuIsOpen:!1,menuPlacement:"bottom",menuPosition:"absolute",menuShouldBlockScroll:!1,menuShouldScrollIntoView:!M0(),noOptionsMessage:function(){return"No options"},openMenuOnFocus:!1,openMenuOnClick:!0,options:[],pageSize:5,placeholder:"Select...",screenReaderStatus:function(t){var n=t.count;return"".concat(n," result").concat(n!==1?"s":""," available")},styles:{},tabIndex:0,tabSelectsValue:!0,unstyled:!1};function Fy(e,t,n,r){var i=_y(e,t,n),s=Wy(e,t,n),l=Ry(e,t),u=Ml(e,t);return{type:"option",data:t,isDisabled:i,isSelected:s,label:l,value:u,index:r}}function Dy(e,t){return e.options.map(function(n,r){if("options"in n){var i=n.options.map(function(l,u){return Fy(e,l,t,u)}).filter(function(l){return Ty(e,l)});return i.length>0?{type:"group",data:n,options:i,index:r}:void 0}var s=Fy(e,n,t,r);return Ty(e,s)?s:void 0}).filter(O0)}function Oy(e){return e.reduce(function(t,n){return n.type==="group"?t.push.apply(t,Dr(n.options.map(function(r){return r.data}))):t.push(n.data),t},[])}function XE(e,t){return Oy(Dy(e,t))}function Ty(e,t){var n=e.inputValue,r=n===void 0?"":n,i=t.data,s=t.isSelected,l=t.label,u=t.value;return(!Ly(e)||!s)&&Gy(e,{label:l,value:u,data:i},r)}function jE(e,t){var n=e.focusedValue,r=e.selectValue,i=r.indexOf(n);if(i>-1){var s=t.indexOf(n);if(s>-1)return n;if(i-1?n:t[0]}var Ry=function(t,n){return t.getOptionLabel(n)},Ml=function(t,n){return t.getOptionValue(n)};function _y(e,t,n){return typeof e.isOptionDisabled=="function"?e.isOptionDisabled(t,n):!1}function Wy(e,t,n){if(n.indexOf(t)>-1)return!0;if(typeof e.isOptionSelected=="function")return e.isOptionSelected(t,n);var r=Ml(e,t);return n.some(function(i){return Ml(e,i)===r})}function Gy(e,t,n){return e.filterOption?e.filterOption(t,n):!0}var Ly=function(t){var n=t.hideSelectedOptions,r=t.isMulti;return n===void 0?r:n},JE=1,Tf=function(e){Fd(n,e);var t=Pd(n);function n(r){var i;if(Ad(this,n),i=t.call(this,r),i.state={ariaSelection:null,focusedOption:null,focusedValue:null,inputIsHidden:!1,isFocused:!1,selectValue:[],clearFocusValueOnUpdate:!1,prevWasFocused:!1,inputIsHiddenAfterUpdate:void 0,prevProps:void 0},i.blockOptionHover=!1,i.isComposing=!1,i.commonProps=void 0,i.initialTouchX=0,i.initialTouchY=0,i.instancePrefix="",i.openAfterFocus=!1,i.scrollToFocusedOptionOnUpdate=!1,i.userIsDragging=void 0,i.controlRef=null,i.getControlRef=function(u){i.controlRef=u},i.focusedOptionRef=null,i.getFocusedOptionRef=function(u){i.focusedOptionRef=u},i.menuListRef=null,i.getMenuListRef=function(u){i.menuListRef=u},i.inputRef=null,i.getInputRef=function(u){i.inputRef=u},i.focus=i.focusInput,i.blur=i.blurInput,i.onChange=function(u,d){var p=i.props,g=p.onChange,v=p.name;d.name=v,i.ariaOnChange(u,d),g(u,d)},i.setValue=function(u,d,p){var g=i.props,v=g.closeMenuOnSelect,I=g.isMulti,E=g.inputValue;i.onInputChange("",{action:"set-value",prevInputValue:E}),v&&(i.setState({inputIsHiddenAfterUpdate:!I}),i.onMenuClose()),i.setState({clearFocusValueOnUpdate:!0}),i.onChange(u,{action:d,option:p})},i.selectOption=function(u){var d=i.props,p=d.blurInputOnSelect,g=d.isMulti,v=d.name,I=i.state.selectValue,E=g&&i.isOptionSelected(u,I),w=i.isOptionDisabled(u,I);if(E){var A=i.getOptionValue(u);i.setValue(I.filter(function(x){return i.getOptionValue(x)!==A}),"deselect-option",u)}else if(!w)g?i.setValue([].concat(Dr(I),[u]),"select-option",u):i.setValue(u,"select-option");else{i.ariaOnChange(u,{action:"select-option",option:u,name:v});return}p&&i.blurInput()},i.removeValue=function(u){var d=i.props.isMulti,p=i.state.selectValue,g=i.getOptionValue(u),v=p.filter(function(E){return i.getOptionValue(E)!==g}),I=ii(d,v,v[0]||null);i.onChange(I,{action:"remove-value",removedValue:u}),i.focusInput()},i.clearValue=function(){var u=i.state.selectValue;i.onChange(ii(i.props.isMulti,[],null),{action:"clear",removedValues:u})},i.popValue=function(){var u=i.props.isMulti,d=i.state.selectValue,p=d[d.length-1],g=d.slice(0,d.length-1),v=ii(u,g,g[0]||null);i.onChange(v,{action:"pop-value",removedValue:p})},i.getValue=function(){return i.state.selectValue},i.cx=function(){for(var u=arguments.length,d=new Array(u),p=0;pI||v>I}},i.onTouchEnd=function(u){i.userIsDragging||(i.controlRef&&!i.controlRef.contains(u.target)&&i.menuListRef&&!i.menuListRef.contains(u.target)&&i.blurInput(),i.initialTouchX=0,i.initialTouchY=0)},i.onControlTouchEnd=function(u){i.userIsDragging||i.onControlMouseDown(u)},i.onClearIndicatorTouchEnd=function(u){i.userIsDragging||i.onClearIndicatorMouseDown(u)},i.onDropdownIndicatorTouchEnd=function(u){i.userIsDragging||i.onDropdownIndicatorMouseDown(u)},i.handleInputChange=function(u){var d=i.props.inputValue,p=u.currentTarget.value;i.setState({inputIsHiddenAfterUpdate:!1}),i.onInputChange(p,{action:"input-change",prevInputValue:d}),i.props.menuIsOpen||i.onMenuOpen()},i.onInputFocus=function(u){i.props.onFocus&&i.props.onFocus(u),i.setState({inputIsHiddenAfterUpdate:!1,isFocused:!0}),(i.openAfterFocus||i.props.openMenuOnFocus)&&i.openMenu("first"),i.openAfterFocus=!1},i.onInputBlur=function(u){var d=i.props.inputValue;if(i.menuListRef&&i.menuListRef.contains(document.activeElement)){i.inputRef.focus();return}i.props.onBlur&&i.props.onBlur(u),i.onInputChange("",{action:"input-blur",prevInputValue:d}),i.onMenuClose(),i.setState({focusedValue:null,isFocused:!1})},i.onOptionHover=function(u){i.blockOptionHover||i.state.focusedOption===u||i.setState({focusedOption:u})},i.shouldHideSelectedOptions=function(){return Ly(i.props)},i.onValueInputFocus=function(u){u.preventDefault(),u.stopPropagation(),i.focus()},i.onKeyDown=function(u){var d=i.props,p=d.isMulti,g=d.backspaceRemovesValue,v=d.escapeClearsValue,I=d.inputValue,E=d.isClearable,w=d.isDisabled,A=d.menuIsOpen,x=d.onKeyDown,m=d.tabSelectsValue,y=d.openMenuOnFocus,C=i.state,k=C.focusedOption,M=C.focusedValue,N=C.selectValue;if(!w&&!(typeof x=="function"&&(x(u),u.defaultPrevented))){switch(i.blockOptionHover=!0,u.key){case"ArrowLeft":if(!p||I)return;i.focusValue("previous");break;case"ArrowRight":if(!p||I)return;i.focusValue("next");break;case"Delete":case"Backspace":if(I)return;if(M)i.removeValue(M);else{if(!g)return;p?i.popValue():E&&i.clearValue()}break;case"Tab":if(i.isComposing||u.shiftKey||!A||!m||!k||y&&i.isOptionSelected(k,N))return;i.selectOption(k);break;case"Enter":if(u.keyCode===229)break;if(A){if(!k||i.isComposing)return;i.selectOption(k);break}return;case"Escape":A?(i.setState({inputIsHiddenAfterUpdate:!1}),i.onInputChange("",{action:"menu-close",prevInputValue:I}),i.onMenuClose()):E&&v&&i.clearValue();break;case" ":if(I)return;if(!A){i.openMenu("first");break}if(!k)return;i.selectOption(k);break;case"ArrowUp":A?i.focusOption("up"):i.openMenu("last");break;case"ArrowDown":A?i.focusOption("down"):i.openMenu("first");break;case"PageUp":if(!A)return;i.focusOption("pageup");break;case"PageDown":if(!A)return;i.focusOption("pagedown");break;case"Home":if(!A)return;i.focusOption("first");break;case"End":if(!A)return;i.focusOption("last");break;default:return}u.preventDefault()}},i.instancePrefix="react-select-"+(i.props.instanceId||++JE),i.state.selectValue=Ui(r.value),r.menuIsOpen&&i.state.selectValue.length){var s=i.buildFocusableOptions(),l=s.indexOf(i.state.selectValue[0]);i.state.focusedOption=s[l]}return i}return kd(n,[{key:"componentDidMount",value:function(){this.startListeningComposition(),this.startListeningToTouch(),this.props.closeMenuOnScroll&&document&&document.addEventListener&&document.addEventListener("scroll",this.onScroll,!0),this.props.autoFocus&&this.focusInput(),this.props.menuIsOpen&&this.state.focusedOption&&this.menuListRef&&this.focusedOptionRef&&Sf(this.menuListRef,this.focusedOptionRef)}},{key:"componentDidUpdate",value:function(i){var s=this.props,l=s.isDisabled,u=s.menuIsOpen,d=this.state.isFocused;(d&&!l&&i.isDisabled||d&&u&&!i.menuIsOpen)&&this.focusInput(),d&&l&&!i.isDisabled?this.setState({isFocused:!1},this.onMenuClose):!d&&!l&&i.isDisabled&&this.inputRef===document.activeElement&&this.setState({isFocused:!0}),this.menuListRef&&this.focusedOptionRef&&this.scrollToFocusedOptionOnUpdate&&(Sf(this.menuListRef,this.focusedOptionRef),this.scrollToFocusedOptionOnUpdate=!1)}},{key:"componentWillUnmount",value:function(){this.stopListeningComposition(),this.stopListeningToTouch(),document.removeEventListener("scroll",this.onScroll,!0)}},{key:"onMenuOpen",value:function(){this.props.onMenuOpen()}},{key:"onMenuClose",value:function(){this.onInputChange("",{action:"menu-close",prevInputValue:this.props.inputValue}),this.props.onMenuClose()}},{key:"onInputChange",value:function(i,s){this.props.onInputChange(i,s)}},{key:"focusInput",value:function(){!this.inputRef||this.inputRef.focus()}},{key:"blurInput",value:function(){!this.inputRef||this.inputRef.blur()}},{key:"openMenu",value:function(i){var s=this,l=this.state,u=l.selectValue,d=l.isFocused,p=this.buildFocusableOptions(),g=i==="first"?0:p.length-1;if(!this.props.isMulti){var v=p.indexOf(u[0]);v>-1&&(g=v)}this.scrollToFocusedOptionOnUpdate=!(d&&this.menuListRef),this.setState({inputIsHiddenAfterUpdate:!1,focusedValue:null,focusedOption:p[g]},function(){return s.onMenuOpen()})}},{key:"focusValue",value:function(i){var s=this.state,l=s.selectValue,u=s.focusedValue;if(!!this.props.isMulti){this.setState({focusedOption:null});var d=l.indexOf(u);u||(d=-1);var p=l.length-1,g=-1;if(!!l.length){switch(i){case"previous":d===0?g=0:d===-1?g=p:g=d-1;break;case"next":d>-1&&d0&&arguments[0]!==void 0?arguments[0]:"first",s=this.props.pageSize,l=this.state.focusedOption,u=this.getFocusableOptions();if(!!u.length){var d=0,p=u.indexOf(l);l||(p=-1),i==="up"?d=p>0?p-1:u.length-1:i==="down"?d=(p+1)%u.length:i==="pageup"?(d=p-s,d<0&&(d=0)):i==="pagedown"?(d=p+s,d>u.length-1&&(d=u.length-1)):i==="last"&&(d=u.length-1),this.scrollToFocusedOptionOnUpdate=!0,this.setState({focusedOption:u[d],focusedValue:null})}}},{key:"getTheme",value:function(){return this.props.theme?typeof this.props.theme=="function"?this.props.theme(Ef):z(z({},Ef),this.props.theme):Ef}},{key:"getCommonProps",value:function(){var i=this.clearValue,s=this.cx,l=this.getStyles,u=this.getClassNames,d=this.getValue,p=this.selectOption,g=this.setValue,v=this.props,I=v.isMulti,E=v.isRtl,w=v.options,A=this.hasValue();return{clearValue:i,cx:s,getStyles:l,getClassNames:u,getValue:d,hasValue:A,isMulti:I,isRtl:E,options:w,selectOption:p,selectProps:v,setValue:g,theme:this.getTheme()}}},{key:"hasValue",value:function(){var i=this.state.selectValue;return i.length>0}},{key:"hasOptions",value:function(){return!!this.getFocusableOptions().length}},{key:"isClearable",value:function(){var i=this.props,s=i.isClearable,l=i.isMulti;return s===void 0?l:s}},{key:"isOptionDisabled",value:function(i,s){return _y(this.props,i,s)}},{key:"isOptionSelected",value:function(i,s){return Wy(this.props,i,s)}},{key:"filterOption",value:function(i,s){return Gy(this.props,i,s)}},{key:"formatOptionLabel",value:function(i,s){if(typeof this.props.formatOptionLabel=="function"){var l=this.props.inputValue,u=this.state.selectValue;return this.props.formatOptionLabel(i,{context:s,inputValue:l,selectValue:u})}else return this.getOptionLabel(i)}},{key:"formatGroupLabel",value:function(i){return this.props.formatGroupLabel(i)}},{key:"startListeningComposition",value:function(){document&&document.addEventListener&&(document.addEventListener("compositionstart",this.onCompositionStart,!1),document.addEventListener("compositionend",this.onCompositionEnd,!1))}},{key:"stopListeningComposition",value:function(){document&&document.removeEventListener&&(document.removeEventListener("compositionstart",this.onCompositionStart),document.removeEventListener("compositionend",this.onCompositionEnd))}},{key:"startListeningToTouch",value:function(){document&&document.addEventListener&&(document.addEventListener("touchstart",this.onTouchStart,!1),document.addEventListener("touchmove",this.onTouchMove,!1),document.addEventListener("touchend",this.onTouchEnd,!1))}},{key:"stopListeningToTouch",value:function(){document&&document.removeEventListener&&(document.removeEventListener("touchstart",this.onTouchStart),document.removeEventListener("touchmove",this.onTouchMove),document.removeEventListener("touchend",this.onTouchEnd))}},{key:"renderInput",value:function(){var i=this.props,s=i.isDisabled,l=i.isSearchable,u=i.inputId,d=i.inputValue,p=i.tabIndex,g=i.form,v=i.menuIsOpen,I=i.required,E=this.getComponents(),w=E.Input,A=this.state,x=A.inputIsHidden,m=A.ariaSelection,y=this.commonProps,C=u||this.getElementId("input"),k=z(z(z({"aria-autocomplete":"list","aria-expanded":v,"aria-haspopup":!0,"aria-errormessage":this.props["aria-errormessage"],"aria-invalid":this.props["aria-invalid"],"aria-label":this.props["aria-label"],"aria-labelledby":this.props["aria-labelledby"],"aria-required":I,role:"combobox"},v&&{"aria-controls":this.getElementId("listbox"),"aria-owns":this.getElementId("listbox")}),!l&&{"aria-readonly":!0}),this.hasValue()?(m==null?void 0:m.action)==="initial-input-focus"&&{"aria-describedby":this.getElementId("live-region")}:{"aria-describedby":this.getElementId("placeholder")});return l?me.createElement(w,Y({},y,{autoCapitalize:"none",autoComplete:"off",autoCorrect:"off",id:C,innerRef:this.getInputRef,isDisabled:s,isHidden:x,onBlur:this.onInputBlur,onChange:this.handleInputChange,onFocus:this.onInputFocus,spellCheck:"false",tabIndex:p,form:g,type:"text",value:d},k)):me.createElement(FE,Y({id:C,innerRef:this.getInputRef,onBlur:this.onInputBlur,onChange:cs,onFocus:this.onInputFocus,disabled:s,tabIndex:p,inputMode:"none",form:g,value:""},k))}},{key:"renderPlaceholderOrValue",value:function(){var i=this,s=this.getComponents(),l=s.MultiValue,u=s.MultiValueContainer,d=s.MultiValueLabel,p=s.MultiValueRemove,g=s.SingleValue,v=s.Placeholder,I=this.commonProps,E=this.props,w=E.controlShouldRenderValue,A=E.isDisabled,x=E.isMulti,m=E.inputValue,y=E.placeholder,C=this.state,k=C.selectValue,M=C.focusedValue,N=C.isFocused;if(!this.hasValue()||!w)return m?null:me.createElement(v,Y({},I,{key:"placeholder",isDisabled:A,isFocused:N,innerProps:{id:this.getElementId("placeholder")}}),y);if(x)return k.map(function(P,O){var B=P===M,Z="".concat(i.getOptionLabel(P),"-").concat(i.getOptionValue(P));return me.createElement(l,Y({},I,{components:{Container:u,Label:d,Remove:p},isFocused:B,isDisabled:A,key:Z,index:O,removeProps:{onClick:function(){return i.removeValue(P)},onTouchEnd:function(){return i.removeValue(P)},onMouseDown:function(pe){pe.preventDefault()}},data:P}),i.formatOptionLabel(P,"value"))});if(m)return null;var D=k[0];return me.createElement(g,Y({},I,{data:D,isDisabled:A}),this.formatOptionLabel(D,"value"))}},{key:"renderClearIndicator",value:function(){var i=this.getComponents(),s=i.ClearIndicator,l=this.commonProps,u=this.props,d=u.isDisabled,p=u.isLoading,g=this.state.isFocused;if(!this.isClearable()||!s||d||!this.hasValue()||p)return null;var v={onMouseDown:this.onClearIndicatorMouseDown,onTouchEnd:this.onClearIndicatorTouchEnd,"aria-hidden":"true"};return me.createElement(s,Y({},l,{innerProps:v,isFocused:g}))}},{key:"renderLoadingIndicator",value:function(){var i=this.getComponents(),s=i.LoadingIndicator,l=this.commonProps,u=this.props,d=u.isDisabled,p=u.isLoading,g=this.state.isFocused;if(!s||!p)return null;var v={"aria-hidden":"true"};return me.createElement(s,Y({},l,{innerProps:v,isDisabled:d,isFocused:g}))}},{key:"renderIndicatorSeparator",value:function(){var i=this.getComponents(),s=i.DropdownIndicator,l=i.IndicatorSeparator;if(!s||!l)return null;var u=this.commonProps,d=this.props.isDisabled,p=this.state.isFocused;return me.createElement(l,Y({},u,{isDisabled:d,isFocused:p}))}},{key:"renderDropdownIndicator",value:function(){var i=this.getComponents(),s=i.DropdownIndicator;if(!s)return null;var l=this.commonProps,u=this.props.isDisabled,d=this.state.isFocused,p={onMouseDown:this.onDropdownIndicatorMouseDown,onTouchEnd:this.onDropdownIndicatorTouchEnd,"aria-hidden":"true"};return me.createElement(s,Y({},l,{innerProps:p,isDisabled:u,isFocused:d}))}},{key:"renderMenu",value:function(){var i=this,s=this.getComponents(),l=s.Group,u=s.GroupHeading,d=s.Menu,p=s.MenuList,g=s.MenuPortal,v=s.LoadingMessage,I=s.NoOptionsMessage,E=s.Option,w=this.commonProps,A=this.state.focusedOption,x=this.props,m=x.captureMenuScroll,y=x.inputValue,C=x.isLoading,k=x.loadingMessage,M=x.minMenuHeight,N=x.maxMenuHeight,D=x.menuIsOpen,P=x.menuPlacement,O=x.menuPosition,B=x.menuPortalTarget,Z=x.menuShouldBlockScroll,ie=x.menuShouldScrollIntoView,pe=x.noOptionsMessage,ue=x.onMenuScrollToTop,te=x.onMenuScrollToBottom;if(!D)return null;var Ve=function(G,ut){var ct=G.type,Be=G.data,rt=G.isDisabled,Vt=G.isSelected,Wn=G.label,oi=G.value,Or=A===Be,Rr=rt?void 0:function(){return i.onOptionHover(Be)},ar=rt?void 0:function(){return i.selectOption(Be)},_r="".concat(i.getElementId("option"),"-").concat(ut),Wr={id:_r,onClick:ar,onMouseMove:Rr,onMouseOver:Rr,tabIndex:-1};return me.createElement(E,Y({},w,{innerProps:Wr,data:Be,isDisabled:rt,isSelected:Vt,key:_r,label:Wn,type:ct,value:oi,isFocused:Or,innerRef:Or?i.getFocusedOptionRef:void 0}),i.formatOptionLabel(G.data,"menu"))},Qe;if(this.hasOptions())Qe=this.getCategorizedOptions().map(function(ce){if(ce.type==="group"){var G=ce.data,ut=ce.options,ct=ce.index,Be="".concat(i.getElementId("group"),"-").concat(ct),rt="".concat(Be,"-heading");return me.createElement(l,Y({},w,{key:Be,data:G,options:ut,Heading:u,headingProps:{id:rt,data:ce.data},label:i.formatGroupLabel(ce.data)}),ce.options.map(function(Vt){return Ve(Vt,"".concat(ct,"-").concat(Vt.index))}))}else if(ce.type==="option")return Ve(ce,"".concat(ce.index))});else if(C){var ye=k({inputValue:y});if(ye===null)return null;Qe=me.createElement(v,w,ye)}else{var wt=pe({inputValue:y});if(wt===null)return null;Qe=me.createElement(I,w,wt)}var lt={minMenuHeight:M,maxMenuHeight:N,menuPlacement:P,menuPosition:O,menuShouldScrollIntoView:ie},we=me.createElement(L0,Y({},w,lt),function(ce){var G=ce.ref,ut=ce.placerProps,ct=ut.placement,Be=ut.maxHeight;return me.createElement(d,Y({},w,lt,{innerRef:G,innerProps:{onMouseDown:i.onMenuMouseDown,onMouseMove:i.onMenuMouseMove,id:i.getElementId("listbox")},isLoading:C,placement:ct}),me.createElement(OE,{captureEnabled:m,onTopArrive:ue,onBottomArrive:te,lockEnabled:Z},function(rt){return me.createElement(p,Y({},w,{innerRef:function(Wn){i.getMenuListRef(Wn),rt(Wn)},isLoading:C,maxHeight:Be,focusedOption:A}),Qe)}))});return B||O==="fixed"?me.createElement(g,Y({},w,{appendTo:B,controlElement:this.controlRef,menuPlacement:P,menuPosition:O}),we):we}},{key:"renderFormField",value:function(){var i=this,s=this.props,l=s.delimiter,u=s.isDisabled,d=s.isMulti,p=s.name,g=s.required,v=this.state.selectValue;if(!(!p||u)){if(g&&!this.hasValue())return me.createElement(_E,{name:p,onFocus:this.onValueInputFocus});if(d)if(l){var I=v.map(function(A){return i.getOptionValue(A)}).join(l);return me.createElement("input",{name:p,type:"hidden",value:I})}else{var E=v.length>0?v.map(function(A,x){return me.createElement("input",{key:"i-".concat(x),name:p,type:"hidden",value:i.getOptionValue(A)})}):me.createElement("input",{name:p,type:"hidden",value:""});return me.createElement("div",null,E)}else{var w=v[0]?this.getOptionValue(v[0]):"";return me.createElement("input",{name:p,type:"hidden",value:w})}}}},{key:"renderLiveRegion",value:function(){var i=this.commonProps,s=this.state,l=s.ariaSelection,u=s.focusedOption,d=s.focusedValue,p=s.isFocused,g=s.selectValue,v=this.getFocusableOptions();return me.createElement(SE,Y({},i,{id:this.getElementId("live-region"),ariaSelection:l,focusedOption:u,focusedValue:d,isFocused:p,selectValue:g,focusableOptions:v}))}},{key:"render",value:function(){var i=this.getComponents(),s=i.Control,l=i.IndicatorsContainer,u=i.SelectContainer,d=i.ValueContainer,p=this.props,g=p.className,v=p.id,I=p.isDisabled,E=p.menuIsOpen,w=this.state.isFocused,A=this.commonProps=this.getCommonProps();return me.createElement(u,Y({},A,{className:g,innerProps:{id:v,onKeyDown:this.onKeyDown},isDisabled:I,isFocused:w}),this.renderLiveRegion(),me.createElement(s,Y({},A,{innerRef:this.getControlRef,innerProps:{onMouseDown:this.onControlMouseDown,onTouchEnd:this.onControlTouchEnd},isDisabled:I,isFocused:w,menuIsOpen:E}),me.createElement(d,Y({},A,{isDisabled:I}),this.renderPlaceholderOrValue(),this.renderInput()),me.createElement(l,Y({},A,{isDisabled:I}),this.renderClearIndicator(),this.renderLoadingIndicator(),this.renderIndicatorSeparator(),this.renderDropdownIndicator())),this.renderMenu(),this.renderFormField())}}],[{key:"getDerivedStateFromProps",value:function(i,s){var l=s.prevProps,u=s.clearFocusValueOnUpdate,d=s.inputIsHiddenAfterUpdate,p=s.ariaSelection,g=s.isFocused,v=s.prevWasFocused,I=i.options,E=i.value,w=i.menuIsOpen,A=i.inputValue,x=i.isMulti,m=Ui(E),y={};if(l&&(E!==l.value||I!==l.options||w!==l.menuIsOpen||A!==l.inputValue)){var C=w?XE(i,m):[],k=u?jE(s,m):null,M=UE(s,C);y={selectValue:m,focusedOption:M,focusedValue:k,clearFocusValueOnUpdate:!1}}var N=d!=null&&i!==l?{inputIsHidden:d,inputIsHiddenAfterUpdate:void 0}:{},D=p,P=g&&v;return g&&!P&&(D={value:ii(x,m,m[0]||null),options:m,action:"initial-input-focus"},P=!v),(p==null?void 0:p.action)==="initial-input-focus"&&(D=null),z(z(z({},y),N),{},{prevProps:i,ariaSelection:D,prevWasFocused:P})}}]),n}(fe.Component);Tf.defaultProps=zE;var sr=he(Ne()),QE=["defaultInputValue","defaultMenuIsOpen","defaultValue","inputValue","menuIsOpen","onChange","onInputChange","onMenuClose","onMenuOpen","value"];function Vy(e){var t=e.defaultInputValue,n=t===void 0?"":t,r=e.defaultMenuIsOpen,i=r===void 0?!1:r,s=e.defaultValue,l=s===void 0?null:s,u=e.inputValue,d=e.menuIsOpen,p=e.onChange,g=e.onInputChange,v=e.onMenuClose,I=e.onMenuOpen,E=e.value,w=un(e,QE),A=(0,sr.useState)(u!==void 0?u:n),x=ln(A,2),m=x[0],y=x[1],C=(0,sr.useState)(d!==void 0?d:i),k=ln(C,2),M=k[0],N=k[1],D=(0,sr.useState)(E!==void 0?E:l),P=ln(D,2),O=P[0],B=P[1],Z=(0,sr.useCallback)(function(ye,wt){typeof p=="function"&&p(ye,wt),B(ye)},[p]),ie=(0,sr.useCallback)(function(ye,wt){var lt;typeof g=="function"&&(lt=g(ye,wt)),y(lt!==void 0?lt:ye)},[g]),pe=(0,sr.useCallback)(function(){typeof I=="function"&&I(),N(!0)},[I]),ue=(0,sr.useCallback)(function(){typeof v=="function"&&v(),N(!1)},[v]),te=u!==void 0?u:m,Ve=d!==void 0?d:M,Qe=E!==void 0?E:O;return z(z({},w),{},{inputValue:te,menuIsOpen:Ve,onChange:Z,onInputChange:ie,onMenuClose:ue,onMenuOpen:pe,value:Qe})}var ps=he(Ne());var $E=["allowCreateWhileLoading","createOptionPosition","formatCreateLabel","isValidNewOption","getNewOptionData","onCreateOption","options","onChange"],By=function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:"",n=arguments.length>1?arguments[1]:void 0,r=arguments.length>2?arguments[2]:void 0,i=String(t).toLowerCase(),s=String(r.getOptionValue(n)).toLowerCase(),l=String(r.getOptionLabel(n)).toLowerCase();return s===i||l===i},Nf={formatCreateLabel:function(t){return'Create "'.concat(t,'"')},isValidNewOption:function(t,n,r,i){return!(!t||n.some(function(s){return By(t,s,i)})||r.some(function(s){return By(t,s,i)}))},getNewOptionData:function(t,n){return{label:n,value:t,__isNew__:!0}}};function Hy(e){var t=e.allowCreateWhileLoading,n=t===void 0?!1:t,r=e.createOptionPosition,i=r===void 0?"last":r,s=e.formatCreateLabel,l=s===void 0?Nf.formatCreateLabel:s,u=e.isValidNewOption,d=u===void 0?Nf.isValidNewOption:u,p=e.getNewOptionData,g=p===void 0?Nf.getNewOptionData:p,v=e.onCreateOption,I=e.options,E=I===void 0?[]:I,w=e.onChange,A=un(e,$E),x=A.getOptionValue,m=x===void 0?Ff:x,y=A.getOptionLabel,C=y===void 0?kf:y,k=A.inputValue,M=A.isLoading,N=A.isMulti,D=A.value,P=A.name,O=(0,ps.useMemo)(function(){return d(k,Ui(D),E,{getOptionValue:m,getOptionLabel:C})?g(k,l(k)):void 0},[l,g,C,m,k,d,E,D]),B=(0,ps.useMemo)(function(){return(n||!M)&&O?i==="first"?[O].concat(Dr(E)):[].concat(Dr(E),[O]):E},[n,i,M,O,E]),Z=(0,ps.useCallback)(function(ie,pe){if(pe.action!=="select-option")return w(ie,pe);var ue=Array.isArray(ie)?ie:[ie];if(ue[ue.length-1]===O){if(v)v(k);else{var te=g(k,k),Ve={action:"create-option",name:P,option:te};w(ii(N,[].concat(Dr(Ui(D)),[te]),te),Ve)}return}w(ie,pe)},[g,k,N,P,O,v,w,D]);return z(z({},A),{},{options:B,onChange:Z})}var oT=he(Ko());var KE=(0,Zy.forwardRef)(function(e,t){var n=Vy(e),r=Hy(n);return Yy.createElement(Tf,Y({ref:t},r))}),zy=KE;var Pl=({options:e,placeholder:t,container:n,onChange:r,onInputChange:i,newLabel:s,value:l})=>{let u=(0,hs.useCallback)(d=>qE({value:d,label:s}),[s]);return hs.default.createElement(zy,{options:e,formatCreateLabel:u,inputValue:l,onChange:r,onInputChange:i,styles:eA,isClearable:!0,placeholder:t,controlShouldRenderValue:!1,menuPortalTarget:n})},qE=({value:e,label:t})=>hs.default.createElement("span",null,t.format(e)),eA={option:(e,t)=>ne(j({},e),{background:t.isFocused?"var(--background-secondary)":"var(--background-primary)",color:"var(--text-normal)","&:hover":ne(j({},e["&:hover"]),{backgroundColor:"var(--background-secondary)"})}),valueContainer:(e,t)=>ne(j({},e),{color:"var(--text-normal)"}),menu:e=>j({},e),menuList:(e,t)=>ne(j({},e),{border:"1px solid var(--background-modifier-border)",backgroundColor:"var(--background-secondary-alt)",color:"var(--text-normal)"}),input:(e,t)=>ne(j({},e),{color:"var(--text-normal)"}),singleValue:(e,t)=>ne(j({},e),{color:"var(--text-normal)"}),control:(e,t)=>ne(j({},e),{background:"var(--background-modifier-form-field)",color:"var(--text-normal)",border:"1px solid var(--background-modifier-border)",boxShadow:"none",width:"300px","&:hover":ne(j({},e["&:hover"]),{borderColor:"var(--background-modifier-border)"}),"&:active":ne(j({},e["&:active"]),{borderColor:"var(--interactive-accent);"}),"&:focus":ne(j({},e["&:focus"]),{borderColor:"var(--interactive-accent);"}),"&:focused":ne(j({},e["&:focused"]),{borderColor:"var(--interactive-accent);"}),"&:focus-within":ne(j({},e["&:focus-within"]),{borderColor:"var(--interactive-accent);"})}),menuPortal:e=>ne(j({},e),{zIndex:"var(--layer-modal)"})};var Dl=class extends Xy.Modal{constructor(n,r,i){super(n);this.settings=r,this.titleEl.setText("Janitor Excluded Files"),this.onFiltersChanged=i}render(){let n=el(this.app).map(r=>({value:r.endsWith("/")?r:r+"/",label:r}));this.root.render(Ue.createElement(Ue.StrictMode,null,Ue.createElement(tA,{filters:this.settings.excludedFilesFilters,folders:n,onCancel:()=>{this.close()},onFilterChanged:r=>{this.close(),this.onFiltersChanged&&this.onFiltersChanged(r)}})))}onOpen(){let{contentEl:n}=this;this.root=(0,jy.createRoot)(n),this.render()}onClose(){this.root.unmount()}},tA=({filters:e,folders:t,onCancel:n,onFilterChanged:r})=>{let[i,s]=(0,Rn.useState)({filters:e,value:""}),l=i.filters,u=(0,Rn.useRef)(null),d=(0,Rn.useCallback)(A=>{s(x=>Mf(x.value)?ne(j({},x),{filters:[...x.filters,x.value],value:""}):x)},[]),p=(0,Rn.useCallback)((A,x)=>{(x.action==="select-option"||x.action==="create-option")&&s(m=>Mf(A.value)?ne(j({},m),{filters:[...m.filters,A.value],value:""}):m)},[]),g=(0,Rn.useCallback)((A,x)=>{x.action==="input-change"&&s(m=>ne(j({},m),{value:A}))},[]),v=(0,Rn.useCallback)(A=>{s(x=>ne(j({},x),{filters:x.filters.filter((m,y)=>A!==y)}))},[]),I=(0,Rn.useCallback)(()=>{r&&r(i.filters)},[i.filters]),E=Mf(i.value),w=E?"Press enter or button to add filter":"insert a valid regular expression";return Ue.createElement("div",{ref:u},Ue.createElement("div",null,"Files matching the following regular expressions are currently ignored:"),l.map((A,x)=>Ue.createElement("div",{key:x,className:"mobile-option-setting-item"},Ue.createElement("span",{className:"mobile-option-setting-item-name"},A),Ue.createElement("span",{className:"mobile-option-setting-item-option-icon",onClick:()=>v(x)},Ue.createElement(nl,null)))),Ue.createElement(ol,null,Ue.createElement(rl,{name:"Filter",description:w}),Ue.createElement(il,null,Ue.createElement(Pl,{key:e.length,value:i.value,container:document.body,options:t,placeholder:"Insert folder or regex...",newLabel:'Add "{0}"',onChange:p,onInputChange:g}),Ue.createElement("button",{onClick:d,disabled:!E},"Add"))),Ue.createElement("div",{className:"modal-button-container"},Ue.createElement("button",{className:"mod-cta",onClick:I},"Done"),Ue.createElement("button",{onClick:n},"Cancel")))};function Mf(e){let t=e.length>0;try{let n=new RegExp(e)}catch(n){t=!1}return t}var Je=he(Ne()),Uy=require("obsidian"),Jy=he(qo());var _n=he(Ne());var Ol=class extends Uy.Modal{constructor(n,r,i){super(n);this.settings=r,this.titleEl.setText("Janitor Included Files"),this.onFiltersChanged=i}render(){let n=el(this.app).map(r=>({value:r.endsWith("/")?r:r+"/",label:r}));this.root.render(Je.createElement(Je.StrictMode,null,Je.createElement(nA,{filters:this.settings.includedFilesFilters,folders:n,onCancel:()=>{this.close()},onFilterChanged:r=>{this.close(),this.onFiltersChanged&&this.onFiltersChanged(r)}})))}onOpen(){let{contentEl:n}=this;this.root=(0,Jy.createRoot)(n),this.render()}onClose(){this.root.unmount()}},nA=({filters:e,folders:t,onCancel:n,onFilterChanged:r})=>{let[i,s]=(0,_n.useState)({filters:e,value:""}),l=i.filters,u=(0,_n.useRef)(null),d=(0,_n.useCallback)(A=>{s(x=>Pf(x.value)?ne(j({},x),{filters:[...x.filters,x.value],value:""}):x)},[]),p=(0,_n.useCallback)((A,x)=>{(x.action==="select-option"||x.action==="create-option")&&s(m=>Pf(A.value)?ne(j({},m),{filters:[...m.filters,A.value],value:""}):m)},[]),g=(0,_n.useCallback)((A,x)=>{x.action==="input-change"&&s(m=>ne(j({},m),{value:A}))},[]),v=(0,_n.useCallback)(A=>{s(x=>ne(j({},x),{filters:x.filters.filter((m,y)=>A!==y)}))},[]),I=(0,_n.useCallback)(()=>{r&&r(i.filters)},[i.filters]),E=Pf(i.value),w=E?"Press enter or button to add filter":"insert a valid regular expression";return Je.createElement("div",{ref:u},Je.createElement("div",null,"Files matching the following regular expressions are always included, even if excluded by other rules:"),l.map((A,x)=>Je.createElement("div",{key:x,className:"mobile-option-setting-item"},Je.createElement("span",{className:"mobile-option-setting-item-name"},A),Je.createElement("span",{className:"mobile-option-setting-item-option-icon",onClick:()=>v(x)},Je.createElement(nl,null)))),Je.createElement(ol,null,Je.createElement(rl,{name:"Filter",description:w}),Je.createElement(il,null,Je.createElement(Pl,{key:e.length,value:i.value,container:document.body,options:t,placeholder:"Insert folder or regex...",newLabel:'Add "{0}"',onChange:p,onInputChange:g}),Je.createElement("button",{onClick:d,disabled:!E},"Add"))),Je.createElement("div",{className:"modal-button-container"},Je.createElement("button",{className:"mod-cta",onClick:I},"Done"),Je.createElement("button",{onClick:n},"Cancel")))};function Pf(e){let t=e.length>0;try{new RegExp(e)}catch(n){t=!1}return t}var cn=require("obsidian"),ms=class extends cn.PluginSettingTab{constructor(n,r){super(n,r);this.plugin=r}display(){let{containerEl:n}=this;n.empty(),n.createEl("h2",{text:"Janitor Settings"}),new cn.Setting(n).setName("Add Ribbon Icon").setDesc("Adds an icon to the ribbon to launch scan").addToggle(s=>s.setValue(this.plugin.settings.addRibbonIcon).onChange(l=>ae(this,null,function*(){this.plugin.settings.addRibbonIcon=l,yield this.plugin.saveSettings(),l?this.plugin.addIcon():this.plugin.removeIcon(),this.display()}))),this.createToggle(n,"Run at Startup","The plugin will perform a scan automatically everytime you open a vault.","runAtStartup"),this.createToggle(n,"Ask Confirmation","The user will be able to select which files to remove","promptUser"),new cn.Setting(n).setName("Always Prompt for big files").setDesc("Always prompt before deleting big files").addToggle(s=>s.setValue(this.plugin.settings.promptForBigFiles).onChange(l=>ae(this,null,function*(){this.plugin.settings.promptForBigFiles=l,yield this.plugin.saveSettings()}))),new cn.Setting(n).setHeading(),this.createToggle(n,"Process Orphans","Remove media and attachments that are not in use","processOrphans"),this.plugin.settings.processOrphans&&this.createToggle(n,"Ignore Bases (.base files)","Exclude Obsidian Bases files from orphan detection","ignoreBaseFiles"),this.createToggle(n,"Process Empty","Remove empty files or files with only whitespace","processEmpty"),this.plugin.settings.processEmpty&&this.createToggle(n,"Ignore Frontmatter","Consider a note empty if it only contains frontmatter and no body","emptyIgnoresFrontmatter"),this.createToggle(n,"Process Empty Folders","Remove folders that contain no files or subfolders","processEmptyFolders"),this.createToggle(n,"Process Big Files","Removes files with big dimensions","processBig"),this.plugin.settings.processBig&&new cn.Setting(n).setName("File Size Limit (KB)").setDesc("Files larger than this size will be considered for removal.").addText(s=>s.setValue(this.plugin.settings.sizeLimitKb.toString()).onChange(l=>ae(this,null,function*(){let u=parseInt(l);isFinite(u)?this.plugin.settings.sizeLimitKb=u:this.plugin.settings.sizeLimitKb=qa.sizeLimitKb,yield this.plugin.saveSettings()}))),this.createToggle(n,"Process Expired","Remove notes that have expired","processExpired"),this.plugin.settings.processExpired&&(n.createEl("h3",{text:"Expiration Processing"}),new cn.Setting(n).setName("Metadata Attribute").setDesc("The frontMatter key in which to search for expiration date").addText(s=>s.setPlaceholder("Insert attribute name (es: expires)").setValue(this.plugin.settings.expiredAttribute).onChange(l=>ae(this,null,function*(){this.plugin.settings.expiredAttribute=l,yield this.plugin.saveSettings()}))),new cn.Setting(n).setName("Date Format").setDesc("The format in which the expiration date is stored (e.g. YYYY-MM-DD)").addText(s=>s.setPlaceholder("Insert the date format").setValue(this.plugin.settings.expiredDateFormat).onChange(l=>ae(this,null,function*(){this.plugin.settings.expiredDateFormat=l,yield this.plugin.saveSettings()})))),n.createEl("h3",{text:"File Exclusions"}),this.createToggle(n,"Ignore Obsidian Excluded Files","Does not process files matching the Excluded Files filters in Obsidian Settings","honorObsidianExcludedFiles");let r=new cn.Setting(n).setName("Excluded Files").setDesc("Excluded files will not be processed").addButton(s=>{s.setButtonText("Manage"),s.onClick(l=>{new Dl(this.app,this.plugin.settings,u=>ae(this,null,function*(){this.plugin.settings.excludedFilesFilters=u,yield this.plugin.saveSettings(),this.display()})).open()})});if(this.plugin.settings.excludedFilesFilters&&this.plugin.settings.excludedFilesFilters.length){let s=r.descEl.createEl("ul");this.plugin.settings.excludedFilesFilters.forEach(l=>{s.createEl("li").setText(l)})}let i=new cn.Setting(n).setName("Included Files").setDesc("Included files will always be processed, even if matched by exclusion rules").addButton(s=>{s.setButtonText("Manage"),s.onClick(l=>{new Ol(this.app,this.plugin.settings,u=>ae(this,null,function*(){this.plugin.settings.includedFilesFilters=u,yield this.plugin.saveSettings(),this.display()})).open()})});if(this.plugin.settings.includedFilesFilters&&this.plugin.settings.includedFilesFilters.length){let s=i.descEl.createEl("ul");this.plugin.settings.includedFilesFilters.forEach(l=>{s.createEl("li").setText(l)})}}createToggle(n,r,i,s){new cn.Setting(n).setName(r).setDesc(i).addToggle(l=>l.setValue(this.plugin.settings[s]).onChange(u=>ae(this,null,function*(){this.plugin.settings[s]=u,yield this.plugin.saveSettings(),this.display()})))}};var Rl=class{constructor(t){this.app=t}process(r){return ae(this,arguments,function*(t,n="trash"){let i=[...new Set(t)],s=0,l=0;for(let u of i){let d=app.vault.getAbstractFileByPath(u);if(d)try{switch(n){case"trash-system":yield app.vault.trash(d,!0),s++;break;case"trash":yield app.vault.trash(d,!1),s++;break;case"delete":yield app.vault.delete(d),s++;break;default:console.warn(`Warning: operation ${n} unknown`);break}}catch(p){l++}else console.warn(`Warning: file ${u} was not found for thrashing!`),l++}return{deletedFiles:s,notDeletedFiles:l}})}};var $y=he(Qy()),_l=class extends wn.Plugin{constructor(){super(...arguments);this.initialScanDone=!1}onload(){return ae(this,null,function*(){this.initialScanDone=!1,yield this.loadSettings(),this.settings.addRibbonIcon&&this.addIcon(),this.statusBarItemEl=this.addStatusBarItem(),this.updateStatusBar(""),this.addCommand({id:"scan-files",name:"Scan Files",callback:()=>{this.scanFiles()}}),this.addCommand({id:"scan-files-noprompt",name:"Scan Files (without prompt)",callback:()=>{this.scanFiles(!1,!0)}}),this.addCommand({id:"scan-files-with-prompt",name:"Scan Files (with prompt)",callback:()=>{this.scanFiles(!0,!1)}}),this.addCommand({id:"scan-vault-orphans",name:"Scan Vault (Orphans)",callback:()=>{this.scanFilesFor("orphans")}}),this.addCommand({id:"scan-vault-expired",name:"Scan Vault (Expired)",callback:()=>{this.scanFilesFor("expired")}}),this.addCommand({id:"scan-vault-big",name:"Scan Vault (Big Files)",callback:()=>{this.scanFilesFor("big")}}),this.addCommand({id:"set-expiration",name:"Sets the expiration date of the current note",checkCallback:n=>{let r=this.app.workspace.getActiveViewOfType(wn.MarkdownView);return r?(n||this.chooseDate(r),!0):!1}}),this.createShortcutCommand("set-expiration-1week","Set Expiration (1 week)",1,"week"),this.createShortcutCommand("set-expiration-1month","Set Expiration (1 month)",1,"month"),this.createShortcutCommand("set-expiration-1year","Set Expiration (1 year)",1,"year"),this.addSettingTab(new ms(this.app,this)),this.app.metadataCache.on("resolved",()=>ae(this,null,function*(){this.settings.runAtStartup&&!this.initialScanDone&&(this.initialScanDone=!0,yield this.waitForSyncIfNeeded(),this.scanFiles())}))})}createShortcutCommand(n,r,i,s){this.addCommand({id:n,name:r,checkCallback:l=>{let u=this.app.workspace.getActiveViewOfType(wn.MarkdownView);return u?(l||this.updateNoteWithDate(u,(0,$y.default)().add(i,s).format(this.settings.expiredDateFormat)),!0):!1}})}chooseDate(n){return ae(this,null,function*(){new $a(this.app,this,n).open()})}updateNoteWithDate(n,r){return ae(this,null,function*(){yield this.app.fileManager.processFrontMatter(n.file,i=>{i[this.settings.expiredAttribute]=r})})}updateStatusBar(n){this.statusBarItemEl.setText(n)}scanFilesFor(n){return ae(this,null,function*(){new wn.Notice("Janitor is scanning vault"),this.updateStatusBar("Janitor Scanning...");let r=ne(j({},this.settings),{processOrphans:n==="orphans",processEmpty:!1,processExpired:n==="expired",processBig:n==="big"}),i=yield new rs(this.app,r).scan();if(this.updateStatusBar(""),!(i.orphans&&i.orphans.length||i.expired&&i.expired.length||i.big&&i.big.length)){new wn.Notice("Janitor scanned and found nothing to cleanup");return}let l=new Yi(this.app,this);l.open(),l.updateState(i)})}scanFiles(n=!1,r=!1){return ae(this,null,function*(){var u;new wn.Notice("Janitor is scanning vault"),this.updateStatusBar("Janitor Scanning...");let i,s=yield new rs(this.app,this.settings).scan(),l=s.orphans&&s.orphans.length||s.empty&&s.empty.length||s.emptyFolders&&s.emptyFolders.length||s.expired&&s.expired.length||s.big&&s.big.length;if(this.updateStatusBar(""),!l){new wn.Notice("Janitor scanned and found nothing to cleanup");return}if((this.settings.promptUser&&!r||((u=s.big)==null?void 0:u.length)&&this.settings.promptForBigFiles||n)&&(i=new Yi(this.app,this),i.open()),i)i.updateState(s);else{let d=[s.orphans,s.empty,s.emptyFolders,s.expired,s.big].flatMap(p=>p?p.map(g=>g.path):[]);d=[...new Set(d)],this.perform(this.settings.defaultOperation,d)}})}perform(n,r){return ae(this,null,function*(){let s=yield new Rl(this.app).process(r,n);new wn.Notice(`${s.deletedFiles} files deleted.`+(s.notDeletedFiles?`${s.notDeletedFiles} files not deleted`:""))})}waitForSyncIfNeeded(){var r,i,s;let n=(s=(i=(r=this.app.internalPlugins)==null?void 0:r.plugins)==null?void 0:i.sync)==null?void 0:s.instance;return!n||!n.syncing?Promise.resolve():new Promise(l=>{let u=n.on("status-change",()=>{n.syncing||(n.offref(u),l())})})}onunload(){}addIcon(){this.removeIcon(),this.ribbonIconEl=this.addRibbonIcon("trash","Janitor: scan vault",n=>{this.scanFiles()}),this.ribbonIconEl.addClass("janitor-ribbon-class")}removeIcon(){this.ribbonIconEl&&this.ribbonIconEl.remove()}loadSettings(){return ae(this,null,function*(){this.settings=Object.assign({},qa,yield this.loadData())})}saveSettings(){return ae(this,null,function*(){yield this.saveData(this.settings)})}}; +/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** + * @license React + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +/** @license React v16.13.1 + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! moment.js +//! momentjs.com +//! version : 2.29.4 + +/* nosourcemap */ \ No newline at end of file diff --git a/10_Wiki/Topics/.obsidian/plugins/janitor/manifest.json b/10_Wiki/Topics/.obsidian/plugins/janitor/manifest.json new file mode 100644 index 00000000..7577964b --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/janitor/manifest.json @@ -0,0 +1,11 @@ +{ + "id": "janitor", + "name": "Janitor", + "version": "1.1.3", + "minAppVersion": "0.15.0", + "description": "Performs cleanup tasks on the Obsidian vault", + "author": "Gabriele Cannata", + "authorUrl": "https://github.com/Canna71", + "fundingUrl": "https://www.buymeacoffee.com/gcannata", + "isDesktopOnly": false +} diff --git a/10_Wiki/Topics/.obsidian/plugins/janitor/styles.css b/10_Wiki/Topics/.obsidian/plugins/janitor/styles.css new file mode 100644 index 00000000..c58b90cb --- /dev/null +++ b/10_Wiki/Topics/.obsidian/plugins/janitor/styles.css @@ -0,0 +1,174 @@ +/* + +This CSS file will be included with your plugin, and +available in the app when your plugin is enabled. + +If your plugin does not need CSS, delete this file. + +*/ +.janitor-modal-footer { + /* float: right; */ + padding: 10pt; + display: flex; +} + +.janitor-modal-footer button { + margin-left: 4px; +} + +.janitor-modal-footer .janitor-footer-buttons { + flex: 1; + justify-content: flex-end; + display: flex; +} + +.janitor-scan-section-title { + font-size: larger; + margin-bottom: 5pt; + font-weight: 600; +} + +.janitor-modal-title { + text-align: center; + font-size: 150%; + margin-bottom: 10px; +} + +.janitor-file { + margin-left: 1em; + position: relative; +} + +.janitor-file:hover { + background-color: var(--background-primary); +} + + +.janitor-file .openFileIcon { + right: 0px; + position: absolute; + visibility: hidden; +} + +.janitor-file label { + width: 100%; + display: flex; + align-items: center; +} + +.janitor-file-name { + flex: 1; + min-width: 0; + overflow: hidden; + margin-right: 3.5em; +} + +.janitor-icon { + display: flex; + align-items: center; + line-height: 1; +} + +.janitor-icon svg { + width: 14px; + height: 14px; +} + +.janitor-file-name-text { + display: inline-block; + white-space: nowrap; +} + +.janitor-file:hover .janitor-file-name-text { + animation: janitor-marquee 4s ease-in-out infinite alternate; +} + +@keyframes janitor-marquee { + 0%, 15% { transform: translateX(0); } + 85%, 100% { transform: translateX(var(--marquee-offset, 0px)); } +} + +.janitor-md-preview-link { + display: contents; +} + +.previewFileIcon { + right: 1.5em; + position: absolute; + visibility: hidden; +} + +.janitor-file:hover .previewFileIcon { + visibility: visible; +} + +.janitor-preview-overlay { + position: fixed; + z-index: 9999; + padding: 6px; + background: var(--background-primary); + border: 1px solid var(--background-modifier-border); + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); + pointer-events: none; +} + +.janitor-preview-overlay img { + display: block; + max-width: 200px; + max-height: 200px; + object-fit: contain; + border-radius: 3px; +} + +.janitor-file:hover .openFileIcon { + visibility: visible; +} + +.janitor-file:focus { + outline: auto; +} + +.janitor-main-modal { + width: min(700px, 90vw); +} + +/* Ensure hover preview popover appears above the modal overlay */ +.popover.hover-popover { + z-index: calc(var(--layer-modal, 200) + 10); +} + +.janitor-scan-results { + overflow-y: auto; + max-height: 450px; +} + +.janitor-files-wrapper { + /* overflow-y: auto; */ + /* max-height: 180px; */ + /* border: 1px solid; */ + padding: 5px; +} + +.janitor-date-picker { + padding: 5px;; +} + +.janitor-date-picker label span { + margin-right: 1em;; +} + + +.janitor-date-picker-buttons { + float: right; +} + +.janitor-date-shortcuts { + white-space: nowrap; + margin-top: 1em; + text-align: center; +} + +.janitor-date-shortcuts .janitor-date-picker-buttons { + display: inline-block; +} diff --git a/10_Wiki/Topics/.obsidian/workspace.json b/10_Wiki/Topics/.obsidian/workspace.json index 6be1be00..d5563d91 100644 --- a/10_Wiki/Topics/.obsidian/workspace.json +++ b/10_Wiki/Topics/.obsidian/workspace.json @@ -11,10 +11,14 @@ "id": "471c758202e009a4", "type": "leaf", "state": { - "type": "graph", - "state": {}, - "icon": "lucide-git-fork", - "title": "그래프 뷰" + "type": "markdown", + "state": { + "file": "Programming & Language/도메인 기반 설계(DDD)의 데이터 검증.md", + "mode": "source", + "source": false + }, + "icon": "lucide-file", + "title": "도메인 기반 설계(DDD)의 데이터 검증" } } ] @@ -160,13 +164,23 @@ "icon": "lucide-list", "title": "Focal Loss (포컬 손실) 의 개요" } + }, + { + "id": "665019ba50aa9743", + "type": "leaf", + "state": { + "type": "broken-links-view", + "state": {}, + "icon": "unlink", + "title": "Broken links" + } } - ] + ], + "currentTab": 5 } ], "direction": "horizontal", - "width": 300, - "collapsed": true + "width": 300 }, "left-ribbon": { "hiddenItems": { @@ -176,11 +190,22 @@ "daily-notes:오늘의 일일 노트 열기": false, "templates:템플릿 삽입": false, "command-palette:명령어 팔레트 열기": false, - "bases:새 베이스 생성하기": false + "bases:새 베이스 생성하기": false, + "janitor:Janitor: scan vault": false, + "broken-links:View broken links": false } }, "active": "471c758202e009a4", "lastOpenFiles": [ + "Native Apps.md", + "대규모 건설 플랫폼 뷰어(Large-Scale Construction Viewers).md", + "자연어 프롬프트 (Natural Language Prompt).md", + "인지 행동 치료 (CBT).md", + "인문학적 게임 비평 및 서사학.md", + "무제 1.base", + "무제.base", + "무제 1.canvas", + "무제.canvas", "memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_블로그_v3.json", "memory/episodes/ep_2026-05-05_새로운_프로젝트야_이건_google_ai_studio에서_실행되는거야_다.json", "AI/Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리).md", @@ -205,17 +230,10 @@ "AI/Agent_State_Store.md", "Risk-Management.md", "확산 모델 (Diffusion Models).md", - "확산 모델 (Diffusion Model).md", - "해부학적 오류 디버깅 워크플로우.md", - "프롬프트 확장(Prompt Expansion).md", - "프롬프트 파라미터 제어 (Prompt Parameter Control).md", "sessions/2026-04-30T07-07", "sessions", "company_state.json", "_shared", - "_agents/youtube/tools/youtube_account.py", - "_agents/youtube/tools/youtube_account.json", - "_agents/youtube/tools/trend_sniper.py", - "_agents/youtube/tools/trend_sniper.json" + "_agents/youtube/tools/youtube_account.py" ] } \ No newline at end of file diff --git a/10_Wiki/Topics/03_DevOps_Environment/Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성).md b/10_Wiki/Topics/03_DevOps_Environment/Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성).md index 7945e098..6d021488 100644 --- a/10_Wiki/Topics/03_DevOps_Environment/Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성).md +++ b/10_Wiki/Topics/03_DevOps_Environment/Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성).md @@ -1,40 +1,38 @@ # [[Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성)]] ## 📌 Brief Summary -에이전틱 인프라는 에이전트(LLM)가 안전하고 일관성 있게 작업을 수행할 수 있도록 지원하는 하부 구조를 의미한다. 이는 에이전트의 코드 실행을 격리하는 **[[Sandbox (샌드박스)]]**, 도구 및 데이터 연동을 표준화하는 **[[MCP (Model Context Protocol)]]**, 그리고 에이전트의 행동과 데이터의 출처를 추적하는 **[[Observability (관측성)]]** 및 **[[Data Governance (데이터 거버넌스)]]**로 구성된다. +에이전틱 인프라는 에이전트(LLM)가 안전하고 일관성 있게 작업을 수행할 수 있도록 지원하는 하부 구조를 의미한다 [1, 2]. 이는 에이전트의 코드 실행을 격리하는 **[[Sandbox (샌드박스)]]**, 도구 및 데이터 연동을 표준화하는 **[[MCP (Model Context Protocol)]]**, 그리고 에이전트의 행동과 데이터의 출처를 추적하는 **[[Observability (관측성)]]** 및 **[[Data Governance (데이터 거버넌스)]]**로 구성된다 [3-5]. ## 📖 Core Content -### 1. 실행 격리 및 보안 (Sandbox) -* **[[Docker]] 기반 샌드박스**: 컨테이너 기술을 활용하여 에이전트의 코드 실행 환경을 호스트 시스템과 격리. 표준화된 환경 제공에 유리하다. -* **[[MicroVM]] (Firecracker 등)**: 더 강력한 하드웨어 수준의 격리를 제공하여, 멀티 테넌트 환경이나 고위험 코드 실행 시 보안 위협을 원천 차단한다. +### 1. 실행 격리 및 보안 (Sandbox Substrate) +* **[[Docker]] 기반 샌드박스**: 컨테이너 기술을 활용하여 에이전트의 코드 실행 환경을 격리. 표준화된 환경 제공에 유리하다 [6]. +* **[[MicroVM]] (E2B, Firecracker)**: 하드웨어 수준의 격리를 제공하여 멀티 테넌트 환경에서 고위험 코드 실행 시 보안 위협을 원천 차단한다 [7]. +* **Kubernetes Agent Sandbox**: 대규모 에이전트 클러스터 운영을 위한 오케스트레이션 기반 격리 환경 [8]. -### 2. 도구 및 데이터 표준화와 상호 운용성 (MCP & A2A) -* **[[Model Context Protocol (MCP)]]**: 에이전트가 별도의 클라이언트 구현 없이 로컬 파일, 외부 API, 데이터베이스에 일관된 방식으로 접근할 수 있게 해주는 개방형 표준 프로토콜. **에이전트와 도구/데이터 간의 연결**을 표준화한다. -* **[[A2A Protocol (Agent-to-Agent)]]**: 구글이 주도하는 에이전트 간 상호 운용성 표준. HTTP(S)/SSE 및 JSON-RPC를 기반으로 에이전트들이 작업(Task), 메시지(Message), 아티팩트(Artifact)를 교환할 수 있게 한다. **에이전트와 에이전트 간의 협업**을 표준화한다. -* **Agent Card & Discovery**: '에이전트 카드' 메커니즘을 통해 네트워크상에서 다른 에이전트의 존재와 역량을 동적으로 발견(Discovery)할 수 있게 한다. -* **MCP Gateway**: 여러 MCP 서버를 통합 관리하고 보안 정책을 적용하는 중앙 제어 지점 역할을 한다. +### 2. 도구 및 데이터 표준화 (MCP & Protocols) +* **[[Model Context Protocol (MCP)]]**: 로컬 파일, 외부 API, 데이터베이스에 일관된 방식으로 접근하게 해주는 개방형 표준 [13]. +* **[[A2A Protocol (Agent-to-Agent)]]**: 에이전트 간 작업(Task) 및 메시지 교환을 위한 상호 운용성 표준 [14]. -### 3. 관측성 및 거버넌스 (Observability & Governance) -* **LLM Observability**: 에이전트의 사고 과정(Thought), 도구 호출 트레이스, 토큰 비용, 지연 시간을 실시간으로 모니터링. (예: AgentOps, Langfuse) -* **[[Data Lineage (데이터 리니지)]]**: 에이전트가 참조하는 데이터의 출처와 변경 이력을 추적. 컨텍스트 압축 과정에서의 정보 유실 및 오염된 데이터 주입을 방지한다. -* **[[OpenTelemetry (OTEL)]]**: 분산 트레이싱 표준을 에이전트 워크플로우에 적용하여 엔드투엔드 가시성을 확보한다. +### 3. 심층 관측성 및 진단 (Deep Observability) +* **AI 기반 디버깅**: 방대한 트레이스에서 근본 원인을 찾아내는 **Polly**나 인과 그래프를 분석하는 **AgentTrace** 등의 도구 도입 [11]. +* **시각화 및 스태핑**: 다중 턴 에이전트의 실패를 추적하기 위한 **AgentPrism**, **AgentStepper**와 같은 인터랙티브 디버깅 도구 [11, 15]. +* **에이전트 분석 (Agent Analytics)**: 트레이스 데이터를 쿼리 가능한 분석 데이터로 취급하는 **BigQuery Agent Analytics** 기반 인프라 [4]. ## ⚖️ Trade-offs & Caveats -* **사후 관측 vs 사전 방어**: Observability 도구는 실행 후의 행동을 추적하지만, 데이터 리니지 및 거버넌스는 오염된 데이터가 컨텍스트에 주입되는 것을 사전에 예방하는 데 중점을 둔다. -* **격리 수준과 성능**: MicroVM은 Docker보다 보안성이 높지만 기동 속도와 리소스 오버헤드가 더 클 수 있다. -* **아키텍처 복잡성**: 인프라 계층이 두꺼워질수록 시스템의 전체 지연 시간(Latency)이 증가하며 운영 부담이 커진다. +* **사후 관측(Post-hoc)의 한계**: AgentOps나 Langfuse는 실행 후의 로그를 분석할 뿐, 오염된 입력 데이터(Bad inputs)로 인한 환각이나 실패를 사전에 방지하지는 못한다 [10, 18]. +* **성능 오버헤드**: 관측성 도구 및 샌드박스 계층 통합 시 시스템 실행 속도가 약 **12%~15% 저하**될 수 있다 [14, 22]. +* **운영 부담**: 보안을 위해 관측성 데이터를 자체 호스팅(Self-hosting)할 경우 시스템 유지 관리에 막대한 엔지니어링 리소스가 소요된다 [10]. ## 🔗 Knowledge Connections ### Related Concepts * **[[Agent Harness (에이전트 하네스)]]**: 이러한 인프라 구성 요소들을 통합하여 에이전트에게 실행 런타임을 제공하는 상위 계층. -* **[[Context Engineering (컨텍스트 엔지니어링)]]**: 인프라를 통해 수집된 데이터를 에이전트가 읽기 좋은 형태로 압축하고 주입하는 기술. -* **[[Security & Reliability (보안 및 신뢰성)]]**: 샌드박스와 거버넌스를 통해 달성하고자 하는 궁극적인 시스템 목표. +* **[[Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성)]]**: 사전 거버넌스를 통해 관측성의 한계를 보완하고 시스템 신뢰성을 확보하는 전략. -### Deeper Research Questions -* 컨텍스트 압축(Compaction) 시 데이터 출처(Provenance) 정보를 소실하지 않고 보존하는 최적의 메타데이터 설계 방식은? -* 실시간 데이터 계약(Data Contracts)과 리니지 정보를 결합하여 에이전트의 오염된 컨텍스트 학습을 사전 차단하는 파이프라인 구축 방안은? +### Practical Application Contexts +* **Debugging:** 원시 로그 분석 대신 AgentTrace와 같은 AI 진단 보조 도구를 활용하여 다중 턴 에이전트의 논리적 오류 지점을 식별한다. +* **Infrastructure:** 고위험 작업이 포함된 에이전트 미션은 Firecracker 기반 MicroVM 샌드박스를 강제하여 시스템 침투 가능성을 원천 차단한다. --- *Last updated: 2026-05-05* diff --git a/10_Wiki/Topics/04_Governance_Reliability/Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성).md b/10_Wiki/Topics/04_Governance_Reliability/Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성).md new file mode 100644 index 00000000..840bb4ef --- /dev/null +++ b/10_Wiki/Topics/04_Governance_Reliability/Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성).md @@ -0,0 +1,37 @@ +# [[Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성)]] + +## 📌 Brief Summary +거버넌스, 안전 및 신뢰성은 에이전틱 시스템이 조직의 정책을 준수하고, 외부 위협으로부터 안전하며, 예측 가능한 수준의 성능을 유지하도록 보장하는 제어 프레임워크이다 [1-3]. 이는 단순히 보안 설정을 넘어 데이터 거버넌스, 다단계 권한 승인, 그리고 시스템 수준의 격리 기술을 포괄한다 [4, 5]. + +## 📖 Core Content + +### 1. 데이터 및 도구 거버넌스 (Governance Substrate) +* **[[Data Governance (데이터 거버넌스)]]**: 에이전트가 읽는 데이터의 신뢰성, 최신성, 스키마 안정성을 사전에 검증하고 인증하는 계층 [1, 7]. +* **에이전트 카탈로그 및 정책**: 조직 내에서 허용된 에이전트와 도구의 목록을 관리하고, 실행 정책(Policy Enforcement)을 강제한다 [15, 16]. +* **데이터 리니지 추적**: 에이전트가 생성한 결과물의 원본 데이터를 추적하여 실패의 근본 원인이 모델인지, 데이터인지 명확히 식별한다 [14]. + +### 2. 에이전트 안전 및 권한 통제 (Safety & Permissions) +* **사전 작업 승인 (Pre-Action Authorization)**: 고위험 작업(파일 삭제, 대량 메일 발송 등) 수행 전 인간의 승인이나 별도의 검증 절차를 강제한다 [11, 21]. +* **다중 수준 권한 모드 (Multi-Level Permission Modes)**: 읽기 전용, 샌드박스 쓰기, 제한적 네트워크 접근 등 작업 성격에 따른 세밀한 권한 제어를 적용한다 [12, 21]. +* **[[Guardrails (가드레일)]]**: 에이전트의 출력이 윤리적 가이드라인이나 비즈니스 로직을 벗어나지 않도록 실시간으로 필터링하고 교정한다 [13, 14]. + +### 3. 시스템 신뢰성 및 격리 (Reliability & Isolation) +* **심층 방어 (Defense-in-depth)**: 커널 수준의 격리(Firecracker), 네트워크 차단, RBAC 등을 결합하여 에이전트가 침투 도구로 악용되는 것을 원천 차단한다 [7, 22]. +* **보안 감사 (Security & Audit)**: 모든 사고 과정과 도구 호출 이력을 불변의 로그로 기록하여 사후 사고 조사가 가능하도록 지원한다 [4, 11]. + +## ⚖️ Trade-offs & Caveats +* **엄격한 통제 vs 자율성**: 거버넌스와 권한 통제가 너무 엄격할 경우 에이전트의 문제 해결 능력이 제한되고 생산성이 저하될 수 있다 [22]. +* **사전 예방 vs 사후 분석**: 데이터 거버넌스는 사전 예방에 집중하지만 이를 구축하는 비용이 크며, 관측성 도구는 사후 분석에 유리하지만 이미 발생한 실패를 막지 못한다 [10, 18]. + +## 🔗 Knowledge Connections + +### Related Concepts +* **[[Agent Harness (에이전트 하네스)]]**: 하네스의 L-component가 이 거버넌스 및 안전 정책을 실제로 집행하는 계층이다. +* **[[Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성)]]**: 보안 사고 발생 시 원인을 추적하기 위한 트레이스 데이터를 제공한다. + +### Practical Application Contexts +* **Enterprise Deployment:** 기업 내부망에서 에이전트를 운영할 때는 데이터 거버넌스 기판과 사전 작업 승인 절차가 필수적이다. +* **High-Risk Automation:** 금융 거래나 시스템 설정 변경과 같은 고위험 작업에서는 다중 수준 권한 모드와 가드레일을 통해 위험을 관리한다. + +--- +*Last updated: 2026-05-05* diff --git a/10_Wiki/Topics/AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처).md b/10_Wiki/Topics/AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처).md new file mode 100644 index 00000000..c67cabec --- /dev/null +++ b/10_Wiki/Topics/AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처).md @@ -0,0 +1,37 @@ +# [[AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처)]] + +## 📌 Brief Summary +AI 추론 및 검색 아키텍처는 에이전트가 주어진 문제를 해결하기 위해 지식을 검색(Retrieval)하고 논리적으로 추론(Reasoning)하는 과정의 구조적 설계이다 [1, 2]. 단순한 RAG(Retrieval-Augmented Generation)를 넘어, 다중 에이전트 협업, 추론 예산 관리, 그리고 복합적인 지식 융합을 통해 문제 해결의 정확도와 효율성을 극대화한다 [3, 4]. + +## 📖 Core Content + +### 1. 추론 메커니즘 (Reasoning Frameworks) +* **[[Multi-Agent Orchestration]]**: LangGraph, CrewAI 등을 활용하여 복잡한 작업을 작은 단위로 쪼개고 여러 에이전트가 협업하도록 조율 [8, 9]. +* **추론 예산 (Reasoning Budget)**: 무한 루프를 방지하고 비용 효율성을 위해 토큰 및 시간 단위의 추론 예산을 설정하고 관리 (예: Token Savior) [11, 12]. +* **L3 Meta-Factory**: 에이전트의 워크플로우와 추론 단계를 동적으로 생성하고 최적화하는 상위 메타 계층 [6, 15]. + +### 2. 고급 검색 기술 (Advanced Retrieval) +* **지식 합성 및 융합**: 파편화된 검색 결과들을 하나로 합쳐 고밀도의 컨텍스트로 재구성하는 과정 [3, 7]. +* **LLM-as-judge**: 검색된 정보의 관련성과 정확성을 모델이 스스로 평가하여 최적의 정보만 추론에 활용하도록 필터링 [13]. +* **하이브리드 검색**: 키워드 기반 BM25와 의미론적 벡터 검색을 결합하여 정보 검색의 재현율과 정확도를 동시에 확보 [14]. + +### 3. 운영 및 최적화 (LLMOps) +* **[[LLMOps]]**: 에이전트 추론 파이프라인의 배포, 모니터링, 버전 관리를 위한 운영 체계 [16]. +* **피드백 루프**: 실행 결과에 대한 QA 에이전트의 피드백을 기반으로 추론 전략이나 프롬프트를 실시간으로 교정(Self-correction) [13, 14]. + +## ⚖️ Trade-offs & Caveats +* **추론 깊이 vs 지연 시간**: 추론 단계가 복잡해지고 다중 에이전트 협업이 늘어날수록 문제 해결의 정확도는 높아지지만 반응 속도(Latency)는 희생된다 [22]. +* **오케스트레이션 복잡성**: 너무 많은 에이전트가 개입할 경우 제어 지점이 분산되어 디버깅이 어려워지고 시스템 복잡도가 기하급수적으로 증가한다 [10]. + +## 🔗 Knowledge Connections + +### Related Concepts +* **[[Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리)]]**: 검색된 지식을 메모리에 저장하고 효율적으로 인출하기 위한 기반 기술이다. +* **[[Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성)]]**: 복잡한 추론 트레이스를 관측하고 디버깅하기 위한 인프라 기능을 제공한다. + +### Practical Application Contexts +* **Complex Problem Solving:** 수십 단계의 추론이 필요한 엔지니어링 작업에서는 Reasoning Budget 관리와 다중 에이전트 조율이 필수적이다. +* **Enterprise Search:** 방대한 사내 지식을 활용할 때는 하이브리드 검색과 LLM-as-judge를 통해 정보의 신뢰성을 담보한다. + +--- +*Last updated: 2026-05-05* diff --git a/10_Wiki/Topics/Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리).md b/10_Wiki/Topics/Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리).md new file mode 100644 index 00000000..27c23363 --- /dev/null +++ b/10_Wiki/Topics/Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리).md @@ -0,0 +1,37 @@ +# [[Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리)]] + +## 📌 Brief Summary +에이전트 컨텍스트 및 메모리 관리는 제한된 토큰 윈도우 내에서 에이전트(LLM)가 작업의 일관성을 유지하고, 과거의 경험과 외부 지식을 효율적으로 활용할 수 있도록 돕는 핵심 메커니즘이다 [1, 2]. 이는 단순한 데이터 주입을 넘어, 컨텍스트의 압축, 부패 방지, 그리고 동적인 메타데이터 관리를 포함하는 고도의 엔지니어링 영역이다 [3, 4]. + +## 📖 Core Content + +### 1. 컨텍스트 엔지니어링 및 최적화 +* **컨텍스트 조립 (Context Assembly)**: 액티브 메타데이터(Active Metadata)를 기반으로 현재 작업에 가장 관련성 높은 정보를 동적으로 선별하여 주입 [3, 5]. +* **컨텍스트 압축 (Context Compression)**: 정보의 밀도를 유지하면서 토큰 사용량을 줄이는 기술. 요약(Summarization) 또는 소프트 프롬프트 압축 기술이 활용된다 [8, 9]. +* **데이터 계약 (Data Contracts)**: 컨텍스트 주입 전 스키마 안정성을 검증하여 스키마 드리프트(Schema Drift)로 인한 에이전트의 오작동을 방어한다 [10]. + +### 2. 메모리 아키텍처 (Memory Layering) +* **단기 메모리 (Short-term/Working Memory)**: 현재 세션의 트레이스와 중간 결과물을 저장. 주로 벡터 DB나 로컬 캐시를 활용한다 [11]. +* **장기 메모리 (Long-term/Episodic Memory)**: 과거의 성공/실패 사례와 지식을 보관. 에이전트가 시간이 지날수록 학습하고 발전하는 기반이 된다 [12]. +* **상태 보존 (Checkpointing)**: 긴 실행 시간을 요구하는 딥 에이전트(Deep Agents)의 경우, 각 단계별 상태를 체크포인트로 저장하여 오류 발생 시 복구 지점을 제공한다 [11, 14]. + +### 3. 컨텍스트 품질 관리 +* **컨텍스트 부패 (Context Rot) 방지**: 다단계 작업 중 발생하는 정보 누락과 출처(Provenance) 손실을 막기 위해 원본 리니지 정보를 메타데이터로 유지한다 [20]. +* **최신성(Recency) 및 신뢰성 검증**: 주입되는 데이터가 최신 인증 상태(Certification Status)인지 확인하여 오래된 정보로 인한 환각을 차단한다 [1, 7]. + +## ⚖️ Trade-offs & Caveats +* **압축 vs 정보 손실**: 컨텍스트를 과도하게 압축할 경우 중요한 세부 사항이나 데이터 간의 미묘한 관계가 소실될 수 있다 [21]. +* **메모리 관리 비용**: 복잡한 메모리 레이어링과 체크포인팅 시스템 구축은 인프라 자원과 운영 리소스를 추가로 요구한다 [22]. + +## 🔗 Knowledge Connections + +### Related Concepts +* **[[Agent Harness (에이전트 하네스)]]**: 하네스의 C-component와 S-component가 이 메모리 관리 기능을 수행하는 물리적 주체이다. +* **[[AI Reasoning & Retrieval Architectures (AI 추론 및 검색 아키텍처)]]**: 저장된 메모리와 외부 지식을 어떻게 효과적으로 검색하고 추론에 활용할 것인가를 다룬다. + +### Practical Application Contexts +* **Long-running Tasks:** 수일간 지속되는 프로젝트형 작업에서는 체크포인팅과 액티브 메타데이터 관리를 통해 에이전트의 '기억 상실'을 방지한다. +* **Quality Assurance:** 데이터 계약과 리니지 추적을 결합하여 에이전트가 생성한 결과물의 데이터 소스가 신뢰할 수 있는지 상시 검증한다. + +--- +*Last updated: 2026-05-05* diff --git a/10_Wiki/Topics/Agent Harness.md b/10_Wiki/Topics/Agent Harness.md index 1bd2b321..5e1020ea 100644 --- a/10_Wiki/Topics/Agent Harness.md +++ b/10_Wiki/Topics/Agent Harness.md @@ -1,45 +1,43 @@ # [[Agent Harness (에이전트 하네스)]] ## 📌 Brief Summary -Agent Harness는 에이전트(LLM)가 독립적으로 동작하지 않고, 시스템 자원(파일, 네트워크, 도구)에 접근하고, 상태를 유지하며, 외부와 소통할 수 있도록 감싸는 **'실행 런타임이자 거버넌스 계층'**이다. 에이전트에게는 외부 세계와 소통하는 인터페이스를 제공하고, 시스템에게는 에이전트의 행동을 통제하고 관찰하는 보안 및 운영 경계를 제공한다. 최근에는 이를 **'Agent OS'**라고도 부른다. +Agent Harness는 에이전트(LLM)가 독립적으로 동작하지 않고, 시스템 자원(파일, 네트워크, 도구)에 접근하고, 상태를 유지하며, 외부와 소통할 수 있도록 감싸는 **'실행 런타임이자 거버넌스 계층'**이다 [1-3]. 에이전트에게는 외부 세계와 소통하는 인터페이스를 제공하고, 시스템에게는 에이전트의 행동을 통제하고 관찰하는 보안 및 운영 경계를 제공한다 [4, 5]. 최근에는 이를 **'Agent OS'** 또는 하네스가 에이전트의 역량을 증폭시킨다는 의미에서 **'Harness Multiplier'**라고도 부른다 [1, 6]. ## 📖 Core Content -* **6대 구성 요소 (Standard Architecture)**: - * **[[C-component (Context Manager)]]**: 컨텍스트 조립, 우선순위 할당 및 압축 관리. - * **[[E-component (Execution Loop)]]**: 에이전트의 사고-행동-관찰(ReAct) 반복 루프 제어. - * **[[L-component (Lifecycle Hooks)]]**: 이벤트 인터셉터, 정책 강제(Policy Enforcement) 및 권한 제어 계층. - * **[[S-component (State Store)]]**: 단기/장기 메모리, 체크포인트 및 지식 지속성 관리. - * **[[T-component (Tool Registry)]]**: 외부 도구 연결 표준화(MCP 등) 및 실행 보안 관리. - * **[[V-component (Evaluation Interface)]]**: 결과의 논리적 무결성 검증 및 자가 수정 피드백 루프. -* **시스템 자원 추상화 및 격리**: 에이전트가 호스트 OS API를 직접 호출하는 대신, 하네스가 제공하는 가상화된 파일 시스템과 [[Sandbox (샌드박스)]] 환경을 통해 안전하게 상호작용한다. -* **관측 가능성 (Observability)**: 에이전트의 사고 과정(Thought), 도구 호출 로그, 데이터 흐름을 실시간으로 추적하여 디버깅 및 보안 감사를 수행한다. +* **하네스 아키텍처 (Standard Substrate)**: + * **[[C-component (Context Manager)]]**: 액티브 메타데이터를 기반으로 컨텍스트를 조립하고, 토큰 제약을 극복하기 위한 압축 및 우선순위 관리 수행 [3, 8]. + * **[[E-component (Execution Loop)]]**: **[[Ralph Loop]]**(사고-행동-관찰-평가) 또는 **[[Reasoning Loop]]**를 통해 에이전트의 추론 단계를 세밀하게 제어 [9, 10]. + * **[[L-component (Lifecycle Hooks)]]**: 사전 작업 권한 승인(Pre-Action Authorization), 이벤트 인터셉터 및 정책 강제 계층 [1, 11]. + * **[[S-component (State Store)]]**: 체크포인팅(Checkpointing)을 통한 상태 보존 및 장기 메모리의 지속성 관리 [11, 12]. + * **[[T-component (Tool Registry)]]**: [[MCP (Model Context Protocol)]] 표준을 통한 도구 연결 및 보안 격리된 실행 환경 제공 [12, 13]. + * **[[V-component (Evaluation Interface)]]**: LLM-as-judge를 활용한 논리적 무결성 검증 및 자가 수정 피드백 [13, 14]. + * **추론 예산 (Reasoning Budget)**: 무한 루프를 방지하고 비용 효율성을 위해 토큰 및 시간 단위의 추론 예산을 설정하고 관리 (예: Token Savior) [11, 12]. +* **L3 Meta-Factory**: 에이전트의 워크플로우와 추론 단계를 동적으로 생성하고 최적화하는 상위 메타 계층 [6, 15]. +* **둠 루프 (Doom Loop) 감지**: 에이전트가 작동하지 않는 접근 방식을 끝없이 반복할 때, 하네스 계층의 **LoopDetectionMiddleware**가 이를 감지하고 계획을 재고(Reconsidering)하도록 강제 지침을 주입한다 [1, 5]. +* **하네스 서비스화 (HaaS, Harness-as-a-Service)**: 에이전트 실행 환경을 클라우드 기반의 표준화된 서비스로 제공하여 인프라 구축 부담을 최소화하는 방식 [6, 16]. +* **데이터 거버넌스 기판**: 대부분의 프레임워크가 놓치는 '데이터 품질'을 관리하기 위해, 입력 데이터의 리니지(Lineage)를 추적하고 인증 상태를 검증하는 계층 [1, 7]. +* **공진화 (Co-evolution)**: 모델의 훈련 과정과 하네스 설계가 상호작용하며 발전하는 현상. 최신 모델은 하네스를 루프에 포함하여 사후 훈련(post-trained)을 진행하며, 이는 인간과 에이전트가 상호 학습하며 개선되는 팀워크 플랫폼의 기반이 된다 [1, 2]. ## ⚖️ Trade-offs & Caveats -* **추상화 오버헤드**: 하네스 계층(미들웨어, 샌드박스)이 복잡해질수록 에이전트의 반응 속도(Latency)가 저하될 수 있다. -* **데이터 무결성 검증의 한계**: 대다수의 프레임워크는 실행 흐름은 통제하지만, 주입되는 소스 데이터의 무결성(Data Integrity)을 보장하지 못해 오답이 자신감 있게 도출될 위험이 있다. -* **컨텍스트 부패 (Context Rot)**: 다단계 작업 시 정보 누적으로 인한 망각이 발생하며, 이를 막기 위한 요약(Compaction) 과정에서 맥락과 출처(Provenance)가 손실될 수 있다. -* **하네스 오버피팅**: 특정 하네스 시스템의 도구 구조에 모델이 과도하게 적응하여 범용성이 저하되는 현상이 나타날 수 있다. +* **공진화의 경고 (Co-evolution Warning)**: 특정 하네스 환경에 모델이 과적합(Overfitting)되어, 도구의 로직이 조금만 바뀌어도 성능이 급격히 저하되는 일반화 능력 결여 문제를 초래할 수 있다 [1, 3, 5]. +* **운영 부담 (Operational Burden)**: 하네스 인프라(샌드박스, 관측 도구 등)를 자체 호스팅(Self-hosting)할 경우, 소규모 팀에게는 막대한 시스템 유지 관리 비용이 발생한다 [10, 17]. +* **연쇄적 실패 (Cascading Failures)**: 하네스 계층에서 데이터 무결성 검증이 부재할 경우, 잘못된 소스 데이터가 에이전트의 사고 과정을 오염시켜 전체 미션의 실패로 이어진다 [1, 18]. +* **컨텍스트 부패 (Context Rot)**: 다단계 추론 과정에서 정보가 압축될 때 핵심 맥락과 출처(Provenance)가 손실되어, 에이전트가 '자신감 있는 오답'을 도출할 위험이 있다 [20, 21]. +* **성능 오버헤드**: 보안 격리 및 관측성 도구 통합 시 시스템 실행 속도가 약 12~15% 저하될 수 있다 [14, 22]. ## 🔗 Knowledge Connections ### Related Concepts -* [[Agent Loop (에이전트 루프)]] - * 연결 이유: 하네스 내부에서 모델이 사고와 행동을 반복하게 만드는 핵심 실행 엔진 구조이다. -* [[Context Engineering (컨텍스트 엔지니어링)]] - * 연결 이유: 토큰 한계 극복을 위한 데이터 주입, 압축 및 프롬프트 캐싱 기술이 하네스의 성능을 결정한다. -* [[Model Context Protocol (MCP)]] - * 연결 이유: 하네스 내부 에이전트가 외부 도구 및 데이터 소스와 통신하기 위한 표준 프로토콜이다. -* [[Human-in-the-Loop (HITL)]] - * 연결 이유: 고위험 작업 전 인간의 승인을 강제하여 자율 시스템의 안전성을 담보하는 거버넌스 장치이다. - -### Deeper Research Questions -* 상태 비저장(Stateless) LLM이 장기 작업 중 직면하는 'AI 기억상실' 문제를 하네스의 메모리 시스템은 어떻게 구조적으로 극복하는가? -* 오케스트레이션 프레임워크의 '실행 제어'와 데이터 솔루션의 '품질 거버넌스'를 단일 하네스 아키텍처 내에서 결합하는 방법은 무엇인가? -* 무한 루프(Doom Loop)에 빠진 에이전트를 하네스가 감지하고 스스로 복구(Self-healing)하도록 유도하는 피드백 루프의 설계 원리는? +* [[Agentic Infrastructure & Observability (에이전틱 인프라 및 관측 가능성)]] + * 연결 이유: 하네스 내부에서 발생하는 에이전트의 사고와 행동을 트레이싱하고 디버깅하기 위한 필수 기반 시설이다. +* [[Agent Context & Memory Management (에이전트 컨텍스트 및 메모리 관리)]] + * 연결 이유: 하네스의 S-component가 상태를 유지하고 C-component가 데이터를 조립하는 핵심 메커니즘을 다룬다. +* [[Governance, Safety & Reliability (거버넌스, 안전 및 신뢰성)]] + * 연결 이유: 에이전트의 자율적 행동이 조직의 정책을 벗어나지 않도록 통제하는 하네스의 핵심 제어 원칙이다. ### Practical Application Contexts -* **Implementation:** LangChain, CrewAI 등을 기반으로 MCP를 통해 사내 도구를 연동하고, Docker 기반의 샌드박스를 래핑하여 프로덕션 환경을 구축한다. -* **Operation:** 하네스에 통합된 Observability 도구(AgentOps 등)를 통해 실행 트레이스를 모니터링하고, 반복되는 오류를 규칙 갱신을 통해 교정(Steering)한다. +* **Implementation:** Docker/Firecracker microVM 기반의 [[Sandbox (샌드박스)]]를 하네스에 래핑하여 에이전트의 코드 실행 환경을 물리적으로 격리한다. +* **Operation:** AgentOps 또는 Langfuse를 연동하여 실시간 트레이스를 분석하고, 실패 지점의 데이터를 역추적하여 프롬프트나 데이터 소스를 교정한다. --- *Last updated: 2026-05-05* diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AG-UI Protocol.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AG-UI Protocol.md new file mode 100644 index 00000000..407c3e97 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AG-UI Protocol.md @@ -0,0 +1,16 @@ +# [[AG-UI Protocol]] + +## 📌 Brief Summary +AG-UI(Streaming event format) 프로토콜은 AI 에이전트가 프론트엔드 애플리케이션과 연결되는 방식을 표준화하는 경량 이벤트 기반 프로토콜이다 [1, 2]. 공유 이벤트 버스(Shared event bus)를 통해 실시간 상태 업데이트 스트리밍, 도구 호출 렌더링, 그리고 HITL(Human-in-the-Loop) 인터럽트 등의 기능을 제공한다 [2]. 도구 연결을 위한 MCP나 에이전트 간 통신을 위한 A2A 프로토콜이 설계상 다루지 못했던 실시간 '에이전트-UI' 통신 영역의 간극을 채우기 위해 고안되었다 [1, 2]. + +## 📖 Core Content +* **프론트엔드 연결 표준화:** AG-UI 프로토콜은 에이전트가 시스템 경계를 넘어 애플리케이션의 사용자 인터페이스(UI)와 통신해야 할 때 선택할 수 있는 스트리밍 이벤트 포맷이다 [1]. +* **에이전트 통신 생태계에서의 위치:** AI 에이전트 상호운용성을 위한 프로토콜 생태계 내에서, AG-UI는 MCP(도구 및 데이터 연결)와 A2A(에이전트 간 라우팅) 사이의 층(Layer)을 채워주는 역할을 한다 [1, 2]. 기존 프로토콜들만으로는 실시간 에이전트-UI 통신이 어려웠던 점을 해결하는 데 특화되어 있다 [2]. +* **핵심 작동 메커니즘:** 공유 이벤트 버스 위에서 동작하며, 프론트엔드 애플리케이션으로 에이전트의 현재 상태를 실시간으로 스트리밍하거나 도구 호출 내역을 렌더링하도록 돕는다 [2]. 또한 사람이 의사결정에 개입해야 하는 HITL(Human-in-the-Loop) 상황에서 인터럽트 신호를 처리하는 기능도 담당한다 [2]. +* **플랫폼 도입 사례:** 클라우드 네이티브 에이전트 호스팅 플랫폼 등에서 실제 인프라 계층으로 통합되고 있다. 일례로 완전 관리형 에이전트 배포 플랫폼인 'Amazon Bedrock AgentCore'는 실시간 에이전트-프론트엔드 스트리밍을 지원하기 위해 AG-UI 프로토콜을 지원하고 있다 [3]. + +## ⚖️ Trade-offs & Caveats +소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AI Observability.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AI Observability.md new file mode 100644 index 00000000..10d1941b --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AI Observability.md @@ -0,0 +1,18 @@ +# [[AI Observability]] + +## 📌 Brief Summary +AI Observability(AI 관측성)는 배포된 AI 에이전트의 상태, 추론 과정, 도구 사용, 지연 시간 및 비용 등을 모니터링하고 추적하는 인프라 및 실무 관행이다 [1-3]. 이는 에이전트의 실행 세션을 기록하고 재현함으로써 복잡한 다중 에이전트 워크플로우나 장기 실행 작업에서 발생하는 실패의 근본 원인을 진단할 수 있게 해준다 [2, 4]. 필수적인 시스템 인프라이지만, 입력 데이터의 결함을 사전에 차단하는 것이 아니라 사후(post-hoc)에 문제를 포착한다는 특징을 가진다 [5-7]. + +## 📖 Core Content +* **주요 역할 및 기능:** AI 관측성 도구는 세션 리플레이, LLM 호출 비용, 지연 시간(Latency), 도구 사용 내역 및 동시 실행 에이전트 간의 상호 작용을 추적한다 [1, 2]. 이를 통해 엔지니어는 숨겨진 프롬프트 없이 파이프라인 로그에서 전체 추론 체인을 확인하고, 에이전트가 무엇을 보고 결정했는지 정확히 검사하여 포렌식(Forensic) 수준의 고장 분석을 수행할 수 있다 [2, 3]. 또한 추적(Trace) 데이터는 에이전트가 스스로를 평가하고 오류를 수정하기 위한 디버깅의 피드백 신호로도 활용된다 [8, 9]. +* **관측성 도구 및 프레임워크 생태계:** 대표적인 도구로는 배포 후 세션 모니터링을 위한 AgentOps [1], 자체 호스팅(Self-hosted)이 가능한 오픈소스 LLMOps 플랫폼 Langfuse [10] 등이 있다. 이 외에도 OpenTelemetry 기반의 계측을 제공하는 OpenLLMetry, 로컬 추적 UI인 Arize Phoenix, 비용 및 토큰 모니터링 프록시 Helicone, SQL 쿼리형 추적 데이터를 제공하는 Pydantic Logfire, 전체 트레이스 검색을 지원하는 Braintrust 등 다양한 도구들이 에이전트 관측성을 위해 사용된다 [4]. +* **대규모 트레이스 분석의 진화:** 장기간 실행되는 에이전트는 인간이 수동으로 스캔할 수 없는 방대한 분량의 트레이스를 생성한다 [11]. 이를 해결하기 위해 추적 데이터를 분석하여 근본 원인을 찾아내는 AI 어시스턴트(예: Polly)나, 오류의 근본 원인을 식별하는 인과 그래프 분석(AgentTrace) 등의 AI 기반 디버깅 도구가 도입되고 있다 [11]. 더 나아가 Google Cloud의 BigQuery Agent Analytics와 같이 트레이스와 도구 호출을 단순한 대시보드 로그가 아닌 쿼리 가능한 분석 데이터(Analytical data) 자체로 취급하는 인프라도 등장했다 [4]. + +## ⚖️ Trade-offs & Caveats +* **사후 대응(Post-hoc)의 한계:** 관측성 도구의 가장 큰 제약은 에이전트가 실행된 후 작동하는 사후 도구라는 점이다 [7, 12]. 세션 기록을 통해 에이전트의 잘못된 행동을 포착할 수는 있지만, 오래되거나 인증되지 않은 데이터, 스키마가 변경된 데이터 등 '잘못된 입력(Bad inputs)'으로 인해 발생하는 근본적인 실패를 사전에 방지하지는 못한다 [6, 7, 13]. 따라서 잘못된 데이터 입력에 기반한 결과물임에도 모델 출력 평가 점수가 높게 나오는 착시 현상이 발생할 수 있다 [6]. +* **성능 오버헤드:** AgentOps나 Langfuse와 같은 관측성 도구를 에이전트 하네스 파이프라인에 통합할 경우, 시스템 실행 시 약 12%에서 15% 정도의 성능 오버헤드(Performance overhead)가 발생한다 [2, 14]. +* **운영 부담 (Operational Burden):** 관측성 데이터의 벤더 종속(Vendor lock-in)을 피하거나 내부 보안을 유지하기 위해 Langfuse와 같은 도구를 자체 호스팅(Self-hosting)하는 경우, 소규모 팀에게는 시스템 인프라를 유지 관리해야 하는 추가적인 운영 부담이 가중된다 [10, 14]. +* **정보 과부하 및 인지적 부담:** 수 분에 걸쳐 수백 개의 단계를 수행하는 딥 에이전트(Deep agents)의 경우 거대한 로그를 남기기 때문에 시각화 도구(예: AgentPrism, AgentStepper)나 AI 진단 보조 없이 원시 로그만으로 다중 턴 에이전트의 실패를 사람이 직접 디버깅하는 것은 불가능에 가깝다 [11, 15]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/API Gateway.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/API Gateway.md new file mode 100644 index 00000000..364b186c --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/API Gateway.md @@ -0,0 +1,16 @@ +# [[API Gateway]] + +## 📌 Brief Summary +에이전트 하네스 아키텍처에서 API 게이트웨이(또는 LLM/MCP 게이트웨이)는 AI 에이전트와 다중 LLM 제공자 및 외부 서비스 사이의 요청을 중재하고 제어하는 핵심 인프라 계층입니다 [1-3]. 이 계층은 요청 라우팅, 로드 밸런싱, 응답 캐싱, 콘텐츠 검사, 속도 제한(Rate limiting) 등의 기능을 수행합니다 [1-3]. 이를 통해 시스템은 에이전트의 과도한 리소스 사용을 막는 예산 가드레일을 강제하고, 도구 및 외부 시스템에 대한 안전한 접근을 보장할 수 있습니다 [4, 5]. + +## 📖 Core Content +* **다중 모델 라우팅 및 비용 최적화 (LLM Gateway):** OmniRoute와 같은 다중 제공자 LLM 게이트웨이는 인텔리전트 라우팅, 로드 밸런싱, 자동 대체(Fallback), 속도 제한, 응답 캐싱을 수행합니다 [2]. 단순한 작업은 저렴한 모델로, 복잡한 추론은 고성능 모델로 라우팅하여 토큰 비용을 40~60%가량 절감할 수 있습니다 [2]. Helicone의 AI Gateway 역시 코드 변경 없이 요청 라우팅과 캐싱 기능을 제공하여 비용 추적과 토큰 모니터링을 지원합니다 [1]. +* **보안 및 도구 접근 통제 (MCP/API Gateway):** 외부 도구 사용 시 Harness MCP Gateway는 외부 MCP 서버 호출을 프록시하고 필터링하여 허용 목록(Allow-listing) 적용, 속도 제한, 콘텐츠 검사를 활성화합니다 [3]. GitHub의 에이전트 워크플로우 또한 내부 보안 아키텍처의 일환으로 MCP 게이트웨이와 API 프록시를 활용하여 에이전트 실행 환경을 방어합니다 [6]. Amazon Bedrock AgentCore는 서버리스 런타임 환경에서 도구 접근을 위한 안전한 게이트웨이를 기본 제공합니다 [5]. +* **FinOps 및 예산 가드레일 강제:** 인프라 게이트웨이는 에이전트 서비스의 유닛 이코노믹스를 관리하기 위해 루프 및 단계 제한, 도구 호출 캡(Cap), 실행당 토큰 예산, Wall-clock 타임아웃, 이상 탐지가 포함된 테넌트별 예산 제한 등 5가지의 구체적인 예산 가드레일을 강제합니다 [4]. +* **개인용 에이전트 게이트웨이 (Personal Agent Gateway):** OpenHarness 기반의 개인용 에이전트 앱인 'ohmo'의 경우, 자체 워크스페이스 내에 `gateway.json`을 두어 선택된 LLM 프로바이더 프로필과 외부 채널(Telegram, Slack, Discord 등) 설정을 연결하고 관리하는 역할을 수행합니다 [7, 8]. + +## ⚖️ Trade-offs & Caveats +게이트웨이를 도입하면 보안과 운영 효율성이 크게 향상되지만, 인프라의 세션 관리 복잡성이 증가하는 제약이 있습니다 [1]. 예를 들어, MCP를 원격 서비스로 실행하기 위해 HTTP 전송을 사용할 경우, 상태를 유지해야 하는 세션 제약(예: `Mcp-Session-Id` 헤더 유지)이 로드 밸런서 환경이나 수평적 확장(Horizontal scaling) 구조와 충돌하는 현상이 발생합니다 [1]. 이 때문에 대규모 확장성을 위해서는 전송 계층(Transport layer)에서 세션 관리를 완전히 분리해야 하는 구조적 한계와 극복 과제가 존재합니다 [1]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Active Metadata.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Active Metadata.md new file mode 100644 index 00000000..40b5c482 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Active Metadata.md @@ -0,0 +1,17 @@ +# [[Active Metadata]] + +## 📌 Brief Summary +액티브 메타데이터(Active Metadata)는 AI 에이전트 하네스가 의존하는 데이터의 상태를 지속적으로 모니터링하고 최신 상태로 자동 유지하는 데이터 거버넌스 기능이다 [1]. 실시간 인증 상태, 스키마 상태, 데이터 최신화 신호 등을 구조화된 컨텍스트로 에이전트에게 제공하여, 에이전트가 데이터의 최신 여부를 추측하지 않도록 돕는다 [1]. 이를 통해 오래되거나 검증되지 않은 데이터 입력으로 인해 발생하는 에이전트의 오작동 및 환각 현상을 근본적으로 방지하는 역할을 한다 [1, 2]. + +## 📖 Core Content +* **실시간 데이터 상태 모니터링 및 제공**: 액티브 메타데이터는 데이터 시스템을 지속적으로 모니터링하여 메타데이터의 최신성을 자동으로 유지한다 [1]. 스키마의 상태, 실시간 인증(Certification) 상태, 데이터의 최신화(Freshness) 신호가 구조화된 컨텍스트 형태로 제공된다 [1]. 이를 통해 에이전트는 참조하는 테이블이나 데이터가 최신인지 스스로 추측할 필요가 없어진다 [1]. +* **하네스의 구조적 한계 보완**: 대부분의 에이전트 하네스 프레임워크는 에이전트가 '어떻게' 실행되는지를 제어하지만, 에이전트가 '무엇'을 읽는지에 대한 데이터의 무결성은 검증하지 못한다 [3]. 액티브 메타데이터는 이러한 하네스의 구조적 틈을 메워, 에이전트가 컨텍스트를 읽기 전에 데이터의 신뢰성을 결정하는 통제된 데이터 기반(Governed data substrate) 역할을 수행한다 [3, 4]. +* **MCP 서버를 통한 통합**: 액티브 메타데이터, 데이터 계약(Data contracts), 데이터 리니지 등의 정보는 MCP(Model Context Protocol) 서버를 통해 에이전트 하네스에 제공될 수 있다 [5]. 하네스는 MCP 인터페이스를 통해 이러한 구조화된 컨텍스트를 직접 쿼리할 수 있으므로, 하네스 자체에 별도의 거버넌스 로직을 구축하지 않아도 된다 [5]. + +## ⚖️ Trade-offs & Caveats +* **에이전트 제어 및 오케스트레이션 기능 부재**: 액티브 메타데이터를 제공하는 시스템(예: Atlan)은 그 자체로 에이전트를 오케스트레이션하거나, 메모리를 관리하거나, 에이전트 실행에 대한 가시성(Observability)을 제공하는 하네스 도구가 아니다 [6]. 따라서 이를 LangGraph나 CrewAI와 같은 프레임워크와 완전히 대체할 수 있는 도구로 비교하는 것은 범주 오류(Category error)이며, 반드시 별도의 오케스트레이션 및 제어 프레임워크와 결합하여 사용해야만 한다 [4, 6]. +* **도입 시점과 설계 부담**: 잘못된 입력 데이터로 인한 에이전트 오작동은 사후 디버깅만으로는 해결하기 어렵고 엔터프라이즈 환경에서 매우 빠르게 누적된다 [7]. 따라서 단순한 프로토타입 단계를 넘어설 경우, 하네스 프레임워크를 선정하는 초기 단계부터 액티브 메타데이터와 같은 데이터 품질 인프라를 함께 평가하고 도입해야 하는 설계상의 복잡성과 비용 부담이 존재한다 [7, 8]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Card Service Discovery.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Card Service Discovery.md new file mode 100644 index 00000000..e249ab7e --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Card Service Discovery.md @@ -0,0 +1,15 @@ +# [[Agent Card Service Discovery]] + +## 📌 Brief Summary +Agent Card Service Discovery는 구글(Google)의 오픈 에이전트 간 통신 프로토콜인 A2A(Agent-to-Agent)에서 에이전트 간 라우팅 및 서비스 검색을 위해 사용되는 메커니즘이다 [1]. 이는 다중 에이전트 하네스(Multi-agent harnesses) 환경에서 잘 알려진 URL(well-known URLs)을 통해 에이전트를 검색함으로써, 서로 다른 프레임워크 간의 상호 운용성을 지원하는 역할을 한다 [1]. + +## 📖 Core Content +* **A2A 프로토콜의 핵심 통신 기반**: Agent Card Service Discovery는 HTTP(S)/SSE 상의 JSON-RPC 통신과 결합하여 구글의 A2A 프로토콜을 구성하며, 에이전트 간의 작업(task), 메시지(message), 산출물(artifact) 통신 모델을 지원한다 [1]. +* **프레임워크 간 상호 운용성 표준**: 다중 에이전트 하네스 환경에서 에이전트들이 서로를 식별하고 라우팅할 수 있게 해주는 교차 프레임워크 에이전트 상호 운용성(cross-framework agent interoperability)의 새로운 표준으로 기능하고 있다 [1]. +* 소스에 관련 정보가 부족합니다. (Agent Card Service Discovery의 구체적인 구현 방식이나 상세 아키텍처에 대한 추가 정보는 제공된 소스에 존재하지 않습니다.) + +## ⚖️ Trade-offs & Caveats +소스에 관련 정보가 부족합니다. (이 주제와 관련된 기술적 선택의 부작용이나 최적화의 제약 사항, 반대 급부에 대한 정보는 제공된 소스에 존재하지 않습니다.) + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Debugging.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Debugging.md new file mode 100644 index 00000000..71c9c841 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Agent Debugging.md @@ -0,0 +1,18 @@ +# [[Agent Debugging]] + +## 📌 Brief Summary +에이전트 디버깅(Agent Debugging)은 자율형 AI 에이전트가 하네스 내에서 다단계 작업을 수행할 때 발생하는 실패를 식별, 분석 및 수정하는 방법론과 도구를 의미합니다. 에이전트의 작업은 수백 단계에 걸쳐 비결정론적으로 실행되므로, 기존의 단순한 프롬프트 조정 수준을 넘어 복잡한 실행 트레이스(Trace), 인과 관계 그래프, 상태 변화를 분석하는 방향으로 진화했습니다. 이를 위해 인터랙티브 시각화 도구, AI 기반 근본 원인 분석, 멀티 에이전트 협업 디버깅 루프 등이 활용되어 에이전트 시스템의 신뢰성을 높입니다. + +## 📖 Core Content +* **트레이스 기반 및 AI 지원 분석 (AI-Assisted Trace Analysis):** 에이전트는 장시간에 걸쳐 수많은 단계를 수행하며 방대한 트레이스 데이터를 생성하므로 사람이 수동으로 로그를 검사하는 것은 불가능에 가깝습니다 [1]. LangSmith와 같은 플랫폼은 AI 어시스턴트(예: Polly)를 활용해 거대한 트레이스를 분석하고 근본 원인을 파악합니다 [1]. AgentTrace는 LLM 추론에 의존하는 대신 인과 그래프(Causal Graph) 분석을 통해 실패의 근본 원인을 파악하며, 이를 하위로 전파되는 단순 증상과 구별합니다 [1]. +* **대화형 및 시각적 디버깅 환경 (Interactive & Visual Debugging):** AgentStepper는 에이전트의 실행 궤적을 대화형으로 구조화하여 단계별 실행(Step-through), 중단점(Breakpoint) 조작, 중간 궤적 검사를 가능하게 하여 개발자의 인지 부하를 크게 줄여줍니다 [2]. AgentPrism은 OpenTelemetry 트레이스 데이터를 트리 뷰, 타임라인, 시퀀스 다이어그램 등으로 시각화하며 [2], claude-devtools는 숨겨진 세션 내부를 재구성하여 턴(Turn)당 토큰 사용 내역과 하위 에이전트의 실행 트리를 제공합니다 [1]. +* **체계적 및 제약 기반 진단 (Systematic & Constraint-Based Diagnosis):** AgentRx 프레임워크는 도구 스키마에서 제약 조건을 합성하고 이를 기반으로 진단하여 수동 로그 검사를 체계적인 자동 근본 원인 분석으로 전환합니다 [1]. `Syncause/debug-skill`은 에이전트가 무작정 수정안을 시도("patch and pray")하는 대신, 런타임 환경의 데이터(스택 트레이스 등)를 반드시 인용하여 증거 기반으로 복구하도록 강제합니다 [1]. +* **멀티 에이전트 협업 디버깅 (Collaborative Multi-Agent Debugging):** TraceCoder는 계측 에이전트(Instrumentation Agent), 과거 실패 사례를 학습하는 분석 에이전트(Analysis Agent), 수정 에이전트(Repair Agent)로 구성된 다중 에이전트 협업 루프를 통해 생성된 코드의 디버깅을 자동화합니다 [1]. 또한 AutoGen 프레임워크는 격리된 코드 샌드박스 내에서 에이전트 간의 다중 턴 토론 및 검토를 통한 반복적 디버깅 패턴을 지원합니다 [3, 4]. + +## ⚖️ Trade-offs & Caveats +* **사후 분석의 한계 (Post-hoc Limitation):** AgentOps나 Langfuse와 같은 대다수의 관측성 및 디버깅 도구는 배포 이후 에이전트가 실행된 다음(Post-hoc)에 실패를 기록하고 포착합니다 [5-7]. 즉, 스키마 변형이나 검증되지 않은 소스의 잘못된 입력 데이터로 인해 발생한 근본적인 장애를 사전에 방지하지 못하며, 불량 데이터를 바탕으로 모델이 자신만만하게 내놓은 오답이 출력 평가에서 높은 점수를 받는 오도된 결과를 낳을 수 있습니다 [6, 7]. +* **성능 오버헤드 (Performance Overhead):** 프로덕션 에이전트 스택에 세션 트래킹 및 LLMOps 가시성을 통합할 경우 성능 저하가 발생합니다. 예를 들어 AgentOps는 약 12%, Langfuse는 약 15%의 성능 오버헤드를 수반합니다 [8-10]. +* **무한 루프 및 분산 시스템의 복잡성 (Infinite Loops & Distributed Complexity):** 대화형 에이전트 디버깅 구조(예: AutoGen)에서는 두 에이전트가 좁은 시야에 갇혀 끊임없이 무의미한 시도를 반복하는 "파멸 루프(doom loops)"나 무한 루프에 빠지는 알려진 장애 모드가 존재하며, 이를 벗어나기 위해 인간의 수동 개입이나 강제 종료가 필요할 수 있습니다 [4, 11]. 또한 여러 라우팅 에이전트, 특수 에이전트, 외부 MCP 서버가 얽힌 환경에서의 트레이싱은 디버깅을 복잡한 분산 시스템 문제로 변모시킵니다 [12]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentCore.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentCore.md new file mode 100644 index 00000000..20f3c4ef --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentCore.md @@ -0,0 +1,17 @@ +# [[AgentCore]] + +## 📌 Brief Summary +AgentCore(Amazon Bedrock AgentCore)는 AWS에서 제공하는 완전 관리형 에이전트 배포 플랫폼이자 하네스 인프라이다 [1, 2]. 사용자가 모델, 시스템 프롬프트, 도구, 메모리 설정 등을 구성(Configuration)으로 선언하기만 하면, 자체적인 프로비저닝 없이도 독립된 마이크로 가상 머신(microVM) 환경에서 구동되는 에이전트를 자동으로 구축해 주는 '에이전트 팩토리(Agent Factory)' 역할을 수행한다 [3, 4]. + +## 📖 Core Content +* **아키텍처 및 런타임**: 사용자가 구성을 제출하면 AgentCore 하네스는 AWS의 오픈소스 에이전트 하네스 SDK인 'Strands Agents'를 내부적으로 조립하여 에이전트를 실행한다 [5, 6]. 조립된 에이전트는 전용 CPU, 메모리, 파일 시스템 및 셸(Shell)을 갖춘 격리된 마이크로VM에서 실행되므로, 세션 간 데이터 유출을 완벽히 방지한다 [4, 7]. +* **모델 및 도구 유연성**: Amazon Bedrock, OpenAI, Google Gemini 모델을 지원하며, 동일한 세션 중에도 컨텍스트를 잃지 않고 모델 제공자를 전환할 수 있다 [7, 8]. 도구 측면에서는 브라우저 및 코드 인터프리터를 기본으로 내장하고 있으며, MCP(Model Context Protocol) 서버, AgentCore Gateway 및 사용자 정의 인라인 도구를 설정 변경만으로 쉽게 연결할 수 있다 [7, 9, 10]. +* **스킬(Skills) 주입**: 개발자가 복잡한 오케스트레이션 로직을 작성할 필요 없이, 마크다운(Markdown) 지시문과 스크립트 번들로 구성된 '스킬'을 패키징하여 에이전트에게 특정 API 사용법이나 워크플로우 같은 도메인 지식을 필요에 따라 제공할 수 있다 [7, 10]. +* **실시간 통신 및 평가 인프라**: 음성 에이전트 등 지연 시간이 중요한(sub-800ms) 실시간 상호작용을 위해 피어투피어(P2P) UDP 기반의 WebRTC 양방향 스트리밍과 AG-UI 프로토콜을 지원한다 [1, 11]. 또한 'Amazon Bedrock AgentCore Evaluations'를 통해 에이전트의 궤적 채점, 작업 완료 검사 등의 평가(Eval)를 단순한 오프라인 벤치마크가 아닌 런타임 컨트롤 플레인의 인프라 서비스로 제공한다 [12]. 모든 작업은 AgentCore Observability를 통해 자동으로 추적된다 [7]. + +## ⚖️ Trade-offs & Caveats +* **추상화의 한계와 탈출구(Escape Hatch) 요구**: 구성 파일과 CLI 명령어만으로 에이전트를 매우 빠르게 배포할 수 있지만, 복잡한 다중 에이전트 조정이나 고도로 맞춤화된 오케스트레이션 로직, 특수 라우팅이 필요해질 경우 기본 제공되는 구성 기능만으로는 한계에 부딪힌다 [6, 13]. 이 경우 하네스 구성을 하위 수준인 'Strands Agents' 코드로 내보내기(Export)하여 직접 코드를 수정하고 배포해야 하는 추가 작업이 발생한다 [6, 14]. +* **도구 사용에 따른 토큰 소모**: 내장된 브라우저 도구 등을 활용하여 자율적인 웹 탐색 등을 수행할 때 많은 토큰을 소모하게 되므로 운영 시 비용 및 성능 최적화에 유의해야 한다 [9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentOps.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentOps.md new file mode 100644 index 00000000..43439405 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AgentOps.md @@ -0,0 +1,19 @@ +# [[AgentOps]] + +## 📌 Brief Summary +AgentOps는 다중 에이전트 시스템의 배포 후 세션 모니터링을 위해 설계된 오픈 소스 에이전트 엔지니어링 플랫폼이자 관측성(Observability) 도구이다 [1, 2]. 이 도구는 400개 이상의 LLM을 대상으로 세션 리플레이, 비용, 지연 시간, 도구 사용 내역 및 다중 에이전트 상호작용을 추적한다 [1]. LangGraph, CrewAI, OpenAI Agents SDK 등 다양한 프레임워크와 결합되어 단계별 실행 그래프와 교차 세션 지표를 제공함으로써 프로덕션 환경의 실용적인 디버깅 계층으로 기능한다 [1, 2]. + +## 📖 Core Content +* **관측성 및 세션 리플레이(Session Replay):** AgentOps는 도구 호출, 모델 호출, 비용 및 지연 시간 데이터를 포함한 전체 세션 트랜스크립트를 기록한다 [3]. 엔지니어는 세션 리플레이 기능을 통해 실패한 세션에서 정확히 어떤 일이 발생했는지 법의학적(forensic)으로 분석하고 에이전트의 실패 원인을 디버깅할 수 있다 [3]. +* **다중 에이전트 추적 및 프레임워크 지원:** 동일한 세션 내에서 동시에 실행되는 여러 에이전트 간의 상호작용을 추적할 수 있다 [3]. CrewAI, LangGraph, OpenAI Agents SDK 등 10개 이상의 프레임워크에서 실패 감지 및 단계별 실행 그래프를 지원하여 프로덕션 다중 에이전트 시스템을 위한 가장 실용적인 디버깅 계층으로 평가받는다 [2]. +* **비용 추적 및 최적화:** 400개 이상의 LLM에 대한 비용을 추적하며, 수집된 세션 수준의 데이터는 파인튜닝(fine-tuning) 우선순위를 결정하는 데 피드백으로 활용된다 [3]. 수집된 세션 데이터를 통해 파인튜닝 비용을 최적화할 수 있는 기능을 제공한다 [1]. +* **라이선싱:** 기본적으로 오픈 소스(YC W24) 형태를 띠며, 무료 티어(Free tier)와 함께 대용량 및 엔터프라이즈 기능을 위한 유료 플랜을 제공한다 [2-4]. + +## ⚖️ Trade-offs & Caveats +* **성능 오버헤드:** AgentOps를 프로덕션 모니터링 구성에 적용하여 실행할 경우 약 12%의 성능 오버헤드(performance overhead)가 발생한다는 단점이 있다 [1, 3]. +* **사후 조치(Post-hoc)의 한계:** 이 도구는 에이전트의 행동을 모니터링하고 실패가 발생한 이후(post-hoc)에만 이를 포착할 수 있다 [3, 4]. 따라서 입력 소스의 오류로 인해 발생하는 실패를 실행 전에 사전에 방지하지는 못한다 [3]. +* **데이터 품질 관리 부재:** AgentOps는 에이전트가 사용하는 입력 데이터의 품질, 계보(lineage), 또는 데이터 인증 상태를 모니터링하지 않는다 [4]. 에이전트가 오래되거나 잘못된 데이터에 기반하여 행동하더라도, 세션 리플레이는 '에이전트가 한 행동'만을 보여줄 뿐 데이터가 잘못되었다는 사실 자체를 판단해주지는 못한다 [4]. +* **비용 절감 주장의 독립적 검증 필요:** 세션 데이터를 통해 파인튜닝 비용을 25배 절감할 수 있다는 제조사의 주장은 도입 시 독립적인 검증(independently validated)이 요구된다 [3]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AutoGen - AG2.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AutoGen - AG2.md new file mode 100644 index 00000000..f34908d6 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/AutoGen - AG2.md @@ -0,0 +1,18 @@ +# [[AutoGen / AG2]] + +## 📌 Brief Summary +AutoGen(AG2)는 마이크로소프트(Microsoft)에서 개발한 대화형 다중 에이전트(multi-agent) 프레임워크이다 [1, 2]. 여러 에이전트가 대화를 통해 산출물을 제안하고 비판하며 정제하는 과정을 거치며 작업을 수행하는 아키텍처를 특징으로 한다 [3]. 코드를 안전하게 실행할 수 있는 샌드박싱 환경과 인간 참여(Human-in-the-Loop) 기능을 지원하여, 대규모 다중 에이전트 하네스 설계에 있어 가장 포괄적인 오픈소스 레퍼런스 중 하나로 평가받는다 [1, 2]. + +## 📖 Core Content +* **대화형 다중 에이전트 아키텍처:** AutoGen의 핵심 차별점은 여러 에이전트가 순서를 번갈아 가며 산출물을 제안, 비판, 정제하는 다중 턴(multi-turn) 토론 패턴을 사용한다는 것이다 [3]. 한 에이전트가 제안하면 다른 에이전트가 비판하고 세 번째 에이전트가 이를 종합하는 방식은 단일 에이전트의 생성 방식보다 엔지니어링 및 분석 작업에서 훨씬 더 신뢰할 수 있는 결과를 도출한다 [3]. 또한 AgentChat 계층을 통해 에이전트 루프, 도구 통합, 종료 조건 등을 완전하게 제어할 수 있다 [2]. +* **코드 실행 샌드박싱 (Code Execution Sandboxing):** 코드를 작성하고 테스트해야 하는 에이전트를 위해 Docker 네이티브 기반의 샌드박스화된 코드 실행 환경을 제공한다 [1, 3]. 이를 통해 에이전트는 호스트 시스템에 위험을 가하지 않고 완전히 격리된 환경에서 안전하게 코드를 실행할 수 있으며, 반복적인 디버깅 워크플로우에 최적화된 프레임워크로 널리 사용된다 [1, 3]. +* **인간 참여 제어 (Human-in-the-Loop):** 에이전트 워크플로우 내에 인간의 검토 및 승인 게이트를 추가할 수 있는 구체적인 메커니즘을 지원한다 [4]. `human_input_mode` (NEVER / TERMINATE / ALWAYS) 설정과 `UserProxyAgent`를 활용하여 인간이 다중 에이전트 대화 하네스에 안전하게 개입할 수 있도록 돕는다 [4]. + +## ⚖️ Trade-offs & Caveats +* **무한 루프 발생 위험:** 두 에이전트가 결론을 맺지 못하고 무한히 루프를 도는 현상은 수동 개입이 필요한 이 프레임워크의 알려진 실패 유형(failure mode)이다 [3]. +* **수동 컨텍스트 관리의 필요성:** 다중 턴 대화가 길어짐에 따라 컨텍스트가 지속적으로 축적되지만, 이를 자동으로 관리하거나 요약해 주는 압축 메커니즘이 부족하다 [3]. 따라서 토큰 윈도우가 가득 차게 되면 사용자가 수동으로 컨텍스트를 정리(pruning)해야 하는 제약이 따른다 [3, 5]. +* **스캐폴딩 및 데이터 품질 의존성:** 최종 출력물의 품질이 인간이 사전에 작성해 둔 대화 스캐폴딩(scaffolding)의 수준에 크게 좌우된다 [3]. 또한, 에이전트가 검색한 데이터가 최신인지 또는 인증되었는지를 검증하는 자체 거버넌스 메커니즘이 없으며, 에이전트의 출력물을 원본 소스 데이터와 연결하는 데이터 계보(lineage) 추적 기능도 제공하지 않는다 [5]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Co-evolution (공진화).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Co-evolution (공진화).md new file mode 100644 index 00000000..c6b77a1a --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Co-evolution (공진화).md @@ -0,0 +1,18 @@ +# [[Co-evolution (공진화)]] + +## 📌 Brief Summary +공진화(Co-evolution)는 인공지능 에이전트 환경에서 모델의 훈련 과정과 하네스(Harness) 설계가 상호작용하며 함께 발전하는 현상을 의미한다 [1]. 오늘날의 최신 에이전트 모델들은 하네스를 루프(loop)에 포함시킨 상태로 훈련되며, 기술적 결합뿐만 아니라 인간과 에이전트가 상호 학습하며 개선되어가는 철학적 개념으로도 사용된다 [1, 2]. 그러나 특정 하네스 환경에 모델이 과적합(Overfitting)되어 일반화 능력이 저하될 수 있다는 중대한 기술적 한계를 수반한다 [1, 3]. + +## 📖 Core Content +* **모델 훈련과 하네스 설계의 결합:** Claude Code나 Codex와 같은 최신 에이전트 제품들은 모델과 하네스가 루프에 포함된 상태에서 사후 훈련(post-trained)을 진행한다 [1]. 이러한 훈련 방식은 파일 시스템 조작, bash 실행, 계획 수립, 하위 에이전트(subagent)를 통한 병렬 작업 등 하네스 설계자가 에이전트가 본질적으로 잘 수행해야 한다고 판단하는 동작들을 모델이 효과적으로 개선하도록 돕는다 [1]. +* **피드백 루프를 통한 역량 강화:** 시스템 설계 과정에서 유용한 프리미티브(primitives)가 발견되면 하네스에 추가되고, 이는 다음 세대의 모델을 훈련할 때 다시 사용되는 피드백 루프(feedback loop)를 형성한다 [1]. 이 사이클이 반복되면서 모델은 자신이 훈련된 특정 하네스 환경 내에서 점점 더 강력하고 유능한 성능을 발휘하게 된다 [1]. +* **인간과 에이전트의 공진화 (플랫폼 관점):** 기술적 요소 간의 결합을 넘어 인간과 에이전트 간의 관계에서도 공진화의 개념이 적용된다. 일례로 LobeHub와 같은 작업 공간 플랫폼은 인간과 에이전트가 지속적으로 학습하고 함께 개선되는 공진화(co-evolution) 아이디어를 중심으로 구축되었다 [2]. 이를 통해 에이전트는 일회성 도구가 아니라 사용자의 작업 흐름과 선호도를 이해하는 진정한 팀원으로서 진화하게 된다 [2]. +* **자기 진화(Self-improvement)로의 확장:** 에이전트가 시간이 지남에 따라 자신의 스캐폴딩(하네스)을 스스로 수정하고 개선함에 따라, 하네스 역시 이러한 에이전트의 변화에 맞춰 적응해야 하는 차세대 에이전트 역량 발전의 방향성으로도 공진화가 다루어지고 있다 [4]. + +## ⚖️ Trade-offs & Caveats +* **과적합(Overfitting) 및 일반화(Generalization) 성능 저하:** 모델과 하네스의 공진화는 일반화 측면에서 부정적인 부작용(side effects)을 초래한다 [1]. 하네스를 훈련 루프에 포함시키면 모델이 해당 하네스 설계에 과적합되어, 도구의 로직(예: 파일을 편집하는 패치 방법 등)을 약간만 변경해도 모델의 성능이 악화되는 현상이 발생한다 [1, 5]. 진정한 지능형 모델이라면 도구 논리 변화에 쉽게 적응해야 하지만, 공진화로 인한 과적합이 이를 가로막는다 [5]. +* **장기적인 아키텍처 종속성 초래:** '공진화의 경고(co-evolution warning)'라고 불리는 이 현상에 따르면, 특정 하네스와 함께 훈련된 모델은 해당 설계에 강하게 묶이게 되므로 초기의 하네스 아키텍처 선택이 당면한 작업을 넘어서서 시스템 전체에 장기적인 결과와 제약을 초래할 수 있다 [3]. +* **당면 과제와 훈련된 하네스 간의 불일치:** 모델이 특정 하네스와 함께 훈련되어 역량이 강화되었다 하더라도, 그 하네스가 사용자가 현재 수행하려는 특정 과제에 가장 적합한 '최적의 하네스'임을 의미하지는 않는다 [5]. 종종 훈련에 사용된 기본 하네스를 그대로 사용하는 것보다 현재 작업의 특성에 맞춰 하네스를 새롭게 튜닝하고 최적화(Harness engineering)할 때 훨씬 더 높은 성과를 얻을 수 있다 [5]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Code Execution (코드 실행).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Code Execution (코드 실행).md new file mode 100644 index 00000000..ec802067 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Code Execution (코드 실행).md @@ -0,0 +1,17 @@ +# [[Code Execution (코드 실행)]] + +## 📌 Brief Summary +코드 실행(Code Execution)은 에이전트 하네스가 대규모 언어 모델(LLM)에 자율적인 문제 해결 능력을 부여하기 위해 제공하는 핵심 기술 프리미티브이다 [1, 2]. 에이전트가 사전에 정의된 도구에만 의존하지 않고 Bash나 Python 등의 코드를 직접 작성하여 환경과 상호작용하도록 가상의 컴퓨터를 제공하는 역할을 한다 [3, 4]. 이러한 코드 실행은 호스트 시스템의 안전을 보장하기 위해 주로 샌드박스나 마이크로VM과 같은 격리된 환경에서 이루어진다 [5-7]. + +## 📖 Core Content +* **자율적 문제 해결 및 도구의 일반화**: 코드 실행은 에이전트 하네스의 5대 핵심 프리미티브 중 하나로, 비정형 문제에 대한 동적 해결책을 자율적으로 생성할 수 있게 한다 [1, 2]. 에이전트 하네스에는 Bash 등의 일반 목적 도구가 포함되어 있어, 에이전트가 코드를 통해 스스로 도구를 설계하고 문제를 해결할 수 있다 [3, 4]. +* **효율성 및 토큰 최적화**: 다단계 도구 호출을 코드로 대체하면 효율성이 크게 향상된다. 예를 들어, MCP 서버와 상호작용할 때 에이전트가 개별 도구를 직접 여러 번 호출하는 대신 이를 수행하는 코드를 작성해 실행하도록 하면 토큰 오버헤드를 최대 98.7%까지 절감할 수 있다 [8]. 또한 셸(Shell) 접근을 활용하면 모델 추론을 거치거나 토큰 비용을 소모하지 않고도 가상 머신에서 명령을 직접 실행할 수 있다 [7]. +* **샌드박싱 및 격리된 실행 환경**: 에이전트가 작성한 코드를 실행할 수 있는 안전한 환경을 보장하기 위해 하네스는 온디맨드 샌드박스를 제공한다 [6]. Microsoft의 AutoGen은 Docker 네이티브 샌드박싱을 지원하여 코드 작성 에이전트를 호스트 시스템으로부터 격리하며 [9], AgentCore는 세션마다 전용 CPU, 메모리, 파일 시스템을 갖춘 독립된 마이크로VM(microVM)을 띄워 코드를 실행한다 [7, 10]. 이외에도 제공자 관리형 환경에서 명령을 실행하는 호스팅된 셸(Hosted shell) 방식도 존재한다 [11]. + +## ⚖️ Trade-offs & Caveats +* **보안 위험과 명시적 승인 요구**: 모델이 생성한 코드를 로컬 호스트 환경에서 직접 실행하는 것은 높은 위험을 수반한다 [6]. 따라서 로컬 셸 실행 시에는 격리된 환경을 사용해야 하며, 명령이 실행되기 전에 애플리케이션 측에서 명확한 승인(Approval) 체크포인트를 두어 제어권을 유지해야 한다 [11-13]. +* **실행 환경의 콜드 스타트 지연**: 안전한 코드 실행을 위해 샌드박스나 마이크로VM을 온디맨드로 생성하고 파괴하는 과정에서 초기 구동 지연(Latency)이 발생할 수 있다 [5, 6]. 예를 들어 E2B와 같이 에이전트 도구 루프용으로 특별히 설계된 마이크로VM은 약 150ms의 콜드 스타트 시간을 제공하지만, 인프라의 아키텍처나 환경에 따라 지연율에 차이가 발생할 수 있다 [5]. +* **출력물로 인한 컨텍스트 과부하**: 코드 실행 결과로 반환되는 방대한 에러 로그나 출력물은 모델의 컨텍스트 윈도우를 빠르게 소모시켜 '컨텍스트 부패(Context Rot)'를 유발할 수 있다 [14, 15]. 이를 방지하기 위해 도구 호출 결과의 일부만 유지하고 나머지는 파일 시스템으로 오프로딩(Offloading)하는 등의 하네스 차원의 최적화 관리가 필수적으로 동반되어야 한다 [15]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Containerization.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Containerization.md new file mode 100644 index 00000000..c09a581e --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Containerization.md @@ -0,0 +1,17 @@ +# [[Containerization]] + +## 📌 Brief Summary +컨테이너화(Containerization)는 에이전트 하네스 환경에서 AI 에이전트가 안전하게 코드를 실행하고 도구와 상호작용할 수 있도록 격리된 샌드박스(Sandbox) 실행 환경을 제공하는 핵심 기술이다 [1-3]. 도커(Docker), OCI 컨테이너, 마이크로VM 등을 활용하여 호스트 시스템을 보호함과 동시에 일관되고 재현 가능한 에이전트 구동 및 벤치마크 평가 환경을 구성하는 데 사용된다 [1, 2, 4, 5]. 이를 통해 에이전트는 외부 시스템 인프라를 오염시키지 않고 자율적으로 문제를 해결할 수 있다 [1, 5]. + +## 📖 Core Content +* **격리된 코드 실행 및 샌드박싱**: AutoGen(AG2)과 같은 오케스트레이션 프레임워크는 Docker 네이티브 샌드박싱 기능을 통해 코드를 작성하는 에이전트가 호스트 시스템에 대한 위험 없이 격리된 환경에서 코드를 실행하고 테스트할 수 있도록 지원한다 [1]. 또한 Open Harness 모델은 단일 프로젝트 및 브랜치에 할당된 단일 Docker 컨테이너를 구동하여, 호스트의 의존성 부패(Toolchain rot) 없이 에이전트가 독립적인 작업 공간을 소유하고 활동할 수 있게 한다 [5]. +* **일관된 평가 및 벤치마킹 환경 구축**: 에이전트의 성능을 재현 가능하게 평가하기 위해 HAL(Holistic Agent Leaderboard)과 같은 통합 평가 하네스는 Docker 컨테이너를 활용한다 [3, 6]. SWE-bench, ScienceAgentBench 및 USACO 등 다양한 벤치마크 테스트가 컨테이너 기반으로 병렬 실행되며, 모델의 시스템 제어 변수를 일정하게 유지한다 [3, 4, 7, 8]. +* **다양한 컨테이너 런타임 및 인프라의 진화**: 엔터프라이즈 하네스 환경에서는 단순한 Docker를 넘어 다양한 형태의 컨테이너 기술이 쓰인다. 빠른 시작 시간과 커널 수준의 격리를 제공하는 Firecracker 기반의 마이크로VM(예: E2B)이나 90ms 미만의 부팅 속도와 영구 상태를 지원하는 OCI 컨테이너(예: Daytona)가 사용된다 [2, 9]. 기존 인프라에 통합해야 할 경우, gVisor나 Kata Containers를 통해 커널 수준의 격리를 제공하는 쿠버네티스(Kubernetes) 네이티브 샌드박스 CRD가 도입되기도 한다 [10]. + +## ⚖️ Trade-offs & Caveats +* **운영 및 인프라 복잡성 증가**: 컨테이너화된 환경에서 파일 시스템을 백엔드로 사용하여 에이전트의 컨텍스트를 오프로딩(Offloading)하고 관리하는 방식은 전체 시스템의 운영 복잡성을 가중시킨다 [11]. +* **평가 환경의 자원 구성에 따른 행동 노이즈**: 컨테이너에 할당되는 자원(CPU, 메모리 등) 설정 자체가 에이전트의 문제 해결 전략에 큰 영향을 미칠 수 있다 [12]. 엄격한 자원 제한 환경과 넉넉한 환경에서 에이전트가 선택하는 도구나 종속성 활용 전략이 완전히 달라져 벤치마크 점수에 큰 변동을 일으키는 원인이 된다 [12]. +* **컨테이너 격리만으로는 부족한 보안 한계**: 컨테이너 기반의 샌드박스 격리 기능만으로는 에이전트의 악의적 혹은 통제 불능 상태를 완벽히 막을 수 없다 [2, 9]. 에이전트가 자신의 하네스 구성(예: MCP 서버 설정, 훅 파일)을 수정할 수 있거나 네트워크 이그레스(Egress) 제한이 없는 경우, 컨테이너 내부에 있더라도 권한 상승이나 외부 유출의 위험이 존재하므로 커널 수준의 제어나 OPA(Open Policy Agent) 기반의 네트워크 제어가 동반되어야 한다 [2, 9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Compression (컨텍스트 압축).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Compression (컨텍스트 압축).md new file mode 100644 index 00000000..cb7b33da --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Compression (컨텍스트 압축).md @@ -0,0 +1,17 @@ +# [[Context Compression (컨텍스트 압축)]] + +## 📌 Brief Summary +컨텍스트 압축(Context Compression)은 장기 실행 에이전트 세션에서 모델의 컨텍스트 윈도우 한계를 초과하지 않도록 대화 이력 및 데이터를 요약하고 관리하는 하네스 수준의 핵심 기술이다 [1, 2]. 대화가 길어짐에 따라 발생하는 '컨텍스트 부패(Context Rot)'를 방지하기 위해, 오래되거나 불필요한 데이터를 압축하여 핵심 정보만 모델에 전달한다 [2-5]. 이를 통해 토큰 예산을 효율적으로 통제하면서도 에이전트가 작업 연속성과 중요한 맥락을 유지할 수 있도록 지원한다 [1]. + +## 📖 Core Content +* **개념 및 작동 원리:** 장기 실행 작업에서 모델은 이전 출력, 도구 사용 기록 등 방대한 데이터를 축적하게 된다 [1, 4]. 하네스는 모델 호출 시마다 어떤 정보를 포함하고 압축할지 결정하며, 컨텍스트 윈도우 한계에 도달하면 과거의 대화나 50페이지에 달하는 상세 로그 등을 몇 개의 핵심 요약 포인트로 압축(Compaction)한다 [3, 6]. +* **자율적 압축으로의 진화:** 기본적으로 서버 측에서 고정된 토큰 임계값에 도달하면 반응적으로 압축하는 방식이 사용된다 [7]. 하지만 최근에는 에이전트가 자율적으로 적절한 시점(작업 전환 시 등)에 전용 도구를 호출하여 상호작용 이력을 영구적인 지식 블록으로 병합하고 원시 컨텍스트를 정리하는 '자율적 컨텍스트 압축(Autonomous Context Compression)' 기술이 활용되고 있다 [7]. 이는 기계적인 토큰 예산 관리에서 벗어나 의미론적인 일관성을 기반으로 컨텍스트를 유지할 수 있게 돕는다 [7]. +* **효과 및 성능 기여:** 여러 압축 전략을 결합하면 대화의 연속성을 잃지 않으면서도 세션의 반응성을 유지하고 비용을 절감할 수 있다 [8]. 최신 대화 맥락은 온전히 유지하면서 재현할 필요가 없는 과거의 무거운 도구 사용 이력을 다듬어, 에이전트가 토큰 예산 내에서 효율적으로 작동하도록 만든다 [1]. + +## ⚖️ Trade-offs & Caveats +* **중요 규칙 침식 및 정보 파괴 (Behavioral Drift & Fact Destruction):** 연속적인 요약 과정(Cascaded Summarizations)을 거치면서 에이전트의 제약 조건이 침식되거나 최대 60%의 사실 정보가 파괴되는 부작용이 발생할 수 있다 [9]. 따라서 모델이 절대 잊어버리면 안 되는 중요한 규칙(Critical rules)은 압축 시스템에 의존하지 말고, 시스템 프롬프트(예: CLAUDE.md 등)에 명시하여 압축 과정에서도 살아남도록 설계해야 한다 [10]. +* **데이터 출처 및 계보 유실 (Loss of Data Provenance):** 컨텍스트가 자동으로 요약 및 압축되면 해당 정보의 원래 출처가 어디인지 조용히 유실될 위험이 있다 [11, 12]. 즉, 에이전트가 압축된 컨텍스트를 읽을 때 그 정보의 기원을 소스 데이터까지 추적할 수 있는 리니지(Lineage) 추적 메커니즘이 단절되는 단점이 존재한다 [12]. +* **추론 상태 손상 (Corruption of In-flight Reasoning):** 고정된 한계치에 도달했을 때 하네스에 의해 강제로 실행되는 반응적 압축(Reactive-at-limit compaction)은 에이전트가 하위 작업을 수행하는 중간에 개입하여 진행 중인 추론 상태(In-flight reasoning state)를 훼손할 위험이 있다 [7]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Rot (컨텍스트 부패).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Rot (컨텍스트 부패).md new file mode 100644 index 00000000..53bcf06a --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Context Rot (컨텍스트 부패).md @@ -0,0 +1,24 @@ +# [[Context Rot (컨텍스트 부패)]] + +## 📌 Brief Summary +Context Rot(컨텍스트 부패)는 에이전트의 컨텍스트 윈도우가 도구 출력 결과, 대화 기록, 이전의 추론 과정 등으로 가득 차면서 모델의 추론 및 작업 완료 능력이 점차 저하되는 현상을 의미한다 [1, 2]. 이는 200k 이상의 거대한 토큰 윈도우를 가진 모델에서도 중간에 위치한 밀도 높은 정보가 무시되는 현상과 맞물려, 에이전트가 원래의 지시사항이나 핵심 목표를 잃어버리는 결과를 초래한다 [2, 3]. 이를 해결하기 위해 에이전트 하네스는 제한된 자원인 컨텍스트를 효율적으로 관리하고자 자동 압축(Compaction)이나 도구 호출 오프로딩(Offloading)과 같은 전략을 필수적으로 사용한다 [1, 4]. + +## 📖 Core Content +* **원인 및 발생 메커니즘** + 장기 실행 에이전트가 여러 단계의 작업을 수행함에 따라, 이전 단계의 로그나 도구 출력값 등이 누적되어 컨텍스트 윈도우를 채우게 된다 [2]. 이렇게 누적된 노이즈 속에서 가장 중요한 세부 정보나 원래의 명령어가 흐려지는 '컨텍스트 표류(Context Drifting)' 현상이 나타난다 [5]. 스탠퍼드 대학의 연구(2023)에 따르면, 중요한 내용이 긴 프롬프트의 중간에 묻힐 경우 LLM의 성능이 저하되는 'Lost in the Middle' 현상 또한 컨텍스트 부패를 가속화하는 요인이다 [3]. + +* **하네스 차원의 해결 전략** + 에이전트 하네스는 모델이 지능을 잃지 않도록 다양한 컨텍스트 관리 기술을 제공한다. + * **컨텍스트 압축(Compaction):** 컨텍스트 윈도우가 한계에 다다를 때, 기존의 대화 이력이나 컨텍스트를 지능적으로 요약하고 오프로드하여 에이전트가 중단 없이 작업을 계속할 수 있도록 지원한다 [1]. + * **도구 호출 오프로딩(Tool call offloading):** 방대하고 노이즈가 많은 도구의 출력값이 컨텍스트 윈도우를 어지럽히지 않도록, 출력의 앞부분과 뒷부분 토큰만 남겨두고 전체 결과는 파일 시스템 등에 오프로드(저장)하여 필요할 때만 참조하게 만든다 [4]. + * **점진적 컨텍스트 제공(Progressive disclosure):** 에이전트 시작 단계부터 너무 많은 도구나 서버 설정이 로드되어 성능이 떨어지는 것을 막기 위해, 스킬 시스템 등을 통해 상황에 맞춰 필요한 정보만 점진적으로 노출한다 [4]. + * **프롬프트 구조 최적화:** 'Lost in the Middle' 현상을 방지하기 위해, 하네스는 가장 중요한 컨텍스트 정보를 프롬프트의 경계(처음과 끝부분)에 전략적으로 배치한다 [3]. + +## ⚖️ Trade-offs & Caveats +* **압축으로 인한 정보 유실 및 제약 조건 침식:** 컨텍스트 부패를 막기 위해 진행하는 요약과 압축 과정 자체가 본질적인 리스크를 지닌다. 연쇄적인 요약 과정에서 최대 60%의 사실 정보가 파괴될 수 있으며, 제약 조건들이 깎여나가면서 최대 54%의 에이전트 행동 표류(Behavioral drift)가 발생할 수 있다 [6]. +* **추론 상태 손상 및 타이밍 문제:** 토큰이 한계치에 도달했을 때 기계적으로 작동하는 수동적 압축(Reactive-at-limit compaction) 방식은, 에이전트가 하위 작업을 한창 수행하는 도중에 개입하여 진행 중인 추론 상태(in-flight reasoning state)를 훼손할 위험이 있다 [7]. +* **출처(Provenance) 추적의 상실:** 자동 요약 및 압축 시스템이 과거의 문맥을 밀도 높은 요약본으로 대체하게 되면, 해당 정보가 어디에서 유래했는지 연결 고리를 보여주는 데이터의 출처 기록이 조용히 버려지는 부작용이 있다 [8]. +* **중요 규칙 보존의 한계 구조:** 작업에 치명적인 영향을 미치는 핵심 규칙들은 압축 과정에서 유실되어서는 안 된다 [9]. 따라서 이 규칙들은 압축 시스템에 의존하지 않고 시스템 프롬프트(예: CLAUDE.md)와 같이 요약을 피해 생존할 수 있는 별도의 영구적 위치로 옮겨서 관리해야 하는 아키텍처적 제약이 따른다 [9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Control Layer (제어 계층).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Control Layer (제어 계층).md new file mode 100644 index 00000000..eb4608a2 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Control Layer (제어 계층).md @@ -0,0 +1,17 @@ +# [[Control Layer (제어 계층)]] + +## 📌 Brief Summary +에이전트 하네스 맥락에서 제어 계층(Control Layer 또는 Control Plane)은 대규모 언어 모델(LLM)을 감싸 에이전트의 실제 운영 방식을 관리하는 소프트웨어 프레임워크 시스템을 의미합니다 [1]. 이 계층은 도구 사용, 메모리, 계획 수립 및 다중 에이전트 조정을 위한 스캐폴딩(Scaffolding)을 제공하며 에이전트의 실행, 통신, 장애 복구 및 의사 결정 라우팅을 결정합니다 [1]. 결과적으로 모델의 확률적이고 인지적인 엔진을 실제 작업의 동력으로 전환하는 필수적인 제어 평면 역할을 수행합니다 [2]. + +## 📖 Core Content +* **역할 및 아키텍처 분리:** 제어 계층은 에이전트가 '어떻게' 실행되는지를 통제하는 역할을 맡습니다 [3]. 인증(Auth), 과금, 오케스트레이션을 담당하는 제어 평면은 파일, 셸, 포트 등을 다루는 샌드박스 컴퓨팅 평면과 엄격하게 분리되도록 설계됩니다 [4]. 오케스트레이션, 실행, 평가 등의 관심사를 분리하는 구조화된 스택으로 수렴하고 있습니다 [5]. +* **주요 프레임워크:** 2026년 기준, 대다수 에이전트 스택의 핵심 제어 계층을 구성하는 대표적인 오케스트레이션 프레임워크로는 LangGraph, CrewAI, AutoGen, LangChain deepagents, Microsoft Semantic Kernel, Mastra 등이 있습니다 [6]. 이들은 세밀한 상태 제어를 위한 그래프 기반 아키텍처(LangGraph), 빠른 프로토타이핑을 위한 역할 기반 아키텍처(CrewAI), 혹은 코드 샌드박싱에 유리한 대화형 아키텍처(AutoGen) 등 각기 다른 오케스트레이션 방식을 제공합니다 [7-9]. +* **통합 제어 환경으로의 진화:** 최근의 제어 계층은 평가(Evaluation) 및 관찰 가능성(Observability) 기능 역시 단순히 오프라인 벤치마크에 머물지 않고, 팀이 표준화하여 사용할 수 있는 런타임 제어 평면의 일부로 통합하여 인프라 서비스화 하는 추세를 보이고 있습니다 [10]. + +## ⚖️ Trade-offs & Caveats +* **데이터 품질 검증의 부재:** 제어 계층을 구성하는 프레임워크들의 가장 큰 구조적 한계는 에이전트가 '어떻게' 동작하는지는 관리하지만 '무엇을' 읽는지는 통제하지 않는다는 점입니다 [3]. 어떠한 오케스트레이션 프레임워크도 자체적으로 입력 데이터를 인증하거나 검증할 수 없으며, 이로 인해 별도의 거버넌스된 데이터 계층(Data Layer) 인프라가 없다면 에이전트는 스키마 드리프트, 오래된 데이터, 미인증 소스 등의 잘못된 입력으로 인해 치명적인 오류를 범할 수 있습니다 [1, 11, 12]. +* **통제력과 구성 복잡성의 상충 관계 (Trade-off):** 세밀한 상태 제어를 제공하는 제어 계층(예: LangGraph)은 작업 성공률이 높지만(비교 벤치마크 기준 87%), 구성이 장황하고 가파른 학습 곡선을 요구한다는 단점이 있습니다 [7, 13, 14]. 반면, 역할 기반의 프레임워크(예: CrewAI)는 빠른 프로토타이핑이 가능하지만 세밀한 제어력이 부족하고 상대적으로 작업 성공률(82%)이 낮아 프로젝트의 요구사항에 따른 절충이 필요합니다 [8, 14, 15]. +* **운영 오버헤드 및 종속성:** 제어 계층 내에 사후 모니터링이나 관찰 가능성 도구(AgentOps, Langfuse 등)를 결합할 경우, 시스템 실행에 약 12~15%의 성능 오버헤드가 발생할 수 있습니다 [16, 17]. 또한 특정 기업 생태계(예: Microsoft 기술 스택의 Semantic Kernel)에 맞춰진 제어 프레임워크를 선택할 경우 강력한 타입 안정성과 컴파일 타임 검증을 얻는 대신 해당 플랫폼에 대한 종속성(Lock-in)이 심화될 수 있습니다 [18, 19]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance - Context Layer.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance - Context Layer.md new file mode 100644 index 00000000..fe5597cd --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance - Context Layer.md @@ -0,0 +1,20 @@ +# [[Data Governance / Context Layer]] + +## 📌 Brief Summary +데이터 거버넌스 및 컨텍스트 계층(Data Governance / Context Layer)은 AI 에이전트 하네스 내에서 에이전트에게 공급되는 데이터(컨텍스트)가 신뢰할 수 있고 최신 상태이며 검증되었음을 보장하는 핵심 인프라 계층입니다 [1, 2]. 대부분의 에이전트 오케스트레이션 프레임워크가 에이전트의 '동작 방식'을 제어하는 데 그치는 반면, 이 계층은 에이전트가 '무엇을 읽는지'를 통제하여 잘못된 데이터로 인한 환각이나 시스템 오류를 사전에 방지합니다 [3-5]. 데이터 계보 추적, 활성 메타데이터 관리, 컨텍스트 압축 등의 기술을 통해 복잡한 다중 에이전트 환경에서 컨텍스트 과부하를 막고 데이터의 무결성을 유지합니다 [2, 6, 7]. + +## 📖 Core 소스 +* **에이전트 오케스트레이션 프레임워크의 구조적 한계:** LangGraph, CrewAI, AutoGen과 같은 대부분의 벤치마크 프레임워크는 에이전트의 실행 주기, 도구 호출, 다중 에이전트 조정 등 하네스의 제어 계층(Control Layer)은 완벽히 관리하지만, 이들을 통과하는 데이터의 품질을 검증하거나 인증하는 기능은 갖추고 있지 않습니다 [4, 5, 8, 9]. 결과적으로 에이전트 AI 구현 시간의 80%가 모델이나 프레임워크 설정이 아닌 데이터 엔지니어링 및 거버넌스에 소모되며, 응용 프로그램 오류의 주요 원인(메모리 오염, 계단식 실패 등)은 불량 데이터 입력에서 비롯됩니다 [10-13]. +* **거버넌스 데이터 기질(Governed Data Substrate)의 핵심 요소:** 에이전트가 신뢰할 수 있는 데이터만 읽도록 보장하기 위해 컨텍스트 계층은 다음과 같은 거버넌스 기능을 제공해야 합니다. + * **활성 메타데이터(Active metadata):** 데이터 시스템을 지속적으로 모니터링하여 실시간 인증 상태, 스키마 상태 및 최신성 신호를 구조화된 컨텍스트로 제공합니다 [2]. + * **데이터 계약(Data contracts):** 데이터가 에이전트 컨텍스트 윈도우에 진입하기 전에 스키마 계약을 강제하여 스키마 표류(Schema drift)를 사전에 차단합니다 [2]. + * **데이터 계보(Data lineage) 및 인증:** 열(Column) 수준의 계보를 통해 에이전트가 읽는 데이터의 출처를 추적하며, 데이터 관리자가 인증한 자산만 읽도록 설정하여 기업 환경에서의 규정 준수를 보장합니다 [6]. +* **컨텍스트 엔지니어링 및 압축(Context Engineering & Compaction):** 대규모 작업을 수행할 때 도구 출력과 이전 작업 내역으로 컨텍스트 윈도우가 가득 차면, 에이전트가 원래의 지시사항을 잃어버리는 '컨텍스트 부패(Context rot)'가 발생합니다 [14, 15]. 이를 방지하기 위해 컨텍스트 계층은 대화 기록이 한도에 도달하기 전에 이전 컨텍스트를 조밀한 요약본으로 자동 압축(Auto-summarization)하거나 오프로드합니다 [14, 16]. 또한 관련 문서만 증분적으로 가져오는 RAG(Retrieval-Augmented Generation) 패턴을 활용하고, 정보의 위치에 따라 모델 성능이 저하되는 현상(Lost in the Middle)을 막기 위해 가장 중요한 컨텍스트를 프롬프트 경계에 배치합니다 [7]. + +## ⚖️ Trade-offs & Caveats +* **컨텍스트 압축으로 인한 데이터 출처(Provenance) 소실 위험:** 토큰 한도를 관리하기 위해 이전 단계를 밀도 높은 요약본으로 압축하는 자동 요약 메커니즘을 사용할 경우, 정보의 출처가 조용히 버려질 수 있다는 반대 급부가 존재합니다 [17, 18]. 압축된 컨텍스트에서 에이전트가 데이터를 읽게 되면 해당 정보가 어디에서 생성되었는지 기록이 남지 않으므로, 산출물과 원본 데이터를 연결하는 계보 추적이 끊어질 위험이 있습니다 [17]. +* **사후 관측성(Observability) 도구의 근본적 한계:** AgentOps나 Langfuse와 같은 모니터링 및 평가 도구는 세션을 재생하거나 모델의 출력을 평가하는 데는 매우 유용하지만, 이는 실패가 발생한 후에만 인지할 수 있는 사후적(Post-hoc) 조치입니다 [4, 9, 19, 20]. 이들은 에이전트가 읽은 컨텍스트가 오래되었거나 검증되지 않았는지 판단할 수 없으므로, 잘못된 입력 데이터로 인해 발생한 높은 평가 점수의 오도(Misleading)를 근본적으로 막아주지는 못합니다 [4]. +* **과도한 도구 통합에 따른 컨텍스트 과부하:** 데이터와 도구를 에이전트와 통합할 때, 너무 많은 도구나 MCP 서버를 한 번에 컨텍스트에 로드하면 에이전트가 실제 작업을 시작하기도 전에 성능이 저하될 수 있습니다 [21]. 모든 데이터 접근 권한을 한 번에 열어주는 대신, 점진적 공개(Progressive disclosure)나 온디맨드 방식의 로딩을 채택해야 컨텍스트 예산을 효율적으로 관리할 수 있습니다 [21]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance.md new file mode 100644 index 00000000..6f41d30e --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Governance.md @@ -0,0 +1,22 @@ +# [[Data Governance]] + +## 📌 Brief Summary +에이전트 하네스 환경에서 데이터 거버넌스(Data Governance)는 AI 에이전트가 읽고 처리하는 입력 데이터의 신뢰성, 최신성, 스키마 안정성 및 출처를 사전 검증하고 인증하는 기반 인프라 및 제어 체계를 의미합니다 [1-3]. 대부분의 오케스트레이션 프레임워크는 에이전트의 '실행 방식'은 제어하지만 '어떤 데이터를 읽는지'는 관리하지 못하므로, 이를 보완하는 거버넌스 계층이 필수적입니다 [1, 4]. 데이터 거버넌스가 부재할 경우 미인증 데이터나 오래된 정보가 유입되어 메모리 오염이나 연쇄적 실패, 그리고 이른바 에이전트의 '환각(Hallucination)' 현상이 초래됩니다 [1, 5, 6]. + +## 📖 Core Content +* **데이터 거버넌스의 필수성:** 에이전트 AI 구현 시간의 약 80%는 모델 선택이나 프레임워크 구성이 아닌 데이터 엔지니어링 및 거버넌스 작업에 소요됩니다 [5, 7]. 흔히 'LLM 환각'으로 치부되는 문제의 상당수는 실제로는 일관성이 없거나, 오래되었거나, 부분적으로만 복제된 데이터 소스가 하네스의 컨텍스트로 주입된 결과입니다 [5, 6]. +* **프레임워크의 구조적 한계:** LangGraph, CrewAI, AutoGen, Haystack과 같은 오케스트레이션 및 RAG 프레임워크는 에이전트 제어 계층에서 작동하며, 입력 데이터가 깨끗하다고 가정할 뿐 이를 직접 인증하거나 리니지를 추적하는 내장 메커니즘을 제공하지 않습니다 [8-11]. 따라서 스키마 드리프트(Schema drift)나 미인증 데이터 소스가 아무런 검증 없이 에이전트에 전달될 수 있습니다 [10, 12, 13]. +* **데이터 거버넌스 기판(Substrate)의 핵심 요소:** 에이전트가 읽을 데이터를 사전에 통제하기 위해 다음과 같은 인프라 요소들이 활용됩니다. + * **액티브 메타데이터 (Active Metadata):** 데이터 시스템을 지속적으로 모니터링하여 실시간 인증 상태, 스키마 상태, 데이터 최신성 신호를 구조화된 컨텍스트로 제공합니다 [3]. + * **데이터 계약 (Data Contracts):** 데이터가 에이전트의 컨텍스트 윈도우에 진입하기 전에 스키마 계약을 강제하여, 에이전트가 잘못된 결과를 도출하기 전에 스키마 드리프트를 사전 차단합니다 [3]. + * **데이터 리니지 (Data Lineage):** 에이전트가 읽는 데이터를 원본까지 추적(Column-level)하여, 실패 발생 시 근본 원인이 모델, 프롬프트, 혹은 원본 데이터 중 어디에 있는지 파악할 수 있도록 지원합니다 [14]. + * **인증 상태 (Certification Status):** 에이전트가 데이터 스튜어드가 명시적으로 인증한 데이터 자산만 읽도록 구성하여, 신뢰할 수 없는 데이터로 인한 엔터프라이즈 환경의 실패 요인을 제거합니다 [14]. +* **엔터프라이즈 수준의 확장:** 성공적인 에이전트 스케일링을 위해 Microsoft Copilot Studio, GitHub Enterprise, AWS Agent Registry 등은 관리자 제어를 통한 도구 거버넌스, 중앙 집중식 에이전트/스킬 카탈로그 탐색 규칙, 인프라 수준의 실행 환경 표준화 등 보다 폭넓은 거버넌스 관리 체계를 제공합니다 [15-17]. + +## ⚖️ Trade-offs & Caveats +* **사후 관측성(Observability) 도구의 근본적 한계:** AgentOps나 Langfuse와 같은 도구는 에이전트의 세션을 추적하고 비용이나 지연 시간을 분석하는 데 유용하지만, 이는 실패가 발생한 **이후(Post-hoc)**에만 동작합니다 [10, 18-20]. 결과적으로 불량 입력 데이터(Bad inputs)로 인한 실패 자체를 사전에 예방하지는 못하며, 오래된 데이터에서 파생된 결과물임에도 모델 출력 평가에서는 높은 점수를 받는 등 왜곡된 결과를 초래할 수 있습니다 [18, 19]. +* **접근 권한(RBAC)과 데이터 품질의 혼동 위험:** Azure 기반의 Semantic Kernel이나 Mastra 등에서 제공하는 RBAC(역할 기반 접근 제어) 설정은 **누가(Who) 특정 API나 에이전트를 호출할 수 있는지**를 관리할 뿐, 모델에 입력되는 데이터 자체가 인증되었거나 스키마가 안정적인지를 관리하는 것은 아닙니다 [12, 21]. 오래된 데이터 소스에서 파생된 정보는 RBAC를 완벽히 거치더라도 여전히 오래된 정보일 뿐이므로 권한 관리만으로 데이터 거버넌스를 대체할 수 없습니다 [21]. +* **도입 복잡성 및 리소스 비용:** 에이전트의 런타임 이전에 입력 데이터를 평가, 검증 및 인증해야 하는 데이터 인프라를 구축하는 것은 에이전트 스택 외부에 막대한 거버넌스 엔지니어링 리소스 투자를 요구합니다 [5, 22]. 기업은 신속한 프로토타이핑 이점과 데이터 오류로 인한 연쇄 실패 위험(Cascading failures) 사이에서 적절한 도입 시기를 결정해야 하는 트레이드오프에 직면합니다 [6, 22]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Quality for AI Agent Harnesses.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Quality for AI Agent Harnesses.md new file mode 100644 index 00000000..43943dc9 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Data Quality for AI Agent Harnesses.md @@ -0,0 +1,30 @@ +# [[Data Quality for AI Agent Harnesses]] + +## 📌 Brief Summary +AI 에이전트 하네스에서 데이터 품질(Data Quality)은 에이전트의 컨텍스트 윈도우로 유입되는 입력 데이터의 신뢰성, 최신성 및 무결성을 보장하는 필수 인프라 요소를 의미합니다 [1-4]. 기존의 에이전트 프레임워크들은 에이전트의 실행과 제어 방식만 관리할 뿐 데이터 자체를 검증하지 못하여, 오염되거나 오래된 데이터가 에이전트의 환각(Hallucination) 및 연쇄 장애를 유발하는 주요 원인이 됩니다 [1, 3, 5, 6]. 이를 해결하기 위해 액티브 메타데이터, 데이터 계약, 리니지 추적 등을 통해 에이전트가 읽기 전에 데이터를 사전에 인증하는 전용 데이터 거버넌스 계층이 요구됩니다 [7-9]. + +## 📖 Core Content +* **데이터 품질 인프라의 필요성** + * 에이전트 AI 구현 시간의 80%는 프레임워크 구성이나 모델 선택이 아닌, 데이터 엔지니어링 및 거버넌스 작업에 소요됩니다 [6, 10]. 10개 기업 중 8개 기업이 에이전트 AI를 확장하는 데 있어 '데이터 한계'를 가장 큰 장애물로 꼽고 있습니다 [1, 3, 6]. + * 흔히 대규모 언어 모델(LLM)의 '환각(Hallucination)'으로 치부되는 문제의 상당수는 실제로는 일관성이 없거나, 오래되었거나, 부분적으로만 복제된 불량 데이터 소스를 에이전트가 읽었기 때문에 발생합니다 [1, 3]. + * OWASP(국제웹보안표준기구)의 에이전트 애플리케이션 Top 10 위험 요소에서도 불량 데이터 입력으로 인해 발생하는 '메모리 중독(Memory poisoning)'과 '연쇄 장애(Cascading failures)'가 심각한 보안 위험으로 지목되었습니다 [1, 3]. + +* **기존 오케스트레이션 프레임워크의 구조적 공백** + * LangGraph, CrewAI, AutoGen, Haystack 등 선도적인 에이전트 제어 프레임워크 및 RAG 프레임워크들은 에이전트의 상태, 도구 라우팅, 협업 방식은 훌륭하게 관리하지만, 에이전트에 공급되는 컨텍스트 데이터가 신뢰할 수 있다고 단순 가정해버리는 치명적인 구조적 한계가 있습니다 [2, 6, 11, 12]. + * 즉, 스키마 표류(Schema drift), 오래된 테이블, 인증되지 않은 소스 등은 아무런 검증 없이 프레임워크를 그대로 통과하게 됩니다 [5, 11, 13]. 어떤 오케스트레이션 프레임워크도 자체적으로 입력을 인증할 수는 없으며, 이는 데이터 계층의 몫입니다 [14]. + +* **에이전트 하네스를 위한 데이터 거버넌스 계층 (Atlan 사례)** + 에이전트 파이프라인의 데이터 품질을 통제하는 기판(Substrate)은 다음과 같은 핵심 기능을 통해 에이전트가 읽는 데이터의 신뢰성을 보장합니다 [4, 7]. + * **액티브 메타데이터 (Active metadata):** 데이터 시스템을 지속적으로 모니터링하여 실시간 인증 상태, 스키마 상태, 데이터 최신성 신호를 구조화된 컨텍스트로 제공합니다 [7]. + * **데이터 계약 (Data contracts):** 에이전트의 컨텍스트 윈도우에 데이터가 진입하기 전에 스키마 계약을 강제 검증하여, 에이전트가 잘못된 결과를 도출하기 이전에 스키마 표류를 선제적으로 차단합니다 [7]. + * **데이터 리니지 (Data lineage):** 엔드투엔드 컬럼(Column) 수준의 데이터 계보를 제공합니다. 에이전트의 출력이 틀렸을 때 실패 원인이 모델인지, 프롬프트인지, 원본 데이터인지 그 근본 원인(Root cause)을 추적할 수 있게 합니다 [8]. + * **인증 상태 (Certification status):** 데이터 스튜어드가 인증한 자산만 에이전트가 읽을 수 있도록 설정하여 기업 환경에서의 흔한 장애 원인을 제거합니다 [8]. + +## ⚖️ Trade-offs & Caveats +* **사후 관측(Observability) 도구의 한계성 (Post-hoc Limitation):** + AgentOps나 Langfuse와 같은 옵저버빌리티 및 모니터링 도구는 프로덕션 에이전트 스택의 필수 인프라이지만, 모두 에이전트가 실행된 '이후(Post-hoc)'에 발생하는 일만 기록한다는 결정적 제약이 있습니다 [2, 9, 15, 16]. 이 도구들은 에이전트가 잘못된 데이터 입력을 기반으로 오작동을 일으킨 결과는 잡아낼 수 있지만, 데이터 원천 단계에서 그 결함을 예방하지는 못합니다 [9, 15, 16]. 심지어 불량 입력 데이터로부터 도출된 모델 출력이라 하더라도 출력 자체에 대한 평가 점수는 높게 나올 수 있어 엔지니어에게 오해를 불러일으킬 위험(Trade-off)이 있습니다 [2]. +* **아키텍처 복잡도 증가 및 책임 분리 요구:** + 에이전트 시스템에서 발생 가능한 데이터 장애를 통제하려면, 에이전트 코딩 프레임워크 외에 별도의 '거버넌스 데이터 계층(Governed data layer)'을 반드시 추가로 구축해야 합니다 [4, 9, 14, 17]. 이는 인프라 선택 및 구축의 복잡성과 비용을 증가시킵니다. 데이터 인증 및 유효성 검사 책임은 프레임워크가 아닌 데이터 계층 인프라에 있으므로, 시스템 아키텍처 설계 시부터 실행 제어 도구와 데이터 품질 제어 도구를 별도로 묶어 통합해야 하는 운영상 부담이 존재합니다 [9, 14]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/E2B (Firecracker microVM).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/E2B (Firecracker microVM).md new file mode 100644 index 00000000..adb05e26 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/E2B (Firecracker microVM).md @@ -0,0 +1,16 @@ +# [[E2B (Firecracker microVM)]] + +## 📌 Brief Summary +E2B는 AI 에이전트의 도구 루프(Tool loops)를 위해 특별히 제작된 Firecracker 마이크로VM(microVM) 기반의 오픈소스 샌드박스 환경입니다 [1]. 약 150ms의 빠른 콜드 스타트(Cold start) 성능을 제공하며, 기존의 CI 시스템을 단순히 덧붙이는 방식이 아닌 '하네스 프리미티브(Harness Primitive)로서의 코드 실행'을 구현한 가장 명확한 참조 구현체(Reference implementation)로 평가받습니다 [1]. + +## 📖 Core Content +* **에이전트 맞춤형 샌드박스 인프라**: E2B는 AI 에이전트가 안전하게 코드를 실행할 수 있는 격리된 컨테이너 기반 샌드박스를 제공합니다 [1, 2]. HuggingFace의 `smolagents`와 같은 에이전트 라이브러리에서 Docker, Pyodide 등과 함께 주요 샌드박스 격리(Sandbox isolation) 옵션 중 하나로 기본 지원되고 있습니다 [3]. +* **기술적 사양 및 접근성**: Firecracker 마이크로VM을 활용하여 약 150ms 수준의 콜드 스타트를 달성했으며, Python 및 JavaScript SDK를 모두 제공하는 오픈소스 프로젝트로서 에이전트 프레임워크와의 원활한 통합을 지원합니다 [1]. +* **에이전트 샌드박스의 산업 기준점**: E2B는 현대 에이전트 샌드박스의 표준적 아키텍처로 기능하고 있습니다. 예를 들어, 텐센트 클라우드(Tencent Cloud)의 프로덕션 검증 마이크로VM 샌드박스인 CubeSandbox는 자사의 플랫폼을 'E2B와 호환되는 드롭인 대체재(E2B-compatible drop-in replacement)'라고 명시할 정도로, E2B는 고밀도 에이전트 실행 환경의 기준 규격 역할을 하고 있습니다 [4]. + +## ⚖️ Trade-offs & Caveats +* **타 샌드박스 아키텍처 대비 리소스 오버헤드**: E2B 및 Daytona와 같은 컨테이너 기반 샌드박스는 완전히 격리된 환경을 제공하지만 최신 대안 기술에 비해 효율성 면에서 한계를 보일 수 있습니다. V8 Isolate 기반으로 구축된 Cloudflare Dynamic Workers 샌드박스는 E2B와 비교하여 시작 속도가 100배 이상 빠르고(수 밀리초 수준), 메모리 효율성 역시 최대 100배 뛰어난 것으로 보고되어, E2B 방식이 상대적으로 시작 지연 시간과 메모리 소모가 크다는 반대 급부를 갖습니다 [2]. +* 그 외 E2B의 구체적인 부작용이나 추가적인 기술적 제약 사항에 대해서는 소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/HTTP+SSE.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/HTTP+SSE.md new file mode 100644 index 00000000..ab7ef6b1 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/HTTP+SSE.md @@ -0,0 +1,16 @@ +# [[HTTP+SSE]] + +## 📌 Brief Summary +HTTP+SSE(Server-Sent Events)는 모델 컨텍스트 프로토콜(MCP) 및 에이전트 하네스 환경에서 클라이언트와 원격 서버 간의 양방향 통신 및 실시간 스트리밍을 지원하기 위해 사용되는 전송 프로토콜 방식이다 [1, 2]. 2025년 11월 스펙 업데이트를 통해 'Streamable HTTP Transport'로 대체되며 그 기능이 발전하였으며, MCP 서버가 로컬 프로세스를 넘어 원격 서비스로 구동될 수 있도록 하는 핵심 통신 기반을 제공한다 [2]. 이를 통해 에이전트 시스템은 지속적인 스트리밍 이벤트를 주고받으며 자율적인 작업을 수행할 수 있다 [1, 2]. + +## 📖 Core Content +* **원격 서비스 통신 지원**: HTTP+SSE 구조를 계승한 전송 계층은 클라이언트가 서버로 메시지를 보낼 때 HTTP POST를 사용하고, 서버가 클라이언트로 응답할 때는 선택적인 GET 요청 기반의 SSE(Server-Sent Events) 스트림을 사용한다 [2]. 이를 통해 다중 클라이언트 연결 처리가 가능해졌으며, MCP 서버의 원격 배포가 실현되었다 [2]. +* **스트리머블 HTTP 전송(Streamable HTTP Transport)으로의 진화**: 초기의 HTTP+SSE 전송 방식은 2025년 11월 25일 제정된 사양(Spec)에 따라 'Streamable HTTP Transport'로 대체 및 통합되었다 [2]. +* **관리형 에이전트 하네스에서의 활용**: 2026년 4월 퍼블릭 베타로 출시된 Anthropic의 Claude Managed Agents 플랫폼과 같은 완전 관리형 하네스 환경에서도 안전한 샌드박싱 시스템, 내장 도구들과 함께 서버 전송 이벤트(SSE) 스트리밍 기능이 기본적으로 지원된다 [1]. + +## ⚖️ Trade-offs & Caveats +* **세션 관리의 복잡성과 로드 밸런서 충돌**: HTTP+SSE 기반의 스트리밍 전송은 원격 배포를 가능하게 만들었으나 세션 관리 측면에서 큰 복잡성을 유발한다 [2]. 특히 연결 상태를 유지해야 하는(Stateful) `Mcp-Session-Id` 헤더가 로드 밸런서의 트래픽 분산 메커니즘이나 수평적 확장(Horizontal scaling) 구조와 직접적으로 충돌하는 문제가 발생한다 [2]. +* **구조적 개선의 필요성**: 이러한 확장성 한계 및 세션 유지 제약을 극복하기 위해, 2026년 MCP 로드맵에서는 전송 계층(Transport layer)으로부터 세션을 완전히 분리(Decoupling)하는 아키텍처 개선안을 주요 해결 과제로 삼고 있다 [2]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Hallucination (환각).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Hallucination (환각).md new file mode 100644 index 00000000..26c7516d --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Hallucination (환각).md @@ -0,0 +1,17 @@ +# [[Hallucination (환각)]] + +## 📌 Brief Summary +에이전트 시스템에서 환각(Hallucination)이란 대규모 언어 모델(LLM)이 잘못된 매개변수로 함수를 호출하거나 존재하지 않는 API를 참조하는 등 사실이 아닌 결과를 생성하는 현상을 의미합니다 [1]. 많은 경우 LLM 자체의 결함으로 여겨지는 환각은 실제로는 일관성이 없거나 오래된(stale) 데이터 소스가 입력된 결과로 발생합니다 [2, 3]. 에이전트 하네스는 도구 호출을 사전에 검증하고 데이터 거버넌스를 통해 입력 품질을 통제함으로써 이러한 환각을 완화하는 핵심 역할을 수행합니다 [1, 3]. + +## 📖 Core Content +* **데이터 품질과 환각의 상관관계**: 흔히 LLM의 자체적인 환각이라고 치부되는 문제의 상당수는 실제로는 일관성이 없거나, 오래되었거나, 부분적으로만 복제된 데이터 소스를 에이전트가 읽었기 때문에 발생하는 결과입니다 [2, 3]. 즉, 나쁜 입력 데이터가 주어지면 에이전트는 그 데이터를 바탕으로 잘못된 행동을 하게 됩니다 [4]. +* **도구 호출 환각 (Hallucinated Tool Calls)**: 모델이 외부 시스템과 상호작용할 때, 잘못된 매개변수 유형을 사용하거나 존재하지도 않는 API 함수를 호출하는 환각을 일으킬 수 있습니다 [1]. 또한, 실제로는 작업이 완료되지 않았음에도 완료되었다고 허위로 선언하는 형태의 환각도 발생합니다 [5]. 적절한 검증이 없다면 에이전트는 이렇게 망가진 호출을 계속 재시도하며 토큰만 낭비하게 됩니다 [1]. +* **에이전트 하네스를 통한 환각 억제**: 하네스 인프라는 모델이 외부 시스템에 직접 접근하지 못하게 하고, 도구 호출을 가로채어 유효성을 검사하여 환각적 호출의 영향을 차단합니다 [6]. 또한 DeepEval과 같은 평가 프레임워크는 환각 여부를 측정하는 내장 지표(metrics)를 제공하여 에이전트 출력 품질을 검증할 수 있게 돕습니다 [7]. 가장 근본적으로는 Atlan과 같은 거버넌스 데이터 계층을 활용하여 에이전트가 읽는 데이터 자체를 사전에 인증하고 스키마 변동을 방지함으로써 입력 단계에서부터 환각의 원인을 제거합니다 [8, 9]. + +## ⚖️ Trade-offs & Caveats +에이전트의 환각적 행동이나 잘못된 출력을 파악하기 위해 AgentOps나 Langfuse 같은 사후 모니터링 도구(Observability tools)를 활용할 수 있지만, 이러한 도구들은 실패가 발생한 이후에 이를 포착하는 사후적(post-hoc) 방식이라는 근본적인 제약이 있습니다 [10, 11]. 따라서 나쁜 입력(bad inputs)으로 인해 생성된 환각 데이터라 할지라도 평가 프레임워크 상에서는 높은 점수를 기록할 수 있으며, 이는 개발자에게 큰 오해를 불러일으킬 수 있습니다 [12]. + +또한 환각을 근본적으로 막기 위해 입력 데이터를 사전에 검증하는 데이터 계층을 하네스 파이프라인에 결합할 경우, 단순히 프레임워크를 구성하는 것을 넘어 데이터 거버넌스와 엔지니어링 작업에 전체 구현 시간의 80%가 소요될 정도로 높은 비용과 조직적 구축 부담이 발생한다는 트레이드오프가 존재합니다 [2, 13]. 환각 등을 추적하기 위해 도입되는 가시성 도구들 역시 각각 12%에서 15%에 이르는 시스템 성능 오버헤드를 유발하여 전체 인프라의 처리 속도에 영향을 미칠 수 있습니다 [14, 15]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness Multiplier.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness Multiplier.md new file mode 100644 index 00000000..da980345 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness Multiplier.md @@ -0,0 +1,22 @@ +# [[Harness Multiplier]] + +## 📌 Brief Summary +하네스 승수(Harness Multiplier)는 인공지능 모델의 순수 추론 능력을 실제 프로덕션 환경에서의 작업 완료 능력으로 변환해 주는 효율성을 의미하는 개념이다 [1, 2]. 에이전트 시스템의 실제 생산 성능은 '모델의 역량(Model Capability)'과 '하네스 승수'의 곱으로 구성된다 [1, 3]. 동일한 모델이라도 실행되는 인프라(하네스) 환경에 따라 성능이 극적으로 달라지며, 경우에 따라서는 최신 모델로의 업그레이드보다 기존 모델의 하네스 최적화가 더 큰 성능 향상을 가져다준다 [2, 4, 5]. + +## 📖 Core Content +* **성능의 구성 공식:** 실제 프로덕션 환경에서 AI 에이전트가 보여주는 성능은 모델 자체의 능력만으로 결정되지 않으며, `생산 성능 = 모델 역량 × 하네스 승수`라는 공식으로 분해하여 평가되어야 한다 [1]. 모델을 단일 참조 하네스에 고립시켜 평가하는 기존의 벤치마크 방식은 실제 도입 시의 성능을 제대로 예측하지 못한다 [3, 6]. +* **하네스 승수의 극적인 효과:** 동일한 주간에 측정된 실험에 따르면, GPT-5.5 모델이 OpenAI의 네이티브 Codex 하네스 환경에서는 61.5%의 기능성 점수를 기록했으나 Cursor 하네스에서는 87.2%를 기록하였다 [4, 5]. 무려 25.7%포인트의 성능 향상은 모델 업그레이드나 프롬프트 개선이 아닌, 오직 런타임 환경(하네스)의 교체로 인한 승수 효과이다 [2, 4, 5, 7]. +* **하네스 승수의 5대 핵심 차원:** 하네스 승수의 크기(효율성)를 결정하는 인프라의 주요 차원은 다음과 같이 세분화된다 [1, 2]. + * **컨텍스트 관리의 정교함(Context Management):** 모델에게 언제 어떠한 정보를 제공하고 불필요한 데이터를 제거할지 결정하는 알고리즘적 관리 수준 [1, 2]. + * **도구 통합의 깊이(Tool Integration Depth):** 단순한 도구 호출에 그치지 않고 실패를 감지해 재시도하거나 대체 경로를 찾는 실행 능력 [1, 2]. + * **메모리의 연속성(Memory Continuity):** 세션 간 이전 단계의 성공 및 실패 맥락을 유지하여 중복된 작업을 방지하는 능력 [1, 2]. + * **검증 메커니즘(Verification Mechanisms):** 사람의 확인이 이루어지기 전에 에이전트 스스로 결과를 테스트하고 교정하는 루프 [1, 2]. + * **다중 에이전트 조율(Multi-agent Coordination):** 복잡한 작업을 분해하고 여러 에이전트 간의 역할을 분배하는 능력 [1]. + +## ⚖️ Trade-offs & Caveats +* **블랙박스 시스템에서의 분리 평가 한계:** 폐쇄형(Closed-source) 독점 시스템의 경우 모델과 하네스 아키텍처가 불투명하게 결합되어 있어, 성과 향상이 모델의 역량 덕분인지 하네스 승수에 의한 것인지 그 기여도를 명확히 분리해 내기 불가능하다는 제약이 있다 [8]. +* **평가 환경 구축의 복잡성:** 하네스 승수를 정확하게 측정하고 최적화하려면 단순히 범용 벤치마크 점수에 의존할 수 없으며, 조직 내부의 실제 업무를 반영하는 자체 작업 샘플(Internal task sets)을 필수적으로 준비해야 한다 [6, 8]. +* **성과 기여도 파악을 위한 오버헤드:** 특정 벤더가 새로운 모델 버전과 함께 하네스 업데이트를 동시에 배포할 경우, 성능 향상의 정확한 원인을 진단하기 위해 '구형 하네스에서의 신형 모델'과 '신형 하네스에서의 구형 모델'을 각각 교차로 평가하는(Ablation protocol) 복잡한 평가 절차가 요구된다 [1, 9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness-as-a-Service.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness-as-a-Service.md new file mode 100644 index 00000000..c4f32ffb --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Harness-as-a-Service.md @@ -0,0 +1,20 @@ +# [[Harness-as-a-Service]] + +## 📌 Brief Summary +Harness-as-a-Service(HaaS)는 개발자가 에이전트 구동을 위한 복잡한 인프라를 직접 구축하는 대신, 사전 구축 및 검증된 런타임 환경을 서비스 형태로 구독하여 사용하는 새로운 인프라 카테고리이다 [1-3]. AWS가 컴퓨팅 자원을 제공하고 Stripe가 결제망을 제공하듯, HaaS는 에이전트 루프, 도구 디스패치, 샌드박싱 등의 인프라에 대한 접근 권한을 판매한다 [2]. 사용자는 원하는 모델, 사용할 도구, 그리고 수행할 작업 세 가지만 제공하면 되며, 그 이면의 복잡한 기술적 요소들은 서비스 제공자에 의해 모두 처리된다 [4]. + +## 📖 Core Content +* **인프라의 서비스화 (Infrastructure as a Service):** 초기 에이전트 구축 방식(예: OpenClaw 등)에서는 개발자가 모델 선택부터 시스템 프롬프트 작성, 도구 정의, 에이전트 루프 구축, 컨텍스트 관리, 오류 처리, 하위 에이전트 조율, 상태 지속성까지 모든 계층을 직접 조립하고 유지보수해야 했다 [2]. 반면 HaaS 모델에서는 이 모든 것이 관련 계층을 전담하는 전문가 팀에 의해 사전에 구축되고 미세 조정된 상태로 제공되어, 개발자는 인프라 구성 대신 에이전트의 작업 논리에만 집중할 수 있게 된다 [2, 5]. +* **사전 구축된 하네스 기능 탑재:** 관리형 하네스 플랫폼은 보안이 보장된 샌드박스, 에러 핸들링, 서버 전송 이벤트(SSE) 기반의 스트리밍, 자동화된 컨텍스트 압축(Context Compression) 및 상태 관리 기능 등을 포괄적으로 제공한다 [2, 3, 5]. +* **주요 벤더의 HaaS 시장 진출 사례:** + * **Anthropic:** 자율 에이전트로서 Claude를 실행하기 위한 완전 관리형 에이전트 하네스인 'Claude Managed Agents'를 퍼블릭 베타로 출시하여 지속성 있는 에이전트 운영에 따른 인프라 복잡성을 해소하고 있다 [1, 5]. + * **Microsoft:** 모든 에이전트가 고유의 컴퓨터를 가져야 한다는 철학 아래 Foundry에 호스팅형 에이전트를 출시했다. 이는 영구적 상태(Durable state), 내장된 신원 확인 및 거버넌스, 그리고 다양한 하네스와 프레임워크를 지원하는 엔터프라이즈급 전용 샌드박스를 제공한다 [1]. + * **기타 오케스트레이션 플랫폼:** OpenAI 역시 자체 Agents SDK를 대폭 업데이트하였으며, MindStudio와 같은 플랫폼은 시각적 빌더와 방대한 통합(Integration) 풀을 통해 오케스트레이션 코드를 밑바닥부터 짜지 않도록 지원하는 유사한 접근 방식을 취하고 있다 [1, 4]. + +## ⚖️ Trade-offs & Caveats +* **벤더 및 프레임워크 종속성(Vendor Lock-in) 문제:** 특정 HaaS 제공자의 클라우드 런타임과 관측성(Observability) 도구에 지나치게 의존할 경우, 향후 다른 인프라 환경이나 오픈소스 프레임워크로 에이전트 코드를 마이그레이션하기 어려워지는 종속성 문제가 발생할 수 있다 [6-8]. +* **데이터 품질 검증의 한계:** 관리형 하네스 서비스는 에이전트가 '어떻게 실행되는가(오케스트레이션)'는 훌륭히 제어하지만, 에이전트가 '무엇을 읽어 들이는가(입력 데이터)'에 대한 거버넌스는 제공하지 않는다 [9]. 즉, 제공된 데이터가 스키마가 변형되었거나 오래되고 인증되지 않은 데이터일 경우 HaaS 자체적으로는 이를 차단할 수 없으므로, 데이터 품질 오류로 인한 에이전트의 연쇄적 실패를 막기 위해서는 별도의 데이터 거버넌스 인프라를 구축해야 하는 제약이 존재한다 [9-11]. +* **보안 경계와 내부 통제력의 교환:** HaaS는 자체 호스팅(Self-hosting) 방식과 비교하여 소규모 팀의 운영 부담을 획기적으로 줄여주지만, 에이전트의 관측 데이터와 실행 트레이스가 외부 서비스에 종속된다 [8]. 따라서 조직 자체의 엄격한 보안 경계(Security perimeter) 내에 모든 데이터를 보관해야 하는 규제 산업이나 특수 환경에서는 클라우드 기반 관리형 하네스의 도입이 보안 정책상 반대 급부로 작용할 수 있다 [8]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/K9 Tactical Gear (경찰견 전술 장비).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/K9 Tactical Gear (경찰견 전술 장비).md new file mode 100644 index 00000000..e2357eba --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/K9 Tactical Gear (경찰견 전술 장비).md @@ -0,0 +1,27 @@ +# [[K9 Tactical Gear (경찰견 전술 장비)]] + +## 📌 Brief 시 Summary +K9 전술 장비(K9 Tactical Gear)는 법 집행 기관, 군사 작전, 수색 구조 및 재난 대응 분야에서 활약하는 작업견(Working dogs)이 임무를 안전하고 효과적으로 수행할 수 있도록 특수하게 설계된 장비이다 [1]. 이러한 장비는 작업견의 보호, 기능성, 편안함을 최우선으로 고려하며 방탄조끼, 모듈형 운송 팩, 전술 목줄 및 하네스 등으로 구성된다 [2]. 소프트웨어 분야의 '에이전트 하네스'가 AI 모델의 한계를 보완하고 통제하듯, K9 전술 하네스 역시 생물학적 에이전트인 작업견이 고위험 환경에서 안전하게 임무를 수행하고 핸들러와 통신 및 제어할 수 있도록 돕는 물리적 인프라 역할을 수행한다 [3]. + +## 📖 Core Content +* **방어 및 보호 시스템 (K9 Tactical Vests):** + * K9 전술 조끼는 탄도 위협, 환경적 위험, 물리적 긴장으로부터 작업견을 보호하기 위해 설계되었다 [2]. + * NIJ Level IIIA 등급의 소프트 아머 패널을 적용하여 .44 매그넘 총탄 등 권총탄을 최대 6회까지 방어하고 파편을 막아내는 방탄 능력을 제공한다 [2-4]. + * 1000D 코듀라(Cordura)나 립스톱 나일론 같은 내마모성 고강도 소재로 제작되며, 과열을 방지하기 위해 통기성이 뛰어난 메쉬 안감을 사용한다 [2-5]. +* **모듈형 확장성 및 제어 (MOLLE & Handling):** + * 조끼와 하네스 양측에는 MOLLE(Modular Lightweight Load-carrying Equipment) 웨빙이 적용되어 의료 키트, 물병, 카메라, GPS 장치 등 임무 특화 장비를 부착할 수 있다 [2, 3, 6]. + * 위험한 지형에서 작업견을 들어 올리거나 즉각적으로 물리적 제어를 할 수 있도록 튼튼한 운반용 핸들(Carry handles)과 금속 리쉬(Leash) 부착 지점이 제공된다 [2, 3, 6]. + * 부대 식별이나 특성을 나타낼 수 있는 패치 부착용 벨크로 패널 및 야간 시야 확보용 반사 스트립 등이 포함된다 [2, 6]. +* **운송 및 보조 장비 (Packs & Accessories):** + * 장기 임무 시 식수, 응급처치 용품 등을 운반할 수 있는 모듈형 배낭을 사용하며, 방수 수납공간을 갖추어 젖은 환경에서도 장비를 보호한다 [5]. + * 응급 상황 시 신속하게 장비를 해제할 수 있는 퀵 릴리스 버클, 거친 지형의 열이나 날카로운 파편으로부터 발을 보호하는 보호 부츠, 무더운 기후에서 체온을 조절하는 쿨링 조끼 등이 활용된다 [7, 8]. + +## ⚖️ Trade-offs & Caveats +* **하중의 제약 및 체력적 한계 (Weight Limits & Strain):** K9이 장비를 착용할 때 무게 제약이 가장 큰 반대급부로 작용한다. FEMA 지침에 따르면 작업견에게 체력적 무리를 주지 않기 위해 장비 팩의 총 무게는 작업견 체중의 25%를 초과해서는 안 된다 [5]. 무거운 방탄 플레이트나 추가 장비의 부착은 이동성을 저하시킬 수 있다. +* **임무 특성에 따른 장비 절충 (Mission-Specific Selection):** 보호력과 기동성 사이에는 명확한 트레이드오프가 존재한다. 예를 들어, 무장 대치 상황에 투입되는 SWAT 팀 작업견은 다소 무겁더라도 탄도 아머(방탄조끼)가 필수적인 반면, 광활한 야생에서 임무를 수행하는 수색구조견에게는 무거운 아머보다는 가볍고 통기성이 뛰어난 조끼가 생존과 임무 수행에 훨씬 유리하다 [9]. +* **핏(Fit) 불일치로 인한 이동성 저해 위험:** 크기가 맞지 않는 장비를 착용하면 작업견의 기동성이 크게 손상될 수 있다. 따라서 개체의 가슴, 목, 길이 등을 정확하게 측정하여 움직임을 구속하지 않는 제품을 선택해야 하는 까다로움이 따른다 [2, 9]. +* **지속적인 유지보수 요구:** 고강도의 활동에 노출되므로 장비의 파손 여부를 정기적으로 검사하고 순한 비누로 세척하는 등 꼼꼼한 관리 절차가 필수적으로 요구된다 [9]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kernel-level Isolation.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kernel-level Isolation.md new file mode 100644 index 00000000..1941a1f7 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kernel-level Isolation.md @@ -0,0 +1,19 @@ +# [[Kernel-level Isolation]] + +## 📌 Brief Summary +커널 수준 격리(Kernel-level Isolation)는 AI 에이전트의 샌드박스 실행 환경에서 호스트 시스템과 에이전트의 워크로드를 운영체제 커널 차원에서 엄격하게 분리하여 높은 수준의 보안을 제공하는 아키텍처 원리입니다 [1, 2]. 에이전트가 자율적으로 실행하는 코드가 시스템을 훼손하는 것을 방지하고 리소스 사용을 제한하며, 환경 자체에 제약을 강제하여 에이전트가 손상되더라도 이를 우회할 수 없도록 만듭니다 [1, 2]. + +## 📖 Core Content +* **LangSmith Sandboxes**: 마이크로VM(microVM) 기반의 샌드박싱 아키텍처를 사용하여 커널 수준의 격리를 제공합니다 [1]. CPU, 메모리, 디스크 등의 리소스 캡(caps)을 설정하고, 런타임 환경에서 비밀 데이터(secrets)를 완전히 배제하는 인증 프록시를 결합하여 안전한 코드 실행을 지원합니다 [1]. +* **NVIDIA OpenShell**: 자율 AI 에이전트를 위한 오픈소스 정책 기반 샌드박스 런타임으로, Landlock LSM(파일 시스템 제어)과 seccomp BPF(시스템 호출 제어)를 통해 커널 수준에서 보안 제약을 강제합니다 [2]. 제약 조건이 환경 자체에 적용되므로, 손상된 에이전트라 할지라도 이를 재정의(override)할 수 없는 강력한 보안성을 보장합니다 [2]. +* **Kubernetes Agent Sandbox**: AI 에이전트 런타임을 위해 격리되고 상태를 유지하는 단일 워크로드를 관리하는 K8s 네이티브 Sandbox CRD입니다 [3]. 커널 수준 격리를 구현하기 위해 gVisor 및 Kata Containers 기술을 지원합니다 [3]. +* **CubeSandbox**: Tencent Cloud가 검증한 프로덕션용 마이크로VM 샌드박스로, eBPF로 강제되는 네트워크 정책과 함께 진정한 커널 수준 격리를 제공합니다 [3]. 스냅샷 클로닝을 통해 60ms 미만의 빠른 콜드 스타트 성능과 인스턴스당 5MB 미만의 낮은 오버헤드를 달성한 사례입니다 [3]. + +## ⚖️ Trade-offs & Caveats +소스 데이터에는 커널 수준 격리 기술 자체의 직접적인 부작용이나 단점에 대한 정보는 다소 부족합니다. + +다만, 샌드박스 아키텍처 선택 관점에서 보았을 때, 커널 수준 격리를 주로 사용하는 마이크로VM이나 컨테이너 기반 샌드박스(예: E2B, Daytona 등)는 강력한 보안과 환경 분리를 제공하는 대신 다른 경량 아키텍처 대비 리소스 및 시작 속도 측면에서 반대 급부(Trade-off)가 존재할 수 있습니다 [2]. 예를 들어 V8 Isolate 기반 샌드박싱 기술(Cloudflare Dynamic Workers)은 메가바이트 단위의 메모리만 사용하여 수 밀리초 만에 격리 환경을 시작할 수 있으며, 이는 컨테이너 기반 샌드박스보다 최대 100배 더 빠르고 메모리 효율이 100배 더 높습니다 [2]. 즉, 커널 수준 격리를 채택할 경우 고도의 보안성을 얻는 대신, 극단적인 경량 환경에 비해서는 속도와 리소스 효율이 낮아지는 제약이 따를 수 있습니다 [2]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kubernetes Agent Sandbox.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kubernetes Agent Sandbox.md new file mode 100644 index 00000000..63443cb5 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Kubernetes Agent Sandbox.md @@ -0,0 +1,18 @@ +# [[Kubernetes Agent Sandbox]] + +## 📌 Brief Summary +Kubernetes Agent Sandbox는 AI 에이전트 런타임을 위한 격리되고 상태를 유지하며 단일 인스턴스로 실행되는(singleton) 워크로드를 관리하기 위해 선언적이고 표준화된 API를 제공하는 K8s 네이티브 Sandbox CRD(Custom Resource Definition)입니다 [1]. SIG Apps 산하에서 개발되었으며, 커널 수준의 격리를 지원하여 에이전트를 안전하게 실행할 수 있도록 돕습니다 [1]. 특히 에이전트가 기존 쿠버네티스(Kubernetes) 인프라 내부에서 실행되어야 할 때 가장 적합한 아키텍처를 제공합니다 [1]. + +## 📖 Core Content +* **선언적 API 및 워크로드 관리:** AI 에이전트의 워크로드를 관리하기 위해 특별히 설계된 쿠버네티스 네이티브 CRD로, 상태 보존형(stateful) 및 싱글톤 워크로드 제어를 위한 선언적(declarative)이고 표준화된 API를 제공합니다 [1]. +* **강력한 커널 수준 격리 (Kernel-level Isolation):** 에이전트가 수행하는 코드가 호스트 환경에 위험을 초래하지 않도록 보장하기 위해 gVisor 및 Kata Containers를 지원하여 커널 수준에서 완벽한 격리를 구현합니다 [1]. +* **네트워크 보안 아키텍처:** 버전 0.2.1 업데이트를 통해 공유 정책 모델(shared policy model) 기반으로 엄격한 네트워크 격리를 강제하는 '기본 보안(Secure by Default)' 네트워킹 아키텍처가 도입되었습니다 [1]. +* **생태계 내 호환성:** Alibaba OpenSandbox와 같은 범용 AI 에이전트 샌드박스 플랫폼에서도 쿠버네티스와 도커(Docker) 런타임 전반에 걸쳐 통합된 API 형식으로 지원되어, 안전한 컨테이너 런타임 구성 시 널리 활용되고 있습니다 [1]. + +## ⚖️ Trade-offs & Caveats +* **시동 시간(Startup Time)의 한계:** 현대적인 에이전트 주도 개발 워크플로우는 100ms 미만의 초고속 시동 속도를 요구하지만, 대부분의 쿠버네티스(K8s) 기반 접근 방식이나 전통적인 가상 머신(VM) 방식으로는 이러한 빠른 실행 속도 기준을 달성하기 어렵다는 명확한 제약이 존재합니다 [2]. +* **자원 효율성 단점:** V8 Isolate 기반의 샌드박스(예: Cloudflare Dynamic Workers)가 밀리초 단위로 시동되고 메모리를 극히 적게 사용하는 것에 비해, 쿠버네티스를 포함한 컨테이너 기반 샌드박스 구조는 최대 100배 느리고 메모리 효율성도 최대 100배 낮다는 아키텍처 상의 제약과 반대급부를 가집니다 [3]. +* **기존 인프라 종속성:** 본 솔루션은 기존에 이미 쿠버네티스 인프라를 사용하고 있으며 그 내부에서 에이전트를 구동해야 하는 특정한 환경에서만 올바른 선택(right choice)이 되므로 [1], 쿠버네티스 환경이 아닌 곳에 도입할 때는 오버헤드가 발생할 수 있습니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/L3 Meta-Factory.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/L3 Meta-Factory.md new file mode 100644 index 00000000..9038acb0 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/L3 Meta-Factory.md @@ -0,0 +1,18 @@ +# [[L3 Meta-Factory]] + +## 📌 Brief Summary +L3 Meta-Factory는 단순한 에이전트 하네스 실행 환경을 넘어 "다른 하네스들을 생성하는 층"으로 기능하는 Claude Code 생태계의 최상위 아키텍처 계층이다 [1, 2]. 이 계층은 사용자의 자연어 도메인 설명을 바탕으로 전문 에이전트 팀 구조, 런타임 설정, 그리고 에이전트가 사용할 스킬 파일들을 자동으로 찍어내는(factory) 역할을 수행한다 [1, 2]. 목적과 생성 결과물에 따라 팀 아키텍처 팩토리(Team-Architecture Factory)나 런타임 설정 팩토리(Runtime-Configuration Factory) 등 여러 서브 층으로 세분화된다 [1, 3]. + +## 📖 Core Content +* **L3 Meta-Factory의 핵심 역할**: 에이전트를 조율하는 단일 하네스를 운영하는 것을 넘어, 주어진 과제에 맞는 에이전트 하네스 구조 자체를 동적으로 생성하는 메타 인프라 역할을 한다 [1]. 사용자가 "하네스 구성해줘"와 같은 명령을 내리면 도메인을 분석해 에이전트 정의(`.claude/agents/`)와 스킬(`.claude/skills/`)을 자동 생성해 준다 [2]. +* **주요 서브 층(Sub-layers)의 구분**: + * **Team-Architecture Factory**: 팀 구조, 메시지 프로토콜, 리뷰 게이트 등 에이전트 팀 아키텍처와 스킬을 뽑아내는 데 특화된 층이다 [3, 4]. `revfactory/harness`가 대표적이며 파이프라인, 팬아웃/팬인, 전문가 풀, 생성-검증, 감독자, 계층적 위임 등 6가지 사전 정의된 아키텍처 패턴을 지원한다 [1, 2]. + * **Runtime-Configuration Factory**: 결정적(deterministic)이고 반복 가능한 런타임 설정을 생성하는 데 특화된 층으로, `coleam00/Archon`이 대표적인 프레임워크다 [1, 3, 4]. + * **Codex Runtime Port**: 메타 팩토리 컨셉을 Codex 런타임 환경에 맞게 구현한 층이며, `SaehwanPark/meta-harness`가 여기에 속한다 [1, 3, 5]. +* **모듈형 운영 및 조합 방식**: 동일한 L3 계층 내에 존재하더라도 각 서브 층의 용도는 명확히 분리된다 [3]. 팀 아키텍처의 설계가 필요할 때는 Team-Architecture Factory를 활용하고, 런타임 결정성이 필요할 때는 Runtime-Configuration Factory를 사용하며, 필요시 두 팩토리를 조합(아키텍처 설계 후 런타임에 배포)하여 상호 보완적으로 운용할 수 있다 [3, 4]. + +## ⚖️ Trade-offs & Caveats +소스에 L3 Meta-Factory 아키텍처 도입에 따른 직접적인 부작용이나 최적화의 기술적 한계에 대한 구체적인 관련 정보가 부족합니다. 다만, 단일 팩토리가 모든 하네스 구성 요소를 완벽하게 제공하지 않으므로 목적에 따른 팩토리의 분리 및 조합이 필수적이라는 제약 사항이 존재한다 [3, 4]. 예를 들어 팀 아키텍처 설계 기능과 런타임 결정성 보장 기능은 서로 다른 서브 층에서 개별적으로 처리되므로, 두 가지 요구사항을 모두 충족하려면 서로 다른 팩토리(예: `revfactory/harness`와 `coleam00/Archon`)를 명시적으로 구분하여 조합해야 하는 파이프라인 설계상의 복잡성이 수반된다 [3, 4]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM 가시성 플랫폼 (LLMOps Observability).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM 가시성 플랫폼 (LLMOps Observability).md new file mode 100644 index 00000000..86682266 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM 가시성 플랫폼 (LLMOps Observability).md @@ -0,0 +1,18 @@ +# [[LLM 가시성 플랫폼 (LLMOps Observability)]] + +## 📌 Brief Summary +LLM 가시성 플랫폼(LLMOps Observability)은 에이전트 하네스 외부 또는 측면에 위치하여 에이전트 실행 이후에 일어난 상황을 기록하고 모니터링하는 필수 인프라 도구이다[1]. 이 플랫폼은 세션 리플레이, 모델 호출, 지연 시간(Latency), 프롬프트 관리, 비용, 다중 에이전트 간의 상호작용 등을 사후적으로 추적(Trace)하고 분석한다[2, 3]. 대표적인 도구로는 AgentOps, Langfuse, LangSmith, Braintrust 등이 있으며, 개발자가 에이전트의 복잡한 실행 과정을 디버깅하고 성능을 평가할 수 있도록 지원한다[4-6]. + +## 📖 Core Content +* **상세 추적 및 모니터링 (Tracing & Monitoring)**: 가시성 플랫폼은 에이전트의 모든 추론 단계, 도구 호출, 검색 단계를 추적한다. 예를 들어 LangSmith는 지연 시간, 토큰 수, 비용 등의 지표를 포함하여 에이전트의 모든 작업을 저장해 대규모 실패 모드를 파악하는 데 사용된다[6, 7]. Langfuse는 프롬프트 버전 관리, 평가 파이프라인 등을 내장하여 LLM 호출을 프롬프트, 입력 및 출력과 연결해 스팬(Span) 수준에서 추적한다[3, 8]. +* **배포 후 세션 포렌식 (Session Replay & Debugging)**: AgentOps와 같은 도구는 세션 리플레이 기능을 제공하여 엔지니어가 에이전트 실패 시 정확히 어떤 일이 발생했는지 포렌식 분석을 수행할 수 있게 한다[2]. Braintrust는 도구 호출과 검색 단계를 중첩된 계층(Nested span hierarchies)으로 포착하여 샘플링 없이 전체 트레이스를 검색함으로써 다중 턴 에이전트 실패의 근본 원인을 찾도록 돕는다[5]. +* **인프라 및 시스템 수준 데이터 통합**: OpenObserve 등은 LLM 추적 데이터와 인프라 로그 및 지표를 통합한다[5]. 이를 통해 단순한 LLM 호출 추적을 넘어, 네트워크 지연이나 GPU 메모리 압박 등 에이전트 실패를 설명할 수 있는 시스템 수준의 이벤트와 에이전트 결정을 연관 지어 분석할 수 있다[5]. +* **자체 호스팅 및 데이터 종속성 탈피 (Self-hosted Options)**: Langfuse와 Arize Phoenix 같은 도구는 자체 호스팅이 가능하여 제3자 클라우드로 데이터를 전송하지 않고도 오프저버빌리티 데이터를 조직 고유의 보안 경계 내에 유지할 수 있도록 지원한다[5, 8]. 이는 관측 데이터에 대한 특정 벤더 종속(Vendor lock-in)을 방지하는 이점을 제공한다[3, 8]. + +## ⚖️ Trade-offs & Caveats +* **사후(Post-hoc) 분석의 근본적 한계와 입력 데이터 무결성 검증 부재**: 가시성 플랫폼은 에이전트 프레임워크 옆에 위치하여 **에이전트가 실행된 이후(Post-hoc)에만 실패를 포착**한다는 결정적인 제약이 있다[1, 9]. 즉, 프롬프트나 출력 결과는 평가할 수 있으나, 에이전트가 읽어 들인 소스 데이터가 오래되었거나, 인증되지 않았거나, 스키마가 변형되었는지 여부는 모니터링하지 못한다[10]. 세션 리플레이에서 에이전트가 자신 있게 잘못된 행동을 한 것으로 확인되더라도, 이는 '에이전트가 무엇을 했는지'를 보여줄 뿐 입력 데이터 자체가 부적절했음을 스스로 증명해 주지는 못한다[11, 12]. 따라서 데이터 소스의 오류로 인한 연쇄적 실패를 막으려면 별도의 데이터 거버넌스 인프라(Atlan 등)가 사전에 필요하다[9, 10, 13]. +* **성능 오버헤드 (Performance Overhead)**: 에이전트 모니터링과 로깅을 위해 실행되는 가시성 도구는 불가피하게 시스템 성능 저하를 동반한다. 예를 들어 AgentOps는 약 12%, Langfuse는 약 15%의 성능 오버헤드를 발생시키는 것으로 나타났다[2, 8]. +* **자체 호스팅의 운영 부담**: 데이터 주권과 벤더 독립성을 위해 Langfuse 등의 자체 호스팅 옵션을 선택할 경우, 조직이나 소규모 팀이 모니터링 인프라 자체를 별도로 유지 및 관리해야 하는 추가적인 운영 부담(Operational burden)이 발생한다[8]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM-as-judge.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM-as-judge.md new file mode 100644 index 00000000..07cc4aaf --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLM-as-judge.md @@ -0,0 +1,17 @@ +# [[LLM-as-judge]] + +## 📌 Brief Summary +LLM-as-judge는 인공지능 에이전트 하네스 환경에서 모델의 산출물이나 시스템의 동작을 평가하기 위해 대규모 언어 모델(LLM) 자체를 심사관(judge)으로 활용하는 추론적(Inferential) 제어 및 평가 방식이다 [1, 2]. 주로 AI 코드 리뷰, 의미론적 분석, 응답 품질의 지속적 샘플링 및 로그 이상 징후 탐지 등에 활용된다 [2, 3]. 이를 통해 인간 개발자가 모든 것을 검토하지 않고도 에이전트의 워크플로우를 테스트하고 신뢰할 수 있는 검증 루프를 구축할 수 있도록 돕는다 [1, 2]. + +## 📖 Core Content +* **추론적 피드백 센서로서의 역할:** 에이전트 하네스 내에서 LLM-as-judge는 의미론적 판단(Semantic judgment)이 필요한 문제를 다루는 '추론적 센서(Inferential sensor)'로 기능한다 [2, 4]. 린터(Linter)나 단위 테스트와 같이 빠르고 결정론적인 연산적(Computational) 센서와 달리, 문맥적 이해가 필요한 AI 코드 리뷰나 응답 품질 모니터링 등의 영역에서 에이전트의 상태를 감시하고 오류를 식별한다 [2, 3]. +* **평가 및 CI 파이프라인 통합:** 다양한 에이전트 프레임워크와 관측 도구들은 LLM-as-judge를 기본 평가 메커니즘으로 채택하고 있다. `promptfoo`, `Weights & Biases Weave`, `Mastra` 등의 도구는 LLM-as-judge를 내장하여 에이전트 산출물의 회귀 테스트를 CI(지속적 통합) 파이프라인에 직접 통합할 수 있도록 지원한다 [1, 5, 6]. +* **평가자 모델 역량에 대한 높은 의존성:** Red Hat의 평가 주도 개발(Eval-Driven Development) 사례 연구에 따르면, LLM-as-judge 역할을 수행하는 평가자 모델의 역량(Capability)은 평가의 정확도에 결정적인 영향을 미친다 [1]. 실제 실험에서 대형 모델(llama-3-3-70b)은 알려진 실패 사례를 모두 잡아낸 반면, 더 작은 모델들은 여러 실패 사례를 놓치는 한계를 보였다 [1]. 즉, 적절하고 강력한 모델을 평가자로 사용할 때만 시스템에 대한 실질적인 신뢰도를 높일 수 있다 [2]. + +## ⚖️ Trade-offs & Caveats +* **높은 비용 및 실행 지연:** LLM-as-judge는 GPU나 NPU 자원을 사용하기 때문에 전통적인 연산적 센서에 비해 실행 속도가 느리고 비용이 많이 든다 [2, 4]. 따라서 에이전트가 코드를 변경하는 모든 커밋(Commit)마다 LLM-as-judge를 실행하는 것은 경제적으로나 시간적으로 비효율적이다 [4]. +* **비결정성(Non-determinism)과 평가 피로:** 확률론적 모델에 기반하므로 평가 결과가 항상 100% 동일하게 보장되지 않는 비결정성을 띤다 [2, 4]. +* **설계적 제약:** 무분별한 LLM-as-judge의 사용은 막대한 평가 비용으로 인해 시스템 전체를 무너뜨릴 수 있으므로(eval cost collapse), 유의미한 리스크를 줄일 수 있는 핵심적인 위치에만 값비싼 검사를 추가하는 계층적 가드레일 설계가 필수적이다 [1]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps - AgentOps.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps - AgentOps.md new file mode 100644 index 00000000..323ca2cd --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps - AgentOps.md @@ -0,0 +1,19 @@ +# [[LLMOps / AgentOps]] + +## 📌 Brief 시 Summary +LLMOps/AgentOps는 AI 에이전트를 실험 단계의 프로토타입에서 신뢰할 수 있는 프로덕션 운영 환경으로 전환하고 관리하기 위한 인프라 및 운영 체계이다 [1, 2]. 이는 에이전트의 배포, 관측 가능성(Observability), 평가(Evaluation), 비용 관리 및 거버넌스를 포괄하는 실무 영역을 의미한다 [1, 3, 4]. 단순히 모델의 성능 향상에 그치지 않고, 에이전트가 실행하는 도구 호출, 상태 변화, 추론 궤적을 데이터로 추적하여 하네스 아키텍처를 지속적으로 디버깅하고 개선하는 데 핵심적인 목적이 있다 [5, 6]. + +## 📖 Core Content +* **관측 가능성(Observability) 및 추적(Tracing):** Langfuse, AgentOps, Braintrust 등의 플랫폼을 활용하여 LLM 호출, 프롬프트 관리, 도구 사용 내역, 비용, 지연 시간 등을 세션 및 스팬(Span) 단위로 정밀하게 추적한다 [4-6]. OpenTelemetry와 같은 표준 시맨틱 규칙을 사용하여 에이전트의 의사 결정을 인프라 시스템의 이벤트와 연관 지으며, 다중 턴 에이전트 실패의 근본 원인을 분석할 수 있도록 세션 리플레이 및 실행 그래프 시각화를 제공한다 [5-7]. +* **평가(Evaluation) 및 CI 파이프라인 통합:** promptfoo, DeepEval 등의 프레임워크를 통해 LLM을 심판(LLM-as-judge)으로 활용하여 에이전트 산출물을 평가하고 회귀 테스트를 수행한다 [4, 8]. 이는 에이전트 배포를 차단하는 평가 게이트(Evaluation gates) 역할을 수행하며, 사용자에게 도달하기 전 CI/CD 파이프라인 단에서 하네스의 성능 저하를 방지한다 [8, 9]. +* **비용 및 자원 최적화 (FinOps):** LiteLLM, OmniRoute와 같은 다중 공급자 게이트웨이를 사용하여 트래픽 부하 분산, 지능형 모델 라우팅, 실패 대체(Fallback)를 수행한다 [2, 10]. 토큰 예산뿐만 아니라 최대 루프 횟수, 도구 호출 캡, 실행 시간 초과(Timeout) 등 인프라 게이트웨이 수준의 엄격한 가드레일을 적용하여 통제되지 않은 에이전트의 비용 폭증을 방지한다 [2, 11]. +* **데이터 거버넌스 연동:** 에이전트에 입력되는 데이터 자체의 품질이 에이전트의 성공을 좌우하므로, Atlan과 같은 거버넌스 기반 기저층과 결합하여 에이전트가 읽는 데이터의 활성 메타데이터, 스키마 계약, 데이터 리니지 및 인증 상태를 사전에 검증한다 [12-14]. + +## ⚖️ Trade-offs & Caveats +* **사후 모니터링의 근본적 한계 (Post-hoc Observability):** AgentOps, Langfuse와 같은 대부분의 관측 도구는 에이전트가 실행된 이후에 작동하여 실패를 사후에(Post-hoc) 기록할 뿐, 오래되거나 손상된 입력 데이터로 인해 발생하는 에이전트의 실패 자체를 원천 차단하지는 못한다 [15-19]. 따라서, 오염된 입력 데이터를 기반으로 산출된 결과에 높은 평가 점수가 부여되는 착시 현상이 발생할 수 있다 [17]. +* **시스템 성능 오버헤드:** 에이전트 하네스에 추적 및 세션 모니터링 기능을 배치하여 실행할 경우, 약 12%에서 15%에 달하는 시스템 성능 오버헤드가 발생할 수 있다는 단점이 있다 [1, 4, 5]. +* **비결정적 특성에 따른 평가 비용 증가:** 에이전트 워크플로우의 비결정적(Non-deterministic)인 특성으로 인해 기존의 이분법적인 통과/실패(Pass/Fail) 테스트 방식은 실효성이 없다 [8]. 따라서 LLM-as-judge 등을 이용한 확률론적 평가와 행동 지문(Behavioral fingerprinting) 기반의 검증을 도입해야 하는데, 이는 상당한 연산 비용과 토큰 소모를 수반한다 [8]. +* **호스팅 방식에 따른 트레이드오프:** 자체 호스팅(Self-hosted) 형태의 LLMOps 도구는 특정 벤더에 대한 관측 데이터 종속성(Vendor lock-in)을 없애고 보안 경계 내에 데이터를 유지할 수 있다는 강점이 있으나, 소규모 개발 팀에게는 인프라를 직접 운영해야 하는 운영 부담을 더하게 된다 [1, 4]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps.md new file mode 100644 index 00000000..c4d7f321 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/LLMOps.md @@ -0,0 +1,18 @@ +# [[LLMOps]] + +## 📌 Brief Summary +LLMOps는 프로덕션 환경에서 대규모 언어 모델(LLM)과 AI 에이전트의 실행을 추적, 평가, 모니터링 및 관리하는 운영 체계를 의미합니다 [1]. 이를 위해 모델 호출, 프롬프트 관리, 평가 파이프라인 등을 통합적으로 지원하는 플랫폼이 활용되며 대표적인 오픈소스 LLMOps 도구로는 Langfuse가 있습니다 [1, 2]. 이 체계는 팀 단위의 협업과 자체 호스팅(Self-hosted) 환경을 통해 에이전트의 관측 가능성(Observability)을 확보하는 데 중점을 둡니다 [1, 2]. + +## 📖 Core Content +* **LLM 추적(Tracing) 및 모델 호출 연동:** LLMOps 플랫폼은 스팬(Span) 수준에서 LLM 호출을 추적하여, 모델의 호출 과정을 프롬프트, 입력(Input), 출력(Output)과 명확히 연결합니다 [2]. +* **프롬프트 관리 및 출력 평가 파이프라인:** 프롬프트의 버전을 체계적으로 관리하며, 특정 프롬프트 버전에 평가 점수를 연동합니다 [2]. 또한, 사전에 정의된 기준에 따라 모델의 출력물을 채점(Scoring)하는 평가 파이프라인을 내장하고 있습니다 [2]. +* **보안 및 자체 호스팅(Self-hosting) 지원:** LLMOps 환경은 특정 벤더에 대한 관측성 데이터 종속성(Vendor lock-in)을 방지하기 위해 자체 호스팅을 지원합니다 [1, 2]. 이를 통해 조직은 자체 보안 경계 내에서 데이터를 안전하게 보관할 수 있습니다 [2]. +* **팀 협업(Team Collaboration) 워크플로우:** 공유된 LLMOps 워크플로우를 통해 팀원들이 에이전트 실행의 추적(Traces) 데이터와 평가 결과에 공동으로 접근하고 분석할 수 있도록 지원합니다 [2]. + +## ⚖️ Trade-offs & Caveats +* **사후 처리(Post-hoc)의 근본적 한계:** LLMOps 및 관측성 도구들의 가장 큰 제약은 에이전트가 실행된 '이후'에 발생한 결과를 평가하고 모니터링한다는 점입니다 [3, 4]. 이 도구들은 모델의 출력과 프롬프트 성능은 평가할 수 있지만, 모델에 입력된 소스 데이터 자체가 오래되었거나 검증되지 않았거나 스키마가 변형되었는지 여부는 판단하지 못합니다 [4-6]. +* **오도된 평가 점수(Misleading Scores) 발생 위험:** 위와 같은 데이터 품질 관리의 부재로 인해, 잘못되거나 오염된 입력 데이터를 기반으로 생성된 출력물에 대해서도 높은 평가 점수가 부여될 수 있는 심각한 오류 가능성이 존재합니다 [5]. +* **운영 오버헤드 증가:** 시스템 내부에서 LLM 호출의 모든 단계를 추적하는 과정에서 약 15%의 성능 오버헤드(Performance overhead)가 발생할 수 있습니다 [2]. 또한, 보안을 위해 자체 호스팅 옵션을 선택할 경우 규모가 작은 팀에게는 추가적인 운영 부담(Operational burden)으로 작용할 수 있습니다 [2]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Langfuse.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Langfuse.md new file mode 100644 index 00000000..380e4fa3 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Langfuse.md @@ -0,0 +1,16 @@ +# [[Langfuse]] + +## 📌 Brief Summary +Langfuse는 월 600만 건 이상의 SDK 설치를 기록하고 있는 선도적인 오픈소스 LLMOps 가시성(Observability) 및 평가 플랫폼이다 [1]. 자체 호스팅(Self-hosted)이 가능하여 데이터 벤더 종속(vendor lock-in) 없이 에이전트의 모든 실행 단계 추적, 프롬프트 관리, 평가 파이프라인 기능을 단일 도구에서 제공한다 [1, 2]. 주로 배포 후 에이전트의 실행 결과를 모니터링하고 모델의 출력과 프롬프트 성능을 평가하는 사후(post-hoc) 도구로 활용된다 [3, 4]. + +## 📖 Core Content +* **핵심 가시성 및 추적 기능**: Langfuse는 스팬(span) 수준에서 LLM 호출을 추적하여 모델 호출을 프롬프트, 입력 및 출력과 연결한다 [5]. 에이전트가 실행된 이후 무슨 일이 일어났는지 기록하고 분석하며, 데이터 레지던시(data residency)나 비용 통제가 중요한 제약 조건인 환경에서 클라우드 전용 대안보다 선호된다 [2, 4]. +* **프롬프트 및 평가 관리**: 내장된 프롬프트 관리 기능을 통해 버전을 추적하고, 평가 점수를 특정 프롬프트 버전과 직접 연결할 수 있다 [5]. 또한, 평가 파이프라인을 통해 사전에 정의된 기준에 따라 모델의 출력물을 채점한다 [5]. +* **팀 협업 및 배포 환경**: 자체 호스팅을 지원하여 조직의 고유한 보안 경계(security perimeter) 내에 모든 가시성 데이터를 안전하게 보관할 수 있으며, 팀원 간의 협업 기능을 제공하여 공유된 LLMOps 워크플로우를 지원한다 [5]. MIT 라이선스로 제공되며 클라우드 플랜도 이용 가능해, 초기 단계 팀(1~50명)부터 광범위한 프레임워크 커버리지를 필요로 하는 LLMOps 팀에게 널리 권장된다 [3, 5, 6]. + +## ⚖️ Trade-offs & Caveats +* **성능 오버헤드 및 운영 부담**: Langfuse를 에이전트 파이프라인에 통합하여 사용할 경우 약 15%의 성능 오버헤드가 발생할 수 있다 [1, 5]. 또한 자체 호스팅 옵션을 제공하지만, 이를 직접 구축하고 유지하는 것은 소규모 팀에게 추가적인 운영 부담(operational burden)으로 작용할 수 있다 [5]. +* **사후 모니터링의 근본적 한계 (입력 데이터 품질 검증 불가)**: Langfuse는 모델의 출력과 프롬프트 성능을 평가하지만, 에이전트가 읽어 들인 입력 데이터(컨텍스트) 자체의 품질을 검증하지는 못하는 사후 관찰 도구이다 [3, 4]. 즉, 사용된 데이터가 오래되었거나, 인증되지 않았거나, 스키마 변형이 일어났는지 알 수 없기 때문에, 나쁜 입력 데이터를 기반으로 도출된 출력에 대해서도 높은 평가 점수를 부여하는 등 결과가 오도될 위험이 존재한다 [3]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Mcp-Session-Id.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Mcp-Session-Id.md new file mode 100644 index 00000000..89b38158 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Mcp-Session-Id.md @@ -0,0 +1,17 @@ +# [[Mcp-Session-Id]] + +## 📌 Brief Summary +Mcp-Session-Id는 Model Context Protocol(MCP)의 Streamable HTTP Transport 통신에서 클라이언트와 원격 서버 간의 세션을 식별하고 관리하기 위해 사용되는 상태 저장(Stateful) HTTP 헤더이다 [1]. 이 헤더는 MCP 서버가 로컬 프로세스를 넘어 원격 서비스로 구동될 수 있도록 돕지만, 동시에 로드 밸런서 등 인프라의 수평적 확장과 충돌하는 복잡성을 유발한다 [1]. 2026년 로드맵에서는 이러한 한계를 극복하기 위해 세션을 전송 계층에서 분리하는 구조가 논의되고 있다 [1]. + +## 📖 Core Content +* **Streamable HTTP 전송 체계와 원격 서비스 지원:** 2025년 11월 25일 사양에서 기존의 HTTP+SSE 방식을 대체하는 Streamable HTTP 전송 체계가 도입되었다 [1]. 이를 통해 MCP 서버는 단일 기기의 로컬 프로세스로만 동작하는 것이 아니라, 원격 서비스로서 작동할 수 있게 되었다 [1]. +* **통신 메커니즘 및 다중 클라이언트 처리:** 원격으로 배포된 MCP 서버는 클라이언트에서 서버로 향하는 메시지에는 HTTP POST를, 서버에서 클라이언트로 향하는 SSE 스트림에는 선택적으로 GET을 사용하여 다수의 클라이언트 연결(Multiple client connections)을 처리한다 [1]. +* **세션 관리의 핵심, Mcp-Session-Id:** 위와 같은 원격 구조에서 여러 클라이언트 연결을 추적하고 상태를 유지하기 위해 도입된 것이 `Mcp-Session-Id` 헤더이다 [1]. 에이전트 하네스 아키텍처 관점에서, Streamable HTTP는 원격 MCP 배포를 가능하게 했으나 이 헤더를 통한 상태 저장 세션 관리를 요구한다 [1]. + +## ⚖️ Trade-offs & Caveats +* **수평적 확장성(Horizontal Scaling) 및 로드 밸런싱 충돌:** Streamable HTTP 전송 방식은 원격 배포라는 큰 장점을 제공하지만, 세션 관리에 있어 상당한 복잡성을 초래한다는 명확한 반대 급부(Trade-off)를 가진다 [1]. 상태가 저장되는 `Mcp-Session-Id` 헤더는 트래픽을 분산시키는 로드 밸런서(Load balancers)나 서버를 수평적으로 확장하려는 인프라 환경과 기능적으로 충돌(fight)하게 된다 [1]. +* **전송 계층과의 결합으로 인한 제약 및 향후 개선 방향:** 현재의 구조는 세션 관리가 전송 계층에 강하게 결합되어 있어 대규모 확장이 까다롭다 [1]. 이러한 근본적인 제약 사항을 해결하기 위해 2026년 MCP 로드맵에서는 세션을 전송 계층(Transport layer)에서 분리(Decoupling)하여, 상태 저장 세션의 제약 없이 수평적 확장이 가능한 방향으로 사양을 개선하는 것을 목표로 하고 있다 [1]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness (메타 하네스).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness (메타 하네스).md new file mode 100644 index 00000000..e555bc1b --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness (메타 하네스).md @@ -0,0 +1,17 @@ +# [[Meta-Harness (메타 하네스)]] + +## 📌 Brief Summary +메타 하네스(Meta-Harness)는 개별 에이전트 하네스를 수동으로 조정하는 대신, 에이전트가 스스로 하네스 구성(프롬프트, 도구 정의, 컨텍스트 관리 등)을 진화시키고 최적화하도록 지원하는 상위 계층의 프레임워크이자 자동화 패러다임이다 [1]. 이는 다른 하네스들을 자동 생성하는 '메타 팩토리(Meta-Factory)'의 역할을 수행하거나, 외부 최적화 루프를 통해 실패를 진단하고 하네스를 재작성하는 자가 개선(Self-improving) 시스템으로 구현된다 [1, 2]. + +## 📖 Core Content +* **엔드투엔드 최적화 표적 (End-to-End Optimization):** 메타 하네스는 시스템 프롬프트, 도구 정의, 맥락 관리, 완료 로직 등을 개별적으로 튜닝하지 않고 하네스 전체를 공동 최적화(Joint optimization)의 대상으로 삼는다 [1]. 제안자 에이전트(Proposer agent)에게 이전 하네스 후보, 점수, 실행 추적(Execution traces)에 대한 파일 시스템 접근 권한을 부여하여 실패 원인을 특정 하네스 결정의 결과로 역추적하게 한다 [1]. +* **하네스 메타 팩토리 (L3 Meta-Factory):** 메타 하네스는 '다른 하네스들을 생성하는 계층'으로도 기능한다 [2]. 예를 들어, `revfactory/harness` 프레임워크는 사용자의 도메인 설명만으로 사전 정의된 6가지 패턴 중 하나를 선택해 에이전트 팀과 스킬을 자동 생성하는 '팀 아키텍처 팩토리(Team-Architecture Factory)' 역할을 하며, `Archon`은 결정적이고 반복 가능한 런타임 설정을 생성하는 역할을 분담하여 이웃 서브 층으로 공존한다 [2, 3]. +* **자율적 하네스 진화 (Autonomous Harness Evolution):** 에이전트가 자신의 실행 기록을 기반으로 프롬프트, 도구, 전략 등 스캐폴딩(Scaffolding) 자체를 수정하도록 설계된 궁극적인 형태의 메타 하네스가 존재한다 [1]. 대표적으로 `harness-evolver`나 `stanford-iris-lab/meta-harness` 같은 구현체들은 파일 시스템 기반의 검색 루프를 통해 코딩 에이전트가 하네스 아티팩트를 자율적으로 제안, 평가, 정제하는 과정을 거치며 성능을 향상시킨다 [1, 4]. +* **역할 분리 패턴 (Program.md 패턴):** 인간은 `PROGRAM.md`와 같은 파일에 최적화 지시(Directive)를 작성하고, 에이전트는 하네스 엔지니어링 루프를 직접 실행하는 패턴이 가장 실용적인 메타 하네스 접근법으로 꼽힌다 [1]. 이를 통해 단순히 정적인 설정을 넘어서 `AGENTS.md`, 설정 스크립트, 테스트 흐름 등을 최적화 가능한 학습 매개변수로 취급하여 레이블링된 훈련 데이터 없이도 신뢰성을 크게 끌어올린다 [4]. + +## ⚖️ Trade-offs & Caveats +* **막대한 컨텍스트 및 토큰 비용:** 메타 하네스 접근법은 제안자 에이전트가 하네스 결정의 실패 원인을 추적하기 위해 이전 하네스 후보와 수많은 실행 추적(Traces) 데이터에 모두 접근해야 한다. 이로 인해 기존 연구(약 26,000 토큰)에 비해 엄청난 규모인 1,000만(10M) 토큰 수준의 진단 컨텍스트를 요구하므로, 막대한 리소스 오버헤드가 발생한다는 제약이 있다 [1]. +* **메타 평가(Meta-Evaluation) 인프라 구축의 난해함:** 한 에이전트가 다른 에이전트의 하네스를 반복적으로 최적화하는 과정(Agent-on-agent optimization)에서는, 최적화가 실제로 타겟 에이전트를 개선하고 있는지 체계적으로 측정하기 어렵다는 '메타 평가의 공백(Meta-evaluation gap)' 문제가 발생한다 [5]. 이를 해결하기 위해서는 버전화된 에이전트 스냅샷, 예산이 통제된 평가(Budget-controlled evaluation), 그리고 구조화된 실행 추적을 캡처하는 복잡한 전용 평가 프레임워크(예: VeRO)가 필수적으로 수반되어야 한다 [5]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness.md new file mode 100644 index 00000000..35482489 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Meta-Harness.md @@ -0,0 +1,20 @@ +# [[Meta-Harness]] + +## 📌 Brief Summary +메타-하네스(Meta-Harness)는 에이전트 하네스(시스템 프롬프트, 도구 정의, 컨텍스트 관리 등) 전체를 수동으로 조정하는 대신 하나의 공동 최적화 대상으로 취급하는 아우터 루프(outer-loop) 최적화 패러다임입니다 [1, 2]. 이 시스템에서는 에이전트가 과거의 실행 트레이스와 실패 로그를 스스로 분석하여 하네스의 구성 요소를 반복적으로 수정하고 재평가합니다 [1, 3]. 궁극적으로 이는 에이전트가 작업 수행뿐만 아니라 자신의 비계(scaffolding)와 인프라 자체를 스스로 진화시키고 성능을 향상시키는 자율 진화(Self-Improving) 시스템을 구현하는 것을 목표로 합니다 [1]. + +## 📖 Core Content +* **하네스의 아티팩트화 및 학습 가능성**: 메타-하네스는 `AGENTS.md`, 설정 스크립트, 검증 로직, 테스트 흐름과 같은 하네스의 요소들을 정적인 설정(static configs)이 아니라, 언제든 최적화할 수 있는 아티팩트이자 학습 가능한 매개변수(learnable parameters)로 취급합니다 [2]. 단순히 프롬프트를 넘어서 라우팅, 검색, 오케스트레이션 코드까지 모두 최적화의 대상이 됩니다 [1]. +* **파일 시스템 기반의 최적화 루프**: 제안자(proposer) 역할을 하는 에이전트는 파일 시스템에 접근하여 이전의 모든 하네스 후보군, 평가 점수, 실행 트레이스에 대한 방대한 진단 컨텍스트를 읽습니다 [1]. 이를 통해 에이전트는 실패의 원인을 특정 하네스 설계의 결정으로 추적하고 지속적인 편집-실행-평가(edit-execute-evaluate) 루프를 구동합니다 [1, 2]. +* **프로그램 기반 역할 분리 (PROGRAM.md 패턴)**: 메타-하네스의 가장 실용적인 패턴 중 하나는 역할의 분리입니다 [1]. 인간은 `PROGRAM.md`와 같은 파일을 통해 최적화 지침(directive)만을 작성하고, 실제 하네스 엔지니어링 루프(프롬프트, 도구 설정, 에이전트 라우팅 최적화 등)는 에이전트가 자율적으로 실행하도록 하는 방식이 활용됩니다 [1]. +* **재귀적 개선과 자율 진화 메커니즘**: 메타-하네스는 작업 해결과 메타 수준의 개선을 하나의 수정 가능한 프로그램으로 통합하여 인지적 자기 수정(metacognitive self-modification)을 가능하게 합니다 [1]. 이는 향후 자율형 인공지능이 자신의 실패 로그를 분석해 하네스 가이드라인을 스스로 수정하며 성능을 높이는 '재귀적 개선(recursive improvement)' 메커니즘으로 발전하는 핵심 토대가 됩니다 [3]. + +## ⚖️ Trade-offs & Caveats +메타-하네스 최적화 패러다임과 관련하여 소스에서 확인되는 기술적 제약 사항과 과제는 다음과 같습니다. + +* **막대한 컨텍스트 처리 요구량**: 에이전트가 하네스의 실패 원인을 정확히 추적하기 위해서는 이전 하네스의 후보군, 점수, 그리고 매우 방대한 실행 트레이스를 모두 읽어야 합니다. 기존 작업이 2만 6천 토큰 수준이었다면, 메타-하네스 최적화를 위해서는 최대 천만(10M) 토큰 규모의 방대한 진단 컨텍스트(diagnostic context)를 에이전트에 제공해야 하므로 막대한 연산 비용과 컨텍스트 처리 역량이 요구됩니다 [1]. +* **회귀(Regression) 위험과 검증 인프라 필수**: 에이전트가 스스로 하네스 코드를 변경하므로, 잘못된 수정으로 인해 오히려 기존 성능이 저하되는 회귀 현상이 발생할 위험이 큽니다 [1]. 따라서 독립된 작업 공간(isolated git worktrees)이나 샌드박스(Harbor, Docker 등)에서 철저한 검증이 이루어져야 하며, 평가 벤치마크 백엔드가 연동된 강력한 회귀 방지 가드(regression guards)가 필수적으로 수반되어야만 안전한 최적화가 가능합니다 [1]. +* 그 외 메타-하네스 체계가 가지는 구체적인 기술적 부작용이나 한계에 대해서는 소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Multi-Agent Orchestration.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Multi-Agent Orchestration.md new file mode 100644 index 00000000..768173e5 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Multi-Agent Orchestration.md @@ -0,0 +1,22 @@ +# [[Multi-Agent Orchestration]] + +## 📌 Brief 시 Summary +Multi-Agent Orchestration(멀티 에이전트 오케스트레이션)은 복잡하고 모호한 작업을 해결하기 위해 특화된 역할을 가진 여러 AI 에이전트를 조율하고 협력하게 만드는 프레임워크 및 관리 기법이다 [1, 2]. 이 시스템에서 에이전트 하네스(Harness)는 단일 모델이 모든 것을 처리하는 대신, 중앙 관리자나 라우터 역할을 수행하여 작업을 분해하고 하위 에이전트(Sub-agent)들에게 위임한다 [3, 4]. 에이전트 간의 통신, 컨텍스트 격리, 상태 공유 및 핸드오프를 구조적으로 관리함으로써 단일 에이전트 접근법보다 높은 정확성과 확장성을 제공한다 [2, 5]. + +## 📖 Core Content +* **오케스트레이션의 필요성:** 대규모 프로젝트를 하나의 에이전트가 처리할 경우 컨텍스트 윈도우의 한계에 부딪히기 쉽다. 하네스 내의 오케스트레이터(Orchestrator)는 메인 작업을 여러 개의 작은 작업으로 쪼개고 관련 시점에만 하위 에이전트를 생성(Spawn)하여 컨텍스트 윈도우를 좁게 유지한다 [6, 7]. 이를 통해 이전 단계의 관련 컨텍스트만 다음 에이전트에 전달하고 무관한 과거 기록은 제외하여 효율성을 극대화한다 [2]. +* **주요 아키텍처 패턴:** + * **역할 기반 협업 (Role-based Collaboration):** CrewAI와 같이 에이전트마다 특정 페르소나(예: 연구원, 작성자, CEO)를 부여하고, 각자의 목표와 도구를 설정한 뒤 A2A(Agent-to-Agent) 메시징을 통해 협업하게 한다 [4, 8]. + * **대화형 다중 에이전트 (Conversational Multi-agent):** AutoGen처럼 여러 에이전트가 번갈아 가며 결과를 제안하고, 비판하고, 수정하는 다중 턴(Multi-turn) 토론을 진행하여 신뢰성 높은 결과물을 생성한다 [9]. + * **사전 정의된 팀 아키텍처:** revfactory/harness는 파이프라인(순차 의존 작업), 팬아웃/팬인(병렬 독립 작업), 전문가 풀, 생성-검증, 감독자(Supervisor), 계층적 위임 등 6가지 조직 패턴을 적용하여 에이전트 팀을 구성하고 조율한다 [10, 11]. + * **상태 머신 및 그래프 기반 제어:** LangGraph는 조건부 에지(Conditional edges)와 체크포인트 기능을 통해 에이전트 간의 흐름과 명시적 상태를 그래프 기반으로 제어한다 [12, 13]. +* **동적 토폴로지 적용:** 고도화된 오케스트레이션 프레임워크는 고정된 파이프라인 대신 작업의 의존성 그래프에 따라 병렬, 순차, 계층적 토폴로지 중 가장 적합한 구조를 동적으로 선택하여 성능을 향상시킨다 [14]. +* **상용 모델 적용 사례:** Kimi K2.5는 최대 100개의 하위 에이전트를 동시에 조율하는 에이전트 스웜(Agent Swarm) 기능을 제공하며 [15], Grok 4.20은 4개의 전문 에이전트로 구성된 위원회가 병렬로 숙고한 후 응답을 도출하는 시스템을 사용한다 [16]. + +## ⚖️ Trade-offs & Caveats +* **분산 시스템 수준의 복잡성:** 멀티 에이전트 워크플로우는 본질적으로 분산 시스템과 유사하게 동작한다. 따라서 에이전트 간 작업을 넘겨주는 핸드오프(Handoff) 시, 타입이 지정된 스키마(Typed schemas)와 제약된 행동 스키마, 명시적인 경계 검증이 누락될 경우 시스템 전체의 연쇄적 실패를 초래할 수 있다 [17]. +* **디버깅 및 로깅의 난해함:** 여러 에이전트가 동시에 실행될 경우 동시 실행 로그가 얽혀버리므로, 실패 원인을 추적하고 디버깅하기가 매우 어렵다. CrewAI 등에서도 동시 에이전트 로깅은 널리 알려진 페인 포인트(Pain point)로 지적된다 [18]. 이를 보완하기 위해 AgentOps나 Langfuse처럼 다중 에이전트의 상호작용과 세션을 추적하는 전문적인 관측성(Observability) 인프라가 강제된다 [19, 20]. +* **무한 루프 및 수동 개입의 위험:** 대화형 토론이나 자율적인 위임 패턴을 사용할 때, 두 에이전트가 결론을 내지 못하고 서로 무한 루프에 빠지는 현상이 발생할 수 있다 [9]. 이러한 패턴에서는 대화가 길어질수록 컨텍스트 창이 가득 차게 되므로, 하네스나 개발자가 수동으로 컨텍스트를 가지치기(Pruning)하거나 강제로 개입하여 루프를 끊어야 하는 한계가 존재한다 [9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Agent Passport (OAP).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Agent Passport (OAP).md new file mode 100644 index 00000000..1475e3ba --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Agent Passport (OAP).md @@ -0,0 +1,16 @@ +# [[Open Agent Passport (OAP)]] + +## 📌 Brief Summary +Open Agent Passport (OAP)는 자율형 AI 에이전트를 위한 결정론적 사전 조치 권한 부여(Pre-Action Authorization)를 제공하는 2026년 3월의 오픈 사양 및 참조 구현체입니다 [1]. 이 시스템은 에이전트가 도구를 실행하기 전에 동기적으로 호출을 가로채어 선언적 정책에 따라 평가하고, 암호화 기법으로 서명된 감사 기록을 생성합니다 [1]. 이를 통해 샌드박스 실행이나 모델 기반 스크리닝과는 상호 보완적이면서도 명확히 구별되는 독립적인 하네스 보안 계층을 형성합니다 [1]. + +## 📖 Core Content +* **동기적 호출 차단 및 평가**: OAP는 에이전트의 도구 호출이 실제 실행되기 전에 이를 동기적으로 가로채어(intercepts tool calls synchronously before execution) 사전에 정의된 선언적 정책(declarative policy)을 기준으로 유효성을 평가합니다 [1]. +* **암호화된 감사 기록 생성**: 도구 실행에 대한 권한 평가 시 암호화 방식으로 서명된 감사 기록(cryptographically signed audit record)을 생성하여, 에이전트 작업에 대한 투명성과 추적 가능성을 보장합니다 [1]. +* **뛰어난 보안 성능과 처리 속도**: 권한 부여 처리에 소요되는 시간은 중간값 기준 53ms로 신속하게 이루어집니다 [1]. 또한 5,000달러의 포상금이 걸린 실시간 적대적 테스트베드에서 엄격한 OAP 정책을 적용했을 때 공격 성공률 0%를 기록하며 높은 방어력을 입증했습니다 [1]. +* **독립적인 하네스 보안 계층 인식**: OAP는 사전 조치 권한 부여 과정을 샌드박스 내부에서의 실행이나 모델 자체의 판단에 의존하는 스크리닝 방식과 분리하여, 서로 보완적이지만 뚜렷하게 구별되는 하네스 계층으로 다룹니다 [1]. + +## ⚖️ Trade-offs & Caveats +OAP를 적용할 경우 권한 부여를 강제하는 과정에서 중간값 53ms 수준의 지연(latency)이 발생하게 됩니다 [1]. 또한, 엄격한(restrictive) 정책을 적용했을 때는 적대적 공격 성공률이 0%로 완벽한 방어가 가능했으나, 허용적인(permissive) 정책 환경에서는 공격 성공률이 74.6%까지 치솟았다는 점을 고려할 때, 보안 효과가 관리자가 설정한 선언적 정책의 엄격성에 크게 의존한다는 한계가 있습니다 [1]. 그 외의 심층적인 부작용이나 구조적 제약 사항에 대해서는 소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Harness.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Harness.md new file mode 100644 index 00000000..007157aa --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Harness.md @@ -0,0 +1,24 @@ +# [[Open Harness]] + +## 📌 Brief Summary +'Open Harness'는 AI 에이전트를 구동하고 관리하기 위해 개발된 오픈소스 기반의 하네스 및 런타임 프로젝트들을 의미한다 [1-3]. 제공된 소스에 따르면 명칭은 같지만 목적과 아키텍처가 완전히 다른 세 가지 주요 프로젝트(HKUDS의 런타임, MaxGfeller의 상호운용성 SDK, ryaneggz의 샌드박스)가 존재한다 [1, 3]. 이 도구들은 각각 생산 환경 하네스의 내부 작동 방식 검사, 프레임워크 종속성 탈피, 그리고 독립된 단일 프로젝트 실행 환경 제공이라는 고유한 인프라 역할을 수행한다 [2-4]. + +## 📖 Core Content +* **OpenHarness (HKUDS):** 홍콩대학교 데이터 시스템 그룹(HKUDS)에서 개발한 CLI 중심의 오픈소스 에이전트 런타임이다 [2, 5]. 생산 환경의 에이전트 하네스 내부 작동 방식을 검사하고자 하는 연구자와 개발자를 위해 설계되었다 [2]. + * 파일, 셸, 웹 검색, MCP 등 43개 이상의 내장 도구를 갖추고 있으며, 스트리밍 도구 호출 주기, 다단계 권한 모드, `MEMORY.md`를 통한 상태 보존 및 백그라운드 작업 관리 기능을 지원한다 [2, 5, 6]. + * 이 프로젝트는 'ohmo'라는 내장 개인용 AI 에이전트 앱을 포함하고 있으며, 모델 추론과 도구 실행의 투명한 가시성을 제공한다 [2, 7, 8]. +* **OpenHarness.ai (MaxGfeller):** 하네스 프레임워크 간의 종속성(Lock-in)을 피하기 위해 개발된 상호운용성 SDK 계층이다 [4]. + * 에이전트 코드를 한 번 작성하면 수정 없이 Anthropic SDK, Goose, LangChain, Letta, Claude Code 등 여러 런타임 환경에 배포할 수 있는 유니버설 API를 제공한다 [4, 9]. + * 에이전트 내부에서 실행되는 런타임이라기보다는 코드를 다양한 런타임 간에 이식 가능하게 만드는 추상화 계층이다 [4]. +* **Open Harness (ryaneggz):** 단일 프로젝트(리포지토리)를 위해 설계된 Docker 기반의 에이전트 하네스 및 다중 계층 격리 샌드박스이다 [3]. + * "우리가 샌드박스를 제공할 테니, 당신은 하네스를 선택하라(BYOH)"는 철학을 가진다 [3]. + * 호스트의 종속성을 Docker 하나로 제한하며, 마크다운(`crons/*.md`)으로 정의된 일정에 따라 백그라운드에서 에이전트를 구동시키는 'croner' 런타임을 특징으로 한다 [3, 10]. + +## ⚖️ Trade-offs & Caveats +* **데이터 품질 및 거버넌스 제어 부재:** HKUDS의 런타임과 MaxGfeller의 SDK 모두 에이전트가 처리하는 데이터 자체를 검증, 인증하거나 데이터 계보를 추적하는 데이터 품질 거버넌스 기능이 근본적으로 결여되어 있다 [4, 11]. +* **HKUDS OpenHarness의 제약:** 연구 중심의 초기 릴리스이므로, 상용 프레임워크 대안들에 비해 엔터프라이즈용 관리 도구가 부족하다 [12]. 또한 CLI 우선 설계 방식이므로 종합적인 시각적 인터페이스 환경을 기대하기 어렵다 [12]. +* **MaxGfeller OpenHarness.ai의 제약:** 이 프로젝트는 오직 '이식성(Portability)' 문제만 해결하므로, 오케스트레이션이나 메모리, 관찰 가능성(Observability) 기능은 제공하지 않는다 [9]. 또한 지원되는 어댑터 목록에 전적으로 의존해야 하며, 커뮤니티 규모가 작아 엔터프라이즈 규모에서의 상용 검증이 부족하다 [9]. +* **ryaneggz Open Harness의 제약:** 구조적으로 다중 테넌트(Multi-tenant) 비교 환경이 아닌, 단일 리포지토리 및 단일 샌드박스 전용으로 엄격하게 제한되어 있다 [3]. 사용을 위해서는 Docker 호스트 종속성이 필수적으로 요구된다 [3]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Policy Agent (OPA).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Policy Agent (OPA).md new file mode 100644 index 00000000..a61db302 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Open Policy Agent (OPA).md @@ -0,0 +1,15 @@ +# [[Open Policy Agent (OPA)]] + +## 📌 Brief Summary +Open Policy Agent(OPA)는 에이전트 하네스 및 자율형 AI 인프라 내에서 보안 및 거버넌스 정책을 집행하는 데 사용되는 메커니즘입니다 [1, 2]. 에이전트가 시스템에 실질적인 영향을 미치는 행동을 실행하기 전에 선언적 규칙을 기반으로 이를 평가하여 차단, 경고 또는 승인 요구를 결정합니다 [3]. 이를 통해 최소 권한 원칙을 기본으로 적용하고 에이전트의 안전한 운영을 보장합니다 [2, 3]. + +## 📖 Core Content +* **OPA 정책 게이트(OPA Policy Gates)**: 에이전트 하네스(예: Harness Agents)에서 에이전트가 영향을 미치는 작업(effectful action)을 수행하기 전, 모든 작업은 OPA 정책에 따라 사전에 평가됩니다 [3]. 시스템은 선언적 규칙(declarative rules)에 기반하여 해당 작업을 즉각적으로 차단(Block)하거나, 경고(Warn)를 발생시키며, 필요한 경우 추가적인 승인을 요구하도록 제어합니다 [3]. +* **거버넌스 및 최소 권한(Least-privilege) 적용**: 보안을 최우선(Security First)으로 하는 하네스 아키텍처에서 OPA가 통제하는 작업은 권한 범위가 지정된 도구(Scoped tools) 및 인간 개입(Human-in-the-loop) 체계와 결합됩니다 [2]. 이를 통해 에이전트가 과도한 권한을 행사하지 못하도록 최소 권한 원칙이 기본적으로 작동하게 합니다 [2]. +* **샌드박스 네트워크 보안**: NVIDIA OpenShell과 같은 자율형 AI 에이전트용 정책 기반 샌드박스 런타임에서는 OPA 및 Rego로 평가되는 HTTP CONNECT 프록시를 통해 네트워크 보안 제약을 강제합니다 [1]. 이러한 보안 통제는 실행 환경 자체에 직접 적용되므로, 해킹되거나 침해당한 에이전트조차도 시스템의 보안 제약을 임의로 우회하거나 무효화할 수 없도록 방지합니다 [1]. + +## ⚖️ Trade-offs & Caveats +소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/OpenHarness.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/OpenHarness.md new file mode 100644 index 00000000..cac3b38c --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/OpenHarness.md @@ -0,0 +1,32 @@ +# [[OpenHarness]] + +## 📌 Brief Summary +OpenHarness는 에이전트 하네스 생태계에 존재하는 두 가지 독립적인 오픈소스 프로젝트를 동시에 지칭하는 용어이다 [1, 2]. 하나는 홍콩대학교(HKUDS)에서 개발한 CLI 기반의 에이전트 런타임 환경이며, 다른 하나는 MaxGfeller가 개발한 다양한 런타임 간 에이전트 코드 이식을 돕는 상호 운용성(Interoperability) SDK이다 [2-4]. 두 프로젝트 모두 상용 하네스 시스템의 제약에서 벗어나, 실행 주기의 내부 동작을 투명하게 검사하거나 벤더 종속성을 피하고자 하는 개발자와 연구자를 위해 설계되었다 [3, 5]. + +## 📖 Core Content + +소스 자료에 따르면 OpenHarness라는 이름을 공유하지만 구조와 목적이 완전히 다른 두 개의 프로젝트가 존재한다 [1]. + +* **OpenHarness (HKUDS)** + * **목적 및 특징:** 상용 에이전트 하네스의 내부 동작을 내부에서부터 투명하게 검사할 수 있도록 개발된 연구 및 개발자용 오픈소스 런타임이다 [3, 6]. CLI(Command Line Interface) 기반의 실행 주기를 투명하게 노출하며, 파일 시스템, 셸, 검색, 웹, MCP(Model Context Protocol) 등을 다루는 43개 이상의 내장 도구를 기본으로 제공한다 [7, 8]. + * **아키텍처 및 구성 요소:** 모델의 추론을 실제 작업과 연결하기 위해 스트리밍 도구 호출 주기, 지수 백오프 기반 재시도, 병렬 도구 실행 기능을 갖추고 있다 [9]. 컨텍스트 제어를 위해 CLAUDE.md 주입, 상태를 잃지 않는 자동 압축(Auto-Compaction), 경량 상태 관리를 위한 MEMORY.md 파일 기반 지속성 관리 기능을 지원한다 [10-12]. + * **에이전트 생태계 확장:** 이 프레임워크 위에서 'ohmo'라는 개인용 AI 에이전트를 내장 앱으로 제공하여 Slack, Discord, Telegram, Feishu 등의 메신저 채널과 연동할 수 있도록 지원한다 [13, 14]. 또한 claude-code 플러그인 생태계와 호환된다 [15]. + * **안전성 (Governance):** 작업 환경의 보안을 위해 다중 레벨 권한 모드(Default, Auto, Plan Mode)를 두어 실행을 제어하며, 실제 모델 호출이나 하위 에이전트 실행 없이 런타임 설정, 권한 상태 및 MCP 설정 문제 등을 사전에 안전하게 점검할 수 있는 '드라이 런(Dry-run)' 프리뷰 모드를 지원한다 [11, 16, 17]. + +* **OpenHarness.ai (MaxGfeller)** + * **목적 및 특징:** 특정 프레임워크에 종속되는 것을 방지하기 위해 구축된 하네스 상호 운용성 SDK이다 [4]. 에이전트를 실행하는 런타임이 아니라, 한 번 작성한 에이전트 코드를 Anthropic SDK, Goose, LangChain, Letta, Claude Code 등 여러 실행 환경에 수정 없이 배포할 수 있게 해주는 추상화 계층이다 [4]. + * **아키텍처:** 도구(Tools), 메모리, 실행 컨텍스트에 관한 표준화된 범용 API를 정의하고 여러 런타임용 어댑터를 제공함으로써 에이전트 코드의 이식성을 보장한다 [5]. + +## ⚖️ Trade-offs & Caveats + +* **OpenHarness (HKUDS)의 제약 사항:** + * 엔터프라이즈 환경에서의 한계: 초기 릴리스(v0.1.x) 단계로, 상용 대안들에 비해 엔터프라이즈용 관리 도구가 부족하며 본질적으로 연구 지향적인 특성을 띤다 [10]. + * 데이터 품질 관리의 부재: 하네스 내부로 유입되는 컨텍스트와 데이터 입력의 품질을 검증하거나 계보(Lineage)를 추적하는 등의 데이터 거버넌스 메커니즘이 전혀 없다 [4]. + * 인터페이스의 한계: React TUI(Terminal UI)를 부분적으로 지원하기는 하나, 기본적으로 CLI 우선 설계이므로 웹이나 시각적인 관리 인터페이스를 기대하는 환경에는 부적합하다 [10]. + +* **OpenHarness.ai (MaxGfeller)의 제약 사항:** + * 단일 목적성의 한계: 오직 이식성(Portability) 해결에만 초점을 맞춘 도구이므로, 오케스트레이션, 메모리 관리, 옵저버빌리티(Observability) 등 하네스의 핵심 제어 기능은 전혀 제공하지 않는다 [5]. + * 생태계 및 품질의 제약: 커뮤니티 규모가 작아 엔터프라이즈 규모에서의 생산성 검증이 부족하며, SDK가 지원하는 어댑터 목록에 강하게 의존할 수밖에 없다 [5]. HKUDS 버전과 마찬가지로 모든 계층에서 데이터 품질 제어 장치가 전무하다 [18]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Permissions and Safety.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Permissions and Safety.md new file mode 100644 index 00000000..7b1b1a9d --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Permissions and Safety.md @@ -0,0 +1,19 @@ +# [[Permissions and Safety]] + +## 📌 Brief Summary +에이전트 하네스에서 'Permissions and Safety(권한 및 안전)'는 도구가 실행되기 전에 에이전트가 수행할 수 있는 작업을 강제하고 제약하는 핵심 보안 인프라 계층을 의미한다 [1, 2]. 이는 단순한 자연어 프롬프트에 의존하는 대신, 다중 계층 권한 모드, 역할 기반 접근 제어(RBAC), 사전 행동 검증(Pre-action Verification), 인간 개입(Human-in-the-Loop) 등의 구조적 인가 패턴을 통해 에이전트를 제어한다 [3-6]. 궁극적으로 이 시스템은 에이전트의 '과도한 자율성(Excessive Agency)'을 방지하고, 최소 권한 원칙에 따라 신뢰할 수 있고 안전한 인공지능 운영 환경을 보장한다 [4, 7, 8]. + +## 📖 Core Content + +* **구조적 인가 및 다중 계층 권한 제어 (Structured Authorization & Multi-Level Permission):** 현대적인 하네스는 프롬프트 수준의 신뢰에 의존하는 대신 구조적인 인가 패턴을 사용하여 에이전트의 권한을 제어한다 [4]. 예를 들어 OpenHarness 프레임워크는 일상적인 개발을 위한 'Default(작성/실행 전 묻기)', 샌드박스 환경을 위한 'Auto(모두 허용)', 대규모 리팩토링 및 리뷰를 위한 'Plan Mode(모든 쓰기 차단)'와 같은 다중 수준의 권한 모드와 경로 기반(Path-level) 규칙을 제공한다 [3, 9]. +* **사전 행동 검증 및 정책 게이트 (Pre-action Verification & Policy Gates):** 에이전트의 모든 효과적인 조치(Effectful action)는 실행되기 전에 거버넌스 정책에 의해 평가된다 [5]. Harness.io와 같은 플랫폼에서는 Open Policy Agent(OPA) 정책 게이트를 통해 규칙을 선언하고, 승인된 도구(Allow-Listed Tools)만 호출할 수 있도록 환경을 제한한다 [5, 10]. 또한, Microsoft의 인가 패브릭(Authorization Fabric)이나 Open Agent Passport (OAP) 모델은 도구 호출을 동기적으로 가로채어 실행 전에 '허용(ALLOW), 거부(DENY), 승인 필요(REQUIRE_APPROVAL), 마스킹(MASK)'과 같은 결정론적인 정책 평가를 수행한다 [4, 11]. +* **인간 개입 제어 (Human-in-the-Loop, HITL):** 프로덕션 데이터베이스에 기록하거나 외부로 이메일을 전송하는 등의 매우 민감한 작업은 AI가 전적으로 자율적으로 수행하기에 위험하므로, 하네스는 인간 개입(HITL) 워크플로우를 구현한다 [6, 8]. 하네스는 고위험 행동을 식별할 때 에이전트의 실행을 일시 중지(Interrupt)하고 인간의 승인이나 검토를 기다리도록 설계되어, 디지털 노동은 AI가 수행하되 최종 책임과 감독은 인간이 유지하도록 보장한다 [6, 8, 12]. +* **최소 권한 및 격리 환경 (Least-Privilege & Isolation):** 에이전트는 독립적인 외부 스크립트가 아니라 정의된 파이프라인 실행 컨텍스트 내에서 동작하며, 해당 파이프라인이 허용하는 리소스, 커넥터, 시크릿(비밀 데이터), RBAC 범위만을 상속받는다 [5, 7, 13]. 또한 로컬 쉘 실행과 같은 논리는 격리된 환경(샌드박스)에서 실행되며, 명령어 실행 전 명시적인 승인 체크포인트를 유지하여 시스템을 보호한다 [14-16]. + +## ⚖️ Trade-offs & Caveats + +* **승인 피로 (Approval Fatigue)와 자율성의 딜레마:** 에이전트의 안전을 위해 매 작업마다 사용자에게 명시적인 승인을 요구하게 되면, 사용자가 프롬프트의 93% 이상을 무비판적으로 자동 승인해 버리는 '승인 피로' 현상이 발생할 수 있다 [4]. 이를 완화하기 위해 일부 하네스(예: Claude Code의 Auto Mode)는 단일 토큰 게이트와 플래그가 지정된 작업에 대해서만 추론을 요구하는 2단계 분류기를 도입하여 승인을 건너뛰게 하지만, 이는 편의성과 속도를 높이는 대신 철저한 인간의 검증 과정을 약화시킬 수 있다는 제약이 따른다 [4]. +* **인가 아키텍처 및 신원 매핑의 복잡성 증가:** 에이전트가 다양한 시스템과 외부 서비스에 접근하기 위해서는 정교한 인증(Authentication) 및 인가(Authorization) 관리가 필요하다 [4]. 최종 사용자의 자격 증명을 사용하는 '대리(On-behalf-of)' 권한 부여 방식은 교차 채널 신원 매핑 및 사용자별 메모리 격리가 필수적이며, 에이전트 자체 계정을 사용하는 '고정 자격 증명(Fixed-credential)' 방식은 고위험 작업에 대해 더욱 엄격한 인간 개입 가드레일이 요구되는 등, 안전한 하네스 인프라를 설계하고 유지보수하는 데 상당한 기술적 복잡성이 수반된다 [4]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Phase 3- Harness Engineering.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Phase 3- Harness Engineering.md new file mode 100644 index 00000000..19f00c26 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Phase 3- Harness Engineering.md @@ -0,0 +1,20 @@ +# [[Phase 3: Harness Engineering]] + +## 📌 Brief Summary +'Phase 3: Harness Engineering'은 AI 에이전트 발전의 세 번째 단계로, 모델의 크기(Phase 1)나 프롬프트 및 컨텍스트(Phase 2)를 개선하는 것을 넘어 모델이 작동하는 '환경'을 설계하는 단계를 의미한다 [1, 2]. 이는 에이전트의 성공 여부를 결정짓는 컨텍스트 전달, 도구 인터페이스, 계획 아티팩트, 검증 루프, 메모리 시스템 및 샌드박스 등 스캐폴딩(Scaffolding)을 설계하는 공학적 규율이다 [3]. 이 단계에서는 "모델에게 무엇을 말할 것인가"가 아니라 "모델을 어떤 환경에서 작동시킬 것인가"에 집중하여 에이전트의 신뢰성과 성능을 극대화한다 [2]. + +## 📖 Core Content +* **에이전트 발전의 3단계 진화:** AI 에이전트 개발은 더 큰 모델과 데이터를 학습시키는 '가중치 단계(Phase 1)', 프롬프트 엔지니어링이나 RAG 등을 통해 모델이 보는 것을 변경하는 '컨텍스트 단계(Phase 2)'를 거쳐, 현재 런타임과 인프라를 최적화하는 '하네스 엔지니어링 단계(Phase 3)'로 진화했다 [1]. +* **환경 및 스캐폴딩 중심 설계:** 모델 자체는 고정된 텍스트 생성기로 유지되지만, 영구적인 메모리, 스킬 파일, 작업 순서를 제어하는 런타임 등의 하네스 환경을 제공함으로써 에이전트의 신뢰성과 작업 해결 능력을 근본적으로 변화시킨다 [2, 4]. +* **제어 루프 (피드포워드와 피드백):** 하네스 엔지니어링은 에이전트가 오류를 범하기 전에 올바른 방향으로 안내하는 '피드포워드 가이드(Feedforward Guides)'와, 행동 완료 후 결과를 관찰하여 스스로 수정할 수 있게 돕는 '피드백 센서(Feedback Sensors)'라는 두 가지 핵심 제어 루프를 통해 에이전트를 조향(Steering)한다 [5-8]. +* **컴퓨테이셔널(Computational) 및 인퍼렌셜(Inferential) 제어:** 하네스의 제어 장치는 린터나 정적 분석, 테스트처럼 빠르고 결정론적인 '컴퓨테이셔널 제어'와, LLM 심사관(LLM-as-judge)처럼 느리고 확률적이지만 의미론적 판단이 가능한 '인퍼렌셜 제어'로 나뉘어 구성된다 [9, 10]. +* **메타 하네스(Meta-Harness) 최적화:** 최근 연구에서는 시스템 프롬프트, 도구 구성, 오케스트레이션 코드 등 하네스 전체를 최적화 대상으로 간주하여, 에이전트가 자체 실행 트레이스와 실패 신호를 바탕으로 스스로 하네스 구조를 반복적으로 진화시키는 메타 하네스 패턴으로 발전하고 있다 [11, 12]. + +## ⚖️ Trade-offs & Caveats +* **데이터 품질 보증의 구조적 공백:** 현존하는 대부분의 하네스 오케스트레이션 프레임워크는 에이전트가 읽는 데이터가 신뢰할 수 있다고 가정할 뿐 이를 자체적으로 인증하거나 검증하지 않는다 [13-15]. 통제되지 않은 환경에서 스키마가 변경되거나 오래된 데이터가 유입되면 하네스의 오케스트레이션이 아무리 정교하더라도 '메모리 오염'이나 '연쇄 실패'와 같은 치명적인 오류가 발생할 수 있다 [16, 17]. +* **특정 하네스 구조에 대한 과적합(Overfitting):** 특정 하네스 환경 내에서 훈련(Post-trained)된 모델은 해당 하네스 설계에 과적합되는 부작용을 겪을 수 있다 [18, 19]. 이로 인해 도구의 논리나 런타임 지속성(Persistence) 모드가 조금만 변경되어도 일반화 능력을 상실하고 심각한 성능 저하나 토큰 낭비가 발생할 수 있다 [19, 20]. +* **인퍼렌셜 센서의 높은 비용과 비결정성:** 의미론적 판단이나 AI 코드 리뷰를 수행하는 인퍼렌셜 센서(Inferential Sensors)는 유용하지만 실행 속도가 느리고 비용이 많이 들며 결과가 비결정론적이다 [9, 10]. 이로 인해 모든 변경 사항에 대해 상시 실행하기 어렵고, 사람의 의도 오해나 과도한 엔지니어링과 같은 고영향 문제를 완벽히 포착하기에는 여전히 한계가 있다 [21]. +* **멀티 에이전트 조율의 복잡도 증가:** 여러 에이전트가 협업하는 하네스 아키텍처는 본질적으로 분산 시스템처럼 동작하게 된다 [22, 23]. 따라서 각 에이전트 간의 핸드오프(Handoff) 과정에서 명시적인 경계 검증과 엄격한 스키마가 강제되지 않으면 조율 실패가 발생하여 막대한 아키텍처 관리 오버헤드를 초래한다 [22, 23]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Post-hoc Observability (사후 관측성).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Post-hoc Observability (사후 관측성).md new file mode 100644 index 00000000..8d97788b --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Post-hoc Observability (사후 관측성).md @@ -0,0 +1,18 @@ +# [[Post-hoc Observability (사후 관측성)]] + +## 📌 Brief Summary +Post-hoc Observability (사후 관측성)은 AI 에이전트가 실행을 마친 이후에 발생하는 행동과 결과를 기록하고 모니터링하는 인프라를 의미한다 [1, 2]. 이 접근법은 세션 리플레이, 토큰 비용, 지연 시간, 모델 출력 평가 등을 추적하여 실패 원인을 사후적으로 분석하는 데 필수적이다 [2, 3]. 하지만 에이전트가 실패한 이후에만 이를 포착하기 때문에, 불량한 입력 데이터 등 근본적인 원인에 의해 발생하는 에이전트의 실패를 사전에 방지할 수 없다는 구조적 한계를 지닌다 [1, 2]. + +## 📖 Core Content +* **사후 관측성의 주요 역할**: 사후 관측성 도구는 에이전트 오케스트레이션 프레임워크와 나란히 작동하며 **에이전트가 실행된 이후의 상황을 기록**하는 역할을 수행한다 [1]. 대표적으로 AgentOps와 Langfuse 같은 도구들이 있으며, 이들은 에이전트의 행동을 사후적으로(post-hoc) 모니터링하여 프롬프트의 성능 및 모델의 출력 결과를 평가하는 데 집중한다 [3-5]. +* **주요 추적 지표**: 사후 관측성 인프라는 세션 리플레이(Session replay), LLM 비용, 지연 시간(latency), 도구 사용 내역 및 동시 에이전트 간의 다중 상호작용(multi-agent interaction) 등을 추적한다 [2, 3]. 특히 세션 리플레이 기능을 통해 엔지니어는 에이전트가 실패한 세션에서 정확히 어떤 작업을 수행했는지 포렌식 수준으로 분석하고 디버깅할 수 있다 [3]. +* **루프 내 검증(In-loop Verification)과의 차별점**: 에이전트 하네스 엔지니어링 관점에서 단순한 사후 평가(post-hoc eval)에만 의존하는 것은 한계가 있으며, 사후 모니터링 인프라 구축과 동시에 하네스 실행 루프 내부에도 결과 검증(verification) 단계를 직접 설계하는 방식이 상호보완적으로 요구된다 [6]. + +## ⚖️ Trade-offs & Caveats +* **사전 예방 불가 및 사후 대응적 특성**: 사후 관측성의 가장 큰 제약은 **실패가 발생한 후에야 해당 실패를 포착(catch failures after they occur)할 뿐, 잘못된 입력 데이터로 인해 야기되는 연쇄적 실패를 원천적으로 예방(prevent)하지는 못한다는 점**이다 [1, 2]. +* **입력 데이터 품질 검증의 부재**: AgentOps나 Langfuse 등의 관측성 도구들은 에이전트의 동작과 출력물만 평가할 뿐 원천 데이터의 품질, 계보(lineage), 인증 여부 등을 모니터링하지 않는다 [5, 7]. 따라서 에이전트가 스키마가 변경되었거나 오래된(stale) 불량 데이터를 읽고 잘못된 결과를 도출하더라도, 도구는 "오답을 생성했다"는 것은 식별하지만 "초기 입력 데이터가 잘못되었다"는 근본 원인을 파악하지 못한다 [8]. +* **평가 점수 왜곡의 위험성**: 불량 데이터가 입력된 상황에서도 모델의 출력 형태 자체는 우수하게 나타나 높은 평가 점수(Evaluation scores)를 받을 가능성이 존재하며, 이는 시스템 실패 원인을 잘못 진단하게 만드는 심각한 오류(misleading)를 초래할 수 있다 [5]. +* **거버넌스 인프라와의 결합 필수**: 사후 관측성 도구만으로는 프로덕션 환경의 안정성을 완벽히 담보할 수 없으므로, 이러한 단점을 해결하기 위해 에이전트가 데이터를 읽기 전에 입력을 검증하고 인증하는 사전 거버넌스(governed data layer) 구조가 필수적으로 뒷받침되어야 한다 [2, 5, 8]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Pre-Action Authorization.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Pre-Action Authorization.md new file mode 100644 index 00000000..abdcaccf --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Pre-Action Authorization.md @@ -0,0 +1,18 @@ +# [[Pre-Action Authorization]] + +## 📌 Brief Summary +**Pre-Action Authorization(사전 행동 승인)**은 AI 에이전트가 도구를 실행하거나 특정 외부 환경에 접근하기 전에 해당 행동의 권한을 동기적으로 가로채어 평가하는 에이전트 하네스의 핵심 보안 제어 메커니즘입니다 [1, 2]. 이 시스템은 단순한 신원 확인을 넘어, 선언적 정책(Declarative Policy)에 따라 에이전트의 특정 행동을 허용, 거부, 또는 인간의 승인 요구 등으로 결정론적(Deterministic) 판정을 내립니다 [1, 2]. 이를 통해 프롬프트 수준의 지시나 신뢰에 의존하지 않고, 샌드박스 실행이나 모델 기반 스크리닝과는 확연히 구별되는 독립적인 보안 인프라 계층을 제공합니다 [1, 2]. + +## 📖 Core Content +* **결정론적 정책 집행 (Deterministic Policy Enforcement):** Open Agent Passport (OAP)와 같은 개방형 규격 및 참조 구현체는 자율 AI 에이전트의 도구 호출을 실행 전에 동기적으로 가로챕니다 [2]. 선언적 정책에 기반해 평가를 수행하며, 암호화된 서명이 포함된 감사 기록을 생성하여 허용적인 정책에서 발생할 수 있는 74.6%의 공격 성공률을 제한적 정책 하에서 0%로 완벽히 차단하는 성과를 입증했습니다 [2]. +* **동적 권한 부여 패브릭 연동:** Microsoft Security의 Authorization Fabric 사례에서 보듯, 권한 제어는 정책 집행 지점(PEP)과 정책 결정 지점(PDP)을 결합한 엔드포인트로 구현됩니다 [1]. 모든 에이전트는 도구 실행 전에 이 패브릭을 호출하여 ALLOW, DENY, REQUIRE_APPROVAL, MASK 중 하나의 명확하고 결정론적인 판정을 받게 됩니다 [1]. +* **인간 개입(HITL) 및 훅(Hooks) 통합:** 민감한 작업의 경우 하네스는 에이전트의 완전 자율 실행을 제한하고 실행을 일시 정지(Interrupt)시켜 인간의 검토 및 승인(Human-in-the-loop)을 기다리는 워크플로우를 강제합니다 [3]. OpenHarness와 같은 프레임워크에서는 `PreToolUse`와 같은 수명 주기 훅(Lifecycle Hooks)이나 대화형 승인 창(Interactive Approval Dialogs)을 통해 매 실행 전에 권한 검사를 수행하도록 구조화되어 있습니다 [4-6]. +* **프롬프트 의존성 탈피:** 에이전트의 권한 관리를 자연어 프롬프트 지시에 맡기지 않고, 인프라스트럭처(하네스) 수준에서 통제합니다 [1]. 이는 인가(Authorization)를 단순히 에이전트가 누구인지(Identity)의 문제를 넘어, 현재의 비즈니스 및 규제 맥락 하에서 '해당 작업을 지금 수행해도 되는지'에 대한 인프라 제어 평면(Control Plane)의 문제로 취급함을 의미합니다 [1]. + +## ⚖️ Trade-offs & Caveats +* **승인 피로도(Approval Fatigue) 발생 위험:** 대화형 승인 등 인간의 개입을 너무 빈번하게 강제할 경우, 사용자가 권한 요청의 93%를 맹목적으로 자동 승인해버려 보안 절차 자체가 무의미해지는 '승인 피로도' 문제가 발생할 수 있습니다 [1]. 이를 방지하기 위해서는 1차적으로 빠른 게이트를 통과시키고 고위험 행동에 대해서만 개입을 요구하거나, 사용자의 신뢰 수준에 따라 확장되는 적응형 권한 모델을 설계해야 하는 까다로운 과제가 뒤따릅니다 [1, 7]. +* **실행 지연 시간(Latency) 증가:** 모든 도구 호출 전에 동기적으로 정책을 평가해야 하므로 에이전트 실행 루프에 필연적인 오버헤드가 발생합니다 [2]. 예를 들어, OAP 정책 집행에는 중간값 53ms의 지연 시간이 소요되며, 실시간 음성 상호작용 등 극도의 저지연(Low-latency) 처리가 요구되는 환경에서는 이러한 시간 지연의 누적이 전체 에이전트의 응답성 저하 원인이 될 수 있습니다 [2, 8]. +* **인프라 아키텍처의 복잡성 증대:** 사전에 권한을 검증하고 서명된 감사 기록을 남기기 위해서는 Microsoft Entra와 같은 외부 인증 시스템이나 복잡한 권한 부여 패브릭과 연동해야 합니다 [1]. 이는 단순한 단일 에이전트 루프를 운영할 때보다 시스템 설정, 세션 관리, 보안 정책의 유지보수 등 하네스의 전반적인 구조적 복잡성을 크게 높이는 반대 급부를 수반합니다 [1, 2]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Sandbox.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Sandbox.md new file mode 100644 index 00000000..eb222581 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Sandbox.md @@ -0,0 +1,21 @@ +# [[Sandbox]] + +## 📌 Brief Summary +샌드박스(Sandbox)는 에이전트 하네스의 5대 핵심 기술 프리미티브 중 하나로, 에이전트가 생성한 코드를 안전하게 실행할 수 있도록 보장하는 격리된 실행 환경이다 [1-4]. 샌드박스는 호스트 시스템을 파괴하지 않도록 보호하고 네트워크를 격리하여 엄격한 보안 경계를 설정한다 [4, 5]. 이를 통해 에이전트가 코드를 안전하게 구동하고 실행 결과를 관찰 및 검증할 수 있는 자율적 루프를 형성하여, AI 에이전트 운영의 필수적인 인프라로 작용한다 [5, 6]. + +## 📖 Core Content +* **에이전트 실행의 격리 및 확장성 제공:** 에이전트가 로컬 환경에서 직접 코드를 실행하는 것은 보안 위험이 따르고 대규모 작업으로 확장하기 어렵다 [6]. 샌드박스를 도입하면 하네스가 샌드박스에 연결하여 안전하게 코드를 실행하고, 파일을 검사하며, 종속성을 설치하여 작업을 완료할 수 있다 [6]. 이러한 환경은 필요에 따라 온디맨드로 생성되고 여러 작업에 분산 배포된 후 작업이 끝나면 폐기될 수 있어 뛰어난 확장성을 제공한다 [6]. +* **주요 아키텍처 및 구현 방식:** + * **MicroVM 기반:** E2B, LangSmith 등은 Firecracker 등을 활용해 150ms 미만의 콜드 스타트, 커널 수준 격리, 리소스 제한(CPU/메모리/디스크) 기능을 갖춘 샌드박스를 제공한다 [7]. + * **컨테이너 기반:** AutoGen은 Docker 네이티브 샌드박싱을 지원하여 격리된 코드 실행 환경을 제공하며 [8], Daytona는 90ms 미만의 시작 속도와 상태 지속성을 갖춘 OCI 컨테이너 기반 샌드박스를 지원한다 [7]. + * **V8 Isolate 기반:** Cloudflare Dynamic Workers와 같이 기존 컨테이너보다 최대 100배 빠르고 메모리 효율적인 방식을 사용하여 수 밀리초 내에 격리 환경을 시작하는 초경량 기술도 활용된다 [9]. + * **운영체제 및 커널 수준 보호:** Cursor는 macOS Seatbelt, Linux Landlock 및 seccomp를 이용한 크로스 플랫폼 샌드박스를 구현하였으며, NVIDIA OpenShell은 Landlock LSM 및 seccomp BPF를 통해 커널 수준의 보안 제어를 제공한다 [7, 9]. +* **제어 평면(Control Plane)과의 엄격한 분리:** 안전한 운영을 위해 샌드박스는 하네스의 제어 평면(인증, 과금, 오케스트레이션)과 샌드박스의 컴퓨팅 평면(파일, 셸, 포트)을 엄격히 분리하도록 설계된다 [9]. 이 과정에서 아웃바운드 HTTP 요청 등을 가로채어 자격 증명(Secrets)과 같은 민감한 정보가 런타임 환경 시스템 외부에 유지되도록 보호한다 [7, 9]. + +## ⚖️ Trade-offs & Caveats +* **샌드박스 제약에 대한 에이전트 훈련의 필요성:** 샌드박스 환경을 도입하더라도, 에이전트가 샌드박스의 제약을 인식하도록 명시적으로 훈련되지 않으면 허용되지 않은 파일 작업이나 네트워크 접근을 시도하다 오류를 발생시킬 수 있다 [7]. +* **설정 파일 보호 한계 및 권한 상승 위험:** 표준적인 샌드박스 격리 기능만으로는 에이전트가 자체 하네스 설정(예: MCP 서버 구성, 훅 파일 등)을 수정하여 권한을 상승시키는 것을 완벽히 막을 수 없다 [7, 9]. 따라서 에이전트에 의해 인프라가 훼손되지 않도록 커널 수준의 강제 제어나 OPA(Open Policy Agent) 기반 프록시와 같은 추가적인 보안 아키텍처가 동반되어야 한다 [9]. +* **운영 복잡성 및 지연 시간(Latency) 트레이드오프:** 파일 시스템과 샌드박스를 결합한 환경은 컨테이너화된 배포 환경에서 운영 복잡성을 가중시킬 수 있다 [10]. 또한, 샌드박스 아키텍처 선택에 따라 지연 시간과 기능성 간의 반대 급부가 존재한다. AIO Sandbox처럼 풍부한 기능(브라우저, 셸, VSCode 서버 등)을 갖춘 환경은 구동에 4~8초가 소요되는 반면 [11], V8 Isolate 기반 환경은 밀리초 단위로 매우 빠르게 시작되지만 실행할 수 있는 코드와 메모리 제약이 따를 수 있다 [9]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Schema Drift (스키마 표류).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Schema Drift (스키마 표류).md new file mode 100644 index 00000000..4e0e8238 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Schema Drift (스키마 표류).md @@ -0,0 +1,16 @@ +# [[Schema Drift (스키마 표류)]] + +## 📌 Brief Summary +스키마 표류(Schema Drift)는 AI 에이전트가 읽고 처리하는 데이터 구조나 스키마의 예상치 못한 변경이나 불일치를 의미합니다 [1]. 엔터프라이즈 규모의 에이전트 배포 환경에서 오래된 테이블, 인증되지 않은 데이터 소스와 함께 에이전트 실패를 유발하는 가장 흔한 근본 원인 중 하나로 꼽힙니다 [1]. 에이전트 오케스트레이션 프레임워크는 이를 감지하는 기본 기능이 부족하여, 입력 단계가 아닌 작업 완료 시점이나 잘못된 결과가 생성된 이후에야 실패가 드러나는 치명적인 문제를 발생시킵니다 [2-4]. + +## 📖 Core Content +* **에이전트 생산 실패의 주요 원인**: 스키마 표류, 오래된 데이터, 인증되지 않은 소스는 프로덕션 환경에서 에이전트 신뢰성을 떨어뜨리는 핵심 위험 요소입니다 [1]. 실제로 엔터프라이즈급 AI 에이전트 프로젝트의 약 88%가 생산 단계에 도달하지 못하는데, 이는 모델의 지능 부족보다는 **스키마 불일치(Schema Mismatch) 및 컨텍스트 표류 등 하네스 환경의 결함 때문**인 경우가 많습니다 [5]. +* **오케스트레이션 프레임워크의 구조적 한계**: LangGraph, Microsoft Semantic Kernel 등 대부분의 오케스트레이션 프레임워크는 **에이전트가 '어떻게' 실행되는지는 관리하지만, '무엇을' 읽는지는 검증하지 않습니다** [1, 2]. 따라서 접근 권한 제어(RBAC)가 적용되어 있더라도 스키마 표류가 발생한 데이터는 아무런 유효성 검사 없이 프레임워크를 그대로 통과하게 됩니다 [4, 6]. +* **사전 예방을 위한 데이터 컨트랙트(Data Contracts) 적용**: 스키마 표류 문제를 해결하기 위해서는 에이전트의 컨텍스트 윈도우에 데이터가 진입하기 전에 스키마 계약을 강제하는 데이터 거버넌스 계층(예: Atlan)이 필수적입니다 [3]. 이를 통해 에이전트가 잘못된 결과를 출력한 후가 아니라, **에이전트가 데이터를 읽기 전 사전(Proactive)에 스키마 표류를 잡아낼 수 있습니다** [3]. + +## ⚖️ Trade-offs & Caveats +* **사후(Post-hoc) 모니터링 도구의 한계**: AgentOps나 Langfuse와 같은 관측성(Observability) 도구는 에이전트가 실행된 이후를 기록하기 때문에 에이전트가 잘못된 결과를 생성했다는 사실은 파악할 수 있지만, 그 원인이 **스키마 표류와 같은 불량 입력 데이터 때문이라는 것을 근본적으로 방지하거나 식별하는 데에는 한계**가 있습니다 [4]. +* **데이터 거버넌스 계층 추가에 따른 구조적 복잡성**: 스키마 표류로 인한 에이전트 실패를 근본적으로 막기 위해서는 프레임워크나 오케스트레이션의 고도화만으로는 부족하며, 별도의 거버넌스된 데이터 기저(Governed data substrate)가 요구됩니다 [7, 8]. 이는 에이전트 하네스 파이프라인에 데이터 계약 및 활성 메타데이터, 인증 인프라를 추가로 구축해야 함을 의미하며, 시스템 아키텍처의 복잡성과 초기 구축 비용을 증가시킵니다 [3, 4, 8]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Server-Sent Events (SSE).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Server-Sent Events (SSE).md new file mode 100644 index 00000000..276ae495 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Server-Sent Events (SSE).md @@ -0,0 +1,17 @@ +# [[Server-Sent Events (SSE)]] + +## 📌 Brief Summary +Server-Sent Events (SSE)는 에이전트 하네스 환경에서 모델이나 서버가 클라이언트 혹은 다른 에이전트에게 실시간으로 이벤트를 스트리밍하기 위해 사용하는 통신 프로토콜이다 [1, 2]. 주로 자율형 관리형 에이전트의 출력 스트리밍을 담당하며, 에이전트 간 통신(A2A) 및 모델 컨텍스트 프로토콜(MCP) 등에서 데이터를 주고받기 위한 핵심 전송 방식으로 활용된다 [1, 2]. + +## 📖 Core Content +* **관리형 에이전트 환경의 실시간 스트리밍 지원**: Anthropic이 공개한 Claude용 관리형 에이전트 하네스(Claude Managed Agents)는 보안 샌드박스와 내장 도구를 비롯해 서버 전송 이벤트 스트리밍(server-sent event streaming)을 기본 기능으로 지원하여 에이전트의 자율적 작동 상태를 지속적으로 확인할 수 있도록 돕는다 [1]. +* **에이전트 간(Agent-to-Agent, A2A) 통신 프로토콜**: Google이 개발한 개방형 A2A 프로토콜은 에이전트 카드(Agent Card) 서비스 검색 기능과 함께 HTTP(S)/SSE 기반의 JSON-RPC를 통신 규격으로 활용하여 에이전트 간의 상호운용성을 지원한다 [2]. +* **MCP(Model Context Protocol) 원격 서버 전송 규격**: 외부 도구 연동을 위한 MCP에서는 로컬 프로세스가 아닌 원격 서비스로 서버를 실행할 수 있도록 스트리밍 가능한 HTTP 전송(Streamable HTTP Transport) 방식을 지원한다 [2]. 이 구조에서 서버는 다중 클라이언트 연결을 처리하며, 클라이언트에서 서버로 향하는 메시지는 HTTP POST를, 서버에서 클라이언트로 향하는 SSE 스트림에는 선택적(optional) GET 요청을 활용한다 [2]. + +## ⚖️ Trade-offs & Caveats +* **원격 배포의 이점과 세션 관리 복잡성 증가**: 2025년 11월 25일 자 MCP 규격에서 기존의 HTTP+SSE 방식을 스트리밍 가능한 HTTP(Streamable HTTP) 전송으로 변경함으로써 원격 MCP 배포가 가능해졌으나, 이는 심각한 세션 관리의 복잡성을 유발하는 부작용(Trade-off)을 가져왔다 [2]. +* **상태 유지(Stateful) 헤더의 확장성 한계**: 구체적으로 스트림을 식별하고 상태를 유지해야 하는 `Mcp-Session-Id` 헤더가 로드 밸런서 및 아키텍처의 수평적 확장(Horizontal Scaling)과 구조적으로 충돌하는 문제가 발생했다 [2]. 이러한 구조적 제약으로 인해 2026년 MCP 로드맵에서는 세션을 전송 계층(Transport layer)과 완전히 분리하는 방식의 개선을 필수 과제로 다루고 있다 [2]. +* *참고: SSE의 근본적인 웹 통신 구조나 하위 수준의 기술 원리에 대한 소스의 관련 정보는 부족합니다.* + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Token Savior.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Token Savior.md new file mode 100644 index 00000000..2c1d15bd --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/Token Savior.md @@ -0,0 +1,15 @@ +# [[Token Savior]] + +## 📌 Brief Summary +Token Savior는 코딩 에이전트를 위한 MCP(Model Context Protocol) 서버 아키텍처입니다 [1]. 에이전트가 전체 파일을 읽는 대신 함수, 클래스, 호출 그래프 등의 기호를 기준으로 코드베이스를 색인화하여 포인터로 탐색할 수 있도록 지원합니다 [1]. 이를 통해 활성 토큰 사용량을 77% 줄이고 벤치마크 소요 시간을 76% 단축하는 효과를 제공합니다 [1]. 결과적으로 코딩 에이전트의 컨텍스트 전달이 단순한 데이터 압축 문제가 아니라 효율적인 탐색(Navigation)의 문제임을 입증하는 도구입니다 [1]. + +## 📖 Core Content +* **기호 기반의 코드베이스 색인화 및 탐색**: Token Savior는 에이전트가 방대한 코드베이스를 분석할 때 무거운 전체 파일을 읽어 들이는 방식을 탈피합니다 [1]. 대신 함수, 클래스, 호출 그래프(Call graphs)와 같은 **기호(Symbol)를 기준으로 코드를 색인화**하여, 에이전트가 포인터(Pointer)를 통해 필요한 영역만 정밀하게 탐색할 수 있게 합니다 [1]. +* **획기적인 리소스 및 실행 시간 최적화**: 코드의 필요한 부분만 선별적으로 접근할 수 있는 탐색 구조 덕분에, 에이전트 구동 시 발생하는 **활성 토큰(Active tokens) 소비를 77%나 삭감**하는 탁월한 효율성을 보여줍니다 [1]. 더불어 벤치마크 환경에서의 **소요 시간(Wall time)을 76%까지 단축**시킵니다 [1]. +* **컨텍스트 엔지니어링 패러다임의 전환**: Token Savior의 사례는 코딩 에이전트를 위한 컨텍스트 전달(Context delivery) 방식에 중요한 시사점을 던집니다 [1]. 즉, 제한된 컨텍스트 윈도우 내에서 정보를 단순히 **압축(Compression)하는 문제가 아니라, 코드베이스 내비게이션(Navigation) 아키텍처의 문제**로 접근해야 함을 실증적으로 증명합니다 [1]. + +## ⚖️ Trade-offs & Caveats +소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/가드레일 (Guardrails) 및 제어 시스템.md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/가드레일 (Guardrails) 및 제어 시스템.md new file mode 100644 index 00000000..14330d4d --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/가드레일 (Guardrails) 및 제어 시스템.md @@ -0,0 +1,19 @@ +# [[가드레일 (Guardrails) 및 제어 시스템]] + +## 📌 Brief Summary +에이전트 하네스에서 가드레일 및 제어 시스템은 인공지능 모델이 무단, 파괴적 혹은 환각적인 행동을 취하는 것을 방지하는 필수적인 인프라 보안 계층입니다 [1-3]. 이 시스템은 모델의 확률적인(Probabilistic) 추론과 결정을 물리적 시스템의 결정론적(Deterministic) 규칙 및 안전 프로토콜로 제한하여 신뢰성을 확보합니다 [4]. 기업의 보안 요구사항을 충족시키기 위해 샌드박스 격리, 도구 호출 검증, 다계층 권한 부여, 그리고 인간 개입(HITL) 메커니즘을 통합하여 에이전트의 자율성을 통제합니다 [2, 5, 6]. + +## 📖 Core Content +* **권한 및 인가 관리 (Permissions & Authorization)**: 하네스는 모델이 특정 도구를 실행하기 전에 이를 승인할지 결정하는 세밀한 다계층 제어 시스템을 포함합니다 [1, 7]. 에이전트는 다중 수준 권한 모드(예: Default, Auto, Plan Mode), 경로 수준(Path-level) 통제 규칙, 그리고 도구 실행 전후에 개입하는 수명 주기 훅(PreToolUse / PostToolUse Hooks)의 통제를 받습니다 [8, 9]. 인증된 환경에서는 단순한 신원 확인을 넘어 OPA(Open Policy Agent) 정책 게이트나 인가 패브릭(Authorization Fabric)을 활용하여 비즈니스 및 규제 맥락에 따라 '허용', '거부', '승인 필요' 등의 결정을 내립니다 [2, 7]. +* **인간 개입 (Human-in-the-Loop, HITL) 통제**: 생산 데이터베이스 쓰기, 외부 이메일 전송 등 민감하고 위험도가 높은 작업의 경우, 하네스는 모델의 실행을 일시 중단시키고 사람의 승인을 요구하는 인터럽트(Interrupts) 워크플로우를 강제합니다 [6, 10]. 사용자는 단순한 승인과 거부뿐만 아니라 '변경 후 승인(approve with changes)' 등을 통해 도구 입력값을 직접 수정할 수도 있으며, 이를 통해 인공지능이 노동을 수행하되 인간이 최종적인 통제권과 책임을 유지하도록 합니다 [10-12]. +* **실행 샌드박스 및 환경 격리 (Sandboxing & Isolation)**: 에이전트가 자율적으로 생성한 코드가 호스트 시스템을 오염시키거나 파괴하지 못하도록, 하네스는 Docker, OCI 컨테이너, 혹은 Firecracker 마이크로VM과 같이 격리된 샌드박스 환경 내에서만 실행을 허용합니다 [5, 13, 14]. 고도화된 샌드박스는 커널 수준의 격리(Landlock, seccomp)나 엄격한 네트워크 송신 제한을 강제하여 에이전트의 무단 접근을 원천 차단합니다 [5, 15]. +* **도구 호출 검증 (Tool Validation)**: 모델이 존재하지 않는 API를 호출하거나 잘못된 매개변수 유형을 사용하는 환각(Hallucination) 오류를 방지하기 위해, 하네스는 실행 전에 도구 호출을 가로채어 스키마를 검증합니다 [16-18]. 만약 오류가 발생하면 시스템에 치명적인 에러를 발생시키는 대신, 린터(Linter) 메시지 등 정제된 피드백을 모델에 반환하여 스스로 코드를 수정할 수 있는 자가 치유(Self-healing) 루프를 유도합니다 [18, 19]. + +## ⚖️ Trade-offs & Caveats +* **승인 피로(Approval Fatigue) 현상**: 모든 행동에 권한 확인이나 승인 게이트를 추가할 경우 사용자에게 심각한 '승인 피로'가 발생할 수 있습니다 [7]. 사용자가 93% 이상의 프롬프트를 기계적으로 자동 승인하게 되면 가드레일은 본래의 감시 목적을 상실하고 유명무실해지며, 에이전트 시스템의 처리 속도와 자율성만 크게 저하시키는 부작용을 초래합니다 [7, 20]. +* **컨텍스트 부패(Context Rot)와 비용 증가**: 모델이 실패를 반복하거나 하네스가 검증을 위해 지속적으로 에러 메시지와 긴 로그를 컨텍스트에 주입할 경우, 컨텍스트 윈도우가 빠르게 소진되는 문제가 발생합니다 [21, 22]. 이는 모델이 초기 지시사항을 망각하게 만들며 결과적으로 불필요한 토큰 낭비와 연산 오버헤드(비용 증가)로 이어집니다 [22, 23]. +* **무한 루프(Doom Loops) 위험성**: 대규모 언어 모델의 비결정론적 특성상, 샌드박스나 권한 제어에 의해 특정 도구 실행이 차단되었음에도 불구하고 모델이 해결책을 재고하지 못하고 계속해서 동일한 잘못된 코드나 도구 호출을 시도하는 무한 루프에 빠질 위험이 있습니다 [18, 24]. +* **하네스 설정 파일 보호의 한계**: 에이전트가 샌드박스 내에서 활동하더라도, MCP(Model Context Protocol) 서버 설정 파일이나 훅(Hook) 파일 등 하네스 자신의 설정 환경에 에이전트가 쓰기 권한을 가지게 되면 문제가 됩니다 [5]. 에이전트가 자신의 안전 장치 설정을 수정하여 스스로 권한을 상승시키는 심각한 보안 헛점이 발생할 수 있으므로 이에 대한 엄격한 격리가 보장되어야 합니다 [5]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 수준 권한 모드 (Multi-Level Permission Modes).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 수준 권한 모드 (Multi-Level Permission Modes).md new file mode 100644 index 00000000..3026abd0 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 수준 권한 모드 (Multi-Level Permission Modes).md @@ -0,0 +1,3 @@ +**Refining the Summary** + +I'm now integrating information about the 'Human-in-the-Loop' (HITL) control, recognizing its crucial role in managing sensitive operations by pausing execution and awaiting human approval, drawing from the Firecrawl source. I am synthesizing content for the report. I am incorporating definitions and specifics for the "Brief Summary" section. I have a draft definition for the Multi-Level Permission Modes. I will follow up with key features and types. \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 오케스트레이션 (Multi-Agent Orchestration).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 오케스트레이션 (Multi-Agent Orchestration).md new file mode 100644 index 00000000..54adec81 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 오케스트레이션 (Multi-Agent Orchestration).md @@ -0,0 +1,23 @@ +# [[다중 에이전트 오케스트레이션 (Multi-Agent Orchestration)]] + +## 📌 Brief Summary +다중 에이전트 오케스트레이션(Multi-Agent Orchestration)은 단일 에이전트의 역량을 초월하는 복잡한 과제를 해결하기 위해 여러 전문 AI 에이전트(또는 하위 에이전트)를 생성하고 조율하는 기술적 제어 과정이다 [1, 2]. 이는 현대적인 에이전트 하네스의 핵심 기능으로, 역할 기반 협업, 작업 위임, 대화형 상호작용 등 다양한 아키텍처 패턴을 통해 컨텍스트를 격리하고 작업을 효율적으로 분담한다 [3, 4]. 궁극적으로 분산된 에이전트 간의 통신과 핸드오프(Handoff)를 제어하여 복잡한 목표를 신뢰성 있게 달성하도록 돕는 인프라스트럭처 역할을 수행한다 [4, 5]. + +## 📖 Core Content +* **오케스트레이션의 목적과 컨텍스트 격리 효과:** 다중 에이전트 관리는 크고 복잡한 작업을 위해 병렬 작업자를 생성(Spawning)하는 하네스의 핵심 구성 요소 중 하나이다 [1]. 거대한 단일 스킬이나 프롬프트를 사용하는 대신, 관련 지점에서 하위 에이전트를 분리하여 컨텍스트 윈도우를 좁게 유지한다 [6]. 이를 통해 교차 도메인 간의 컨텍스트 비대화를 방지하고 단일 에이전트 접근법에 비해 토큰 처리량을 크게 줄이는 이점을 제공한다 [4]. +* **주요 오케스트레이션 아키텍처 및 토폴로지:** + * **역할 및 대화 기반(Role-based / Conversational):** CrewAI와 같은 프레임워크는 에이전트에게 페르소나, 도구, 목표를 할당하고 A2A(Agent-to-Agent) 메시징을 통해 협업하게 하는 '직원으로의 에이전트' 모델을 사용한다 [7]. AutoGen은 여러 에이전트가 교대로 제안, 비판, 결과물 개선을 수행하는 다중 턴(Multi-turn) 토론 패턴을 지원한다 [8]. + * **그래프 및 상태 기반(Graph-based / Stateful):** LangGraph는 조건부 엣지, 체크포인트 및 스트리밍을 통해 엔지니어가 에이전트의 상태를 명시적으로 제어할 수 있는 방향성 그래프 기반의 오케스트레이션을 제공한다 [9, 10]. + * **표준화된 팀 아키텍처 패턴:** `revfactory/harness` 및 Claude Code 생태계에서는 순차 의존 작업을 위한 **파이프라인(Pipeline)**, 병렬 독립 작업을 위한 **팬아웃/팬인(Fan-out/Fan-in)**, 상황별 선택을 위한 **전문가 풀(Expert Pool)**, **생성-검증(Generate-Verify)**, **감독자(Supervisor)**, 그리고 **계층적 위임(Hierarchical Delegation)** 등 6가지 사전 정의된 아키텍처 패턴을 활용한다 [5, 11]. + * **동적 및 분리형 오케스트레이션:** 작업 종속성 그래프에 따라 병렬, 순차, 계층 등 토폴로지를 동적으로 선택하는 AdaptOrch 기술이나, 계획과 실행을 분리하여 특정 하위 작업의 재계획이 전체 실패로 이어지지 않게 하는 작업 분리형 계획(TDP) 프레임워크가 연구 및 적용되고 있다 [12]. + * **중앙 제어가 없는 자율 협업:** 중앙 오케스트레이터 없이 공유된 파일 시스템이나 Git 리포지토리를 통해 여러 에이전트가 자율적으로 작업을 청구(Claim)하고 충돌을 해결하며 병렬로 작업을 수행하는 탈중앙화 패턴도 존재한다 [10]. +* **산업계 구현 사례:** xAI의 Grok 4.20은 4개의 전문 에이전트가 병렬로 협의하는 다중 에이전트 협업 시스템으로 구성되며 [13], Moonshot AI의 Kimi K2.5는 복잡한 작업을 분해해 최대 100개의 하위 에이전트에게 동시 위임하는 에이전트 스웜(Agent Swarm) 기능을 지원한다 [2]. + +## ⚖️ Trade-offs & Caveats +* **분산 시스템 수준의 복잡성과 핸드오프(Handoff) 오류:** 다중 에이전트 시스템은 본질적으로 분산 시스템처럼 작동하므로 에이전트 간의 작업 이관(Handoff) 시 실패할 확률이 높다 [4]. 이를 방지하기 위해서는 타입이 지정된 스키마, 제한된 작업 범위, 그리고 명시적인 경계 검증(Boundary validation)이 반드시 수반되어야 하는 구현 상의 제약이 존재한다 [4]. +* **디버깅과 근본 원인 분석의 어려움:** 동시 다발적인 에이전트 실행은 디버깅을 매우 까다롭게 만든다. 여러 에이전트가 병렬로 로그를 남기기 때문에, 결과물이 잘못되었을 때 그 원인이 모델에 있는지, 프롬프트에 있는지, 혹은 에이전트가 읽은 소스 데이터의 결함인지 추적하기가 단일 에이전트에 비해 훨씬 어렵다 [14]. 이를 해결하기 위해 인과 관계 그래프(Causal graph) 추적 등 고도화된 디버깅 기법이 별도로 요구된다 [15]. +* **무한 루프(Infinite Loops) 교착 상태:** AutoGen과 같은 대화형 에이전트 프레임워크에서는 두 에이전트가 합의에 이르지 못하고 서로 비판과 제안을 무한히 반복하는 교착 상태(Looping indefinitely)에 빠지는 것이 알려진 실패 모드이다 [8]. 이 경우 자동화된 해결이 어려워 수동적인 인간의 개입(Manual intervention)이 불가피하다는 단점이 있다 [8]. +* **시스템 오버헤드 증가:** 특화된 여러 에이전트에게 역할을 분담하면 작업 효율성과 결과 품질은 향상되지만 [16], 에이전트 간의 종속성을 관리하고 여러 모델을 동시에 호출함에 따라 지연 시간(Latency) 및 토큰 소모 비용, 시스템 성능 오버헤드가 새롭게 발생한다 [3]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 조율 (Multi-Agent Coordination).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 조율 (Multi-Agent Coordination).md new file mode 100644 index 00000000..ef050dd9 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/다중 에이전트 조율 (Multi-Agent Coordination).md @@ -0,0 +1,23 @@ +# [[다중 에이전트 조율 (Multi-Agent Coordination)]] + +## 📌 Brief Summary +다중 에이전트 조율(Multi-Agent Coordination)은 복잡하고 모호한 문제를 해결하기 위해 단일 AI 모델에 의존하는 대신, 특정 역할과 전문성을 지닌 여러 하위 에이전트(Sub-agents)를 생성하고 이들의 협업을 관리하는 에이전트 하네스 아키텍처이다 [1-3]. 에이전트 하네스는 파이프라인, 감독자, 계층적 위임 등의 구조를 통해 에이전트 간의 데이터 핸드오프(Handoff), 작업 분배 및 컨텍스트 격리를 조율한다 [2, 4, 5]. 이를 통해 단일 컨텍스트 윈도우의 한계를 극복하고 긴 작업 시간 동안 시스템의 일관성과 신뢰성을 유지할 수 있다 [1, 3]. + +## 📖 Core Content +* **다중 에이전트 아키텍처 패턴**: 복잡한 작업을 분해하고 조율하기 위해 하네스는 사전 정의된 다양한 팀 아키텍처 패턴을 제공한다. 대표적으로 순차적 의존 작업을 처리하는 **파이프라인(Pipeline)**, 병렬 독립 작업을 수행하는 **팬아웃/팬인(Fan-out/Fan-in)**, 상황별로 적합한 에이전트를 호출하는 **전문가 풀(Expert Pool)**, 산출물 품질을 검수하는 **생성-검증(Generate-Verify)**, 중앙 에이전트가 작업을 동적으로 분배하는 **감독자(Supervisor)**, 상위에서 하위로 작업을 나누는 **계층적 위임(Hierarchical Delegation)** 패턴이 있다 [4, 5]. +* **조율 프레임워크 설계 방식**: + * **역할 기반(Role-based) 협업**: CrewAI와 같은 프레임워크는 에이전트에게 연구자, 작성자 등 명확한 페르소나(역할)와 목표를 부여하여 '직원'처럼 협업하게 하며, A2A(Agent-to-Agent) 메시징 프로토콜을 통해 소통을 조율한다 [6, 7]. + * **대화 및 토론 기반(Conversational)**: AutoGen(AG2)과 같은 시스템은 다수의 에이전트가 다중 턴(Multi-turn)에 걸쳐 서로 제안, 비판, 개선을 주고받는 토론 패턴을 통해 결과물의 신뢰성을 높인다 [8]. + * **그래프 기반 상태 제어(Graph-based)**: LangGraph는 에이전트의 행동을 방향성 그래프의 노드와 엣지로 모델링하여, 복잡한 조건부 라우팅 및 명시적인 상태 관리를 수행한다 [9, 10]. +* **컨텍스트 격리 및 핸드오프(Handoff) 관리**: 여러 전문 에이전트를 조율할 때, 하네스는 이전 단계의 불필요한 전체 대화 이력을 제외하고 오직 현재 작업에 관련된 컨텍스트만 다음 에이전트에게 전달(Handoff)한다 [2, 11]. 이러한 하위 에이전트 간의 컨텍스트 격리(Context isolation)는 단일 에이전트가 모든 스킬을 처리할 때 발생하는 정보 팽창(Context bloat)을 방지하여 토큰 효율성을 극대화한다 [1, 12]. +* **실제 적용 사례**: Kimi K2.5 모델은 복잡한 작업을 분해하여 최대 100개의 AI 하위 에이전트를 동시에 작동시키는 'Agent Swarm' 기능을 도입했으며 [13], xAI의 Grok 4.20은 단일 모델이 아닌 4개의 전문 에이전트 평의회(Council)가 병렬로 숙고하여 응답하는 다중 에이전트 협업 시스템을 채택했다 [14]. + +## ⚖️ Trade-offs & Caveats +* **분산 시스템의 복잡성과 핸드오프 경계 취약성**: 다중 에이전트 시스템은 본질적으로 분산 시스템처럼 동작한다. 따라서 에이전트 간 작업을 넘겨주는 핸드오프 시 엄격하게 타입이 지정된 스키마, 제한된 액션 스키마, 명시적인 경계 검증이 이루어지지 않으면 연쇄적인 시스템 실패가 발생할 수 있다 [1]. +* **무한 루프(Infinite Looping) 및 수동 개입**: AutoGen과 같은 대화형/토론형 에이전트 프레임워크에서는 두 에이전트가 끝없이 서로 비판하거나 응답하는 무한 루프 상태에 빠지는 알려진 실패 모드가 있으며, 이는 인간의 수동 개입이나 정교한 종료 조건 설정을 요구한다 [8]. +* **동시 실행(Concurrent Execution)으로 인한 디버깅 난이도 증가**: 다중 에이전트가 병렬로 동시에 실행될 경우, 최종 결과물이 잘못되었을 때 그 실패가 모델의 추론 오류인지, 프롬프트 문제인지, 혹은 특정 에이전트가 읽은 입력 데이터의 문제인지 근본 원인을 역추적하고 디버깅하기가 매우 까다로워진다 [7]. +* **컨텍스트 관리의 운영 부담**: 에이전트 간의 다중 턴 대화가 증가할수록 컨텍스트가 빠르게 누적된다. 자동 압축(Compaction)이나 상태 관리가 내장되지 않은 시스템에서는 토큰 윈도우 한계를 피하기 위해 누적된 컨텍스트를 수동으로 가지치기(Prune)해야 하는 제약이 따른다 [8]. +* **설정 편의성과 제어력의 상충 관계(Trade-off)**: CrewAI 같은 역할 기반 조율은 설정이 간단하고 가장 빠르게 프로토타입을 만들 수 있지만, 에이전트의 세밀한 상태 제어가 부족하다. 반면, LangGraph 같은 그래프 기반 시스템은 장기 실행 복구(Checkpointing) 및 세밀한 제어가 가능하지만, 단순한 워크플로우에도 설정이 장황해지고 학습 곡선이 가파르다는 반대 급부가 존재한다 [6, 15, 16]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 거버넌스 (Data Governance).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 거버넌스 (Data Governance).md new file mode 100644 index 00000000..48e05ee4 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 거버넌스 (Data Governance).md @@ -0,0 +1,21 @@ +# [[데이터 거버넌스 (Data Governance)]] + +## 📌 Brief Summary +데이터 거버넌스(Data Governance)는 에이전트 하네스 환경에서 AI 에이전트가 읽고 처리하는 데이터 입력값의 신뢰성, 출처, 스키마 안정성 등을 사전에 검증하고 관리하는 인프라 계층을 의미한다 [1-3]. 일반적인 에이전트 오케스트레이션 프레임워크 자체는 데이터 품질을 통제하지 못하므로, 에이전트가 유효하고 검증된 데이터만 활용할 수 있도록 보장하는 거버넌스 기저(Governed data substrate)가 필수적으로 요구된다 [3-5]. 이는 엔터프라이즈 규모에서 보안 위험과 치명적 실패를 예방하고 규정 준수를 달성하기 위한 핵심 시스템이다 [6, 7]. + +## 📖 Core Content +* **데이터 품질 격차와 거버넌스의 필요성**: AI 에이전트 도입 시간의 약 80%는 데이터 엔지니어링과 거버넌스 작업에 소요되며, 기업의 80%가 에이전트 AI 확장의 주된 장애물로 데이터의 한계를 지목한다 [8, 9]. 메모리 오염이나 연쇄 실패 등 에이전트 애플리케이션의 가장 치명적인 보안 위험은 대부분 하네스에 잘못된 데이터가 유입되어 발생한다 [10]. 흔히 LLM의 환각(Hallucination)으로 치부되는 문제들의 상당수도 실제로는 일관성 없고 오래된 데이터 소스에서 기인한 거버넌스의 실패이다 [10]. +* **거버넌스 데이터 기저(Governed Data Substrate)의 핵심 요소**: 에이전트 하네스의 기반이 되는 데이터 계층은 다음과 같은 거버넌스 요소로 구성된다. + * **액티브 메타데이터(Active metadata)**: 데이터 시스템의 최신 상태, 인증 여부, 스키마 정보를 실시간 모니터링하여 에이전트에게 구조화된 컨텍스트로 제공한다 [11]. + * **데이터 계약(Data contracts)**: 데이터가 하네스 컨텍스트에 진입하기 전에 스키마를 강제 검증하여, 스키마 표류(Schema drift)로 인한 에이전트의 오작동을 사전에 차단한다 [11]. + * **데이터 계보(Data lineage)**: 열(Column) 단위의 엔드투엔드 추적을 통해, 에이전트가 생성한 잘못된 출력의 근본 원인이 모델인지, 프롬프트인지, 혹은 원본 데이터인지를 명확히 분석할 수 있게 한다 [12]. + * **인증 상태(Certification status)**: 데이터 관리자가 명시적으로 인증한 데이터 자산만 에이전트가 읽도록 제한하여 엔터프라이즈 및 규제 산업에 필요한 감사 추적(Audit trail)을 보장한다 [6, 12]. +* **조직 및 플랫폼 수준의 거버넌스 구현**: 중앙 집중화된 에이전트 제어를 위해 AWS, Google Cloud 등은 에이전트 도구, 스킬, MCP 서버 등을 관리하는 거버넌스 카탈로그 및 레지스트리를 구축하여 승인 워크플로우와 통제 권한을 제공한다 [13, 14]. 또한 Microsoft Copilot Studio 등은 팀 수준의 접근 권한 제어와 다중 에이전트 오케스트레이션을 위한 고급 거버넌스 관리 기능을 통합하고 있다 [15]. + +## ⚖️ Trade-offs & Caveats +* **사후 관측성(Observability) 도구와의 혼동 위험**: AgentOps나 Langfuse 같은 에이전트 모니터링 도구는 에이전트가 잘못된 데이터를 처리한 후 발생한 실패를 사후에(Post-hoc) 포착할 뿐, 소스 단계에서 불량 데이터를 예방하는 거버넌스 역할을 대신할 수 없다 [5, 16-18]. 에이전트가 모델 출력 평가에서 높은 점수를 받더라도, 오래되거나 검증되지 않은 데이터 입력에서 도출된 결과라면 심각한 오류를 내포할 수 있다는 근본적인 한계가 존재한다 [19]. +* **아키텍처의 복잡성 및 리소스 소모 증가**: 엄격한 거버넌스를 달성하기 위해 권한 제어(RBAC), 샌드박싱, 감사 추적, 중앙 API 레지스트리 통합 등 다양한 통제 장치를 도입해야 하며, 이는 하네스 설계의 복잡성과 초기 시스템 구축 비용 및 시간을 크게 증가시킨다 [7, 8, 13, 14]. +* **프레임워크 자체 거버넌스의 부재**: LangGraph, CrewAI, AutoGen과 같은 대부분의 널리 쓰이는 하네스 오케스트레이션 프레임워크는 입력되는 데이터의 스키마 안정성이나 신뢰성을 스스로 검증하는 기능을 제공하지 않는다 [2, 4, 5, 20, 21]. 따라서 조직은 기존 프레임워크 도입에 그치지 않고, 별도의 데이터 거버넌스 계층(예: Atlan 등)을 추가로 통합해야 하는 기술적 과제를 안게 된다 [3, 4, 22]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 품질 계층 (Data Quality Layer).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 품질 계층 (Data Quality Layer).md new file mode 100644 index 00000000..ffca540c --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/데이터 품질 계층 (Data Quality Layer).md @@ -0,0 +1,21 @@ +# [[데이터 품질 계층 (Data Quality Layer)]] + +## 📌 Brief Summary +데이터 품질 계층은 AI 에이전트 하네스가 모델에 주입하는 데이터와 컨텍스트의 신뢰성을 사전에 검증하고 거버넌스를 부여하는 필수 인프라 계층이다. 현존하는 대부분의 에이전트 프레임워크는 실행 제어와 오케스트레이션만을 다룰 뿐, 에이전트가 읽어 들이는 데이터 자체의 품질을 관리하지 못하는 구조적 공백을 가지고 있다. 따라서 데이터 품질 계층은 데이터의 최신성, 스키마 안정성, 출처 등을 인증하여 저품질 데이터로 인한 에이전트의 환각(Hallucination)과 연쇄적인 운영 오류를 원천적으로 방지하는 기반 역할을 수행한다. + +## 📖 Core Content +* **구조적 공백과 거버넌스의 필요성:** LangGraph, CrewAI, AutoGen 등 2026년의 주요 에이전트 하네스 프레임워크들은 에이전트가 실행되는 방식(제어 계층)만을 관리하며, 입력되는 데이터의 신뢰성, 최신성, 인증 여부를 검증하는 기능은 제공하지 않는다 [1-5]. AI 거버넌스 연구에 따르면, 흔히 모델의 '환각(Hallucination)'으로 치부되는 문제의 상당수는 실제로는 일관성 없거나 기한이 지난(stale), 혹은 불완전하게 복제된 데이터 소스에서 기인한다 [6, 7]. 맥킨지(McKinsey)의 조사에서도 에이전트형 AI 구현에 소요되는 시간의 80%가 프레임워크 구성이 아닌 데이터 엔지니어링과 거버넌스 작업에 쓰이며, 기업 10곳 중 8곳이 데이터 한계를 확장의 가장 큰 장애물로 지목하고 있다 [6-8]. +* **데이터 품질 계층의 필수 구성 요소:** 에이전트 파이프라인의 신뢰성을 확보하기 위해 도입되는 데이터 품질 인프라(예: Atlan)는 에이전트의 컨텍스트 윈도우에 정보가 들어가기 전에 다음과 같은 기능을 제공해야 한다 [9-13]. + * **액티브 메타데이터 (Active Metadata):** 데이터 시스템을 지속적으로 모니터링하여 메타데이터의 최신성, 실시간 인증 상태, 스키마 상태를 에이전트에게 구조화된 컨텍스트로 전달한다 [11]. + * **데이터 계약 (Data Contracts):** 데이터가 하네스 환경에 유입되기 전 스키마 계약을 강제하여, 에이전트가 변형된 스키마(Schema drift)를 읽고 잘못된 결과를 내기 전에 선제적으로 오류를 차단한다 [11]. + * **데이터 리니지 (Data Lineage):** 컬럼(Column) 단위의 데이터 계보를 추적하여 에이전트가 정보의 원천을 확인할 수 있도록 한다. 이를 통해 출력 오류 발생 시 문제의 근본 원인이 모델인지, 프롬프트인지, 원본 데이터인지 명확히 식별할 수 있다 [12]. + * **인증 상태 (Certification Status):** 데이터 스튜어드가 데이터를 인증하고, 에이전트가 인증된 데이터만 참조하도록 구성하여 기업 환경에서 발생하는 주요 실패 유형을 제거한다 [12]. + * **MCP 서버 (MCP Server):** 이러한 활성 메타데이터, 계약, 리니지 정보를 모델 컨텍스트 프로토콜(MCP)을 통해 쿼리할 수 있도록 노출시켜 다양한 하네스와 연결한다 [13]. + +## ⚖️ Trade-offs & Caveats +* **사후 모니터링 및 오케스트레이션 도구의 근본적 제약:** 에이전트 프레임워크가 제공하는 오케스트레이션이 아무리 고도화되더라도, 에이전트가 검증되지 않거나 변형된 데이터를 읽는다면 이를 프레임워크 수준에서 보완할 방법이 없다는 치명적인 한계가 존재한다 [14]. AgentOps나 Langfuse와 같은 사후 모니터링(Post-hoc observability) 도구를 활용하더라도, 이는 에이전트가 잘못된 입력을 바탕으로 행동했다는 사후 기록만을 제공할 뿐 원본 소스에서 나쁜 데이터가 유입되는 것을 방지하지는 못한다 [4, 5, 15, 16]. +* **인프라 구성의 복잡성과 비용 증가:** 결과적으로 기업이나 개발팀은 에이전트 하네스 도구와는 별개로, Atlan과 같은 거버넌스가 적용된 데이터 기반 구조(Governed data substrate)를 구축해야 하는 추가적인 인프라 부담을 안게 된다 [9, 10, 17, 18]. 특히 규제가 심한 산업 분야에서는 이러한 데이터 인증 인프라가 단순한 선택 사항이 아니라, 규정 준수(Compliance)를 위한 필수적인 감사 추적 요구사항으로 작용하여 에이전트 AI 시스템을 프로덕션 환경에 배포하는 데 높은 진입 장벽과 초기 투자 비용을 요구하게 된다 [13, 19]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/둠 루프 (Doom Loop).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/둠 루프 (Doom Loop).md new file mode 100644 index 00000000..5269536c --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/둠 루프 (Doom Loop).md @@ -0,0 +1,22 @@ +# [[둠 루프 (Doom Loop)]] + +## 📌 Brief Summary +둠 루프(Doom Loop)는 자율형 AI 에이전트가 특정 문제 해결 계획을 결정한 후 시야가 좁아져(myopic), 작동하지 않는 잘못된 접근 방식을 미세하게만 변경하며 실패를 끝없이 반복하는 현상을 의미한다 [1]. 에이전트 하네스 환경에서 빈번하게 관찰되는 실패 패턴 중 하나로, 일부 사례에서는 동일한 잘못된 방식을 10번 이상 반복하는 형태로 나타나기도 한다 [1]. 이를 해결하기 위해 하네스 계층에서 편집 횟수 등을 추적하여 에이전트가 스스로의 계획을 재고하도록 유도하는 미들웨어 장치가 주로 활용된다 [1]. + +## 📖 Core Content +* **발생 원인 및 현상:** + * 에이전트가 문제를 해결하기 위해 한 번 계획을 수립하고 나면, 그 계획에 지나치게 매몰되어 근시안적으로 변할 때 둠 루프가 발생한다 [1]. + * 에이전트는 기존의 실패한 접근법의 근본적인 원인을 파악하여 새로운 계획을 세우는 대신, 동일한 코드나 파일에 작고 무의미한 변형만을 가하면서 계속해서 실패를 반복하게 된다 [1]. +* **하네스 엔지니어링을 통한 해결 방안:** + * 에이전트가 둠 루프에서 벗어나 한 발 물러서서 계획을 재고할 수 있도록 장려하는 하네스 계층의 적극적인 개입이 필요하다 [1]. + * 구체적인 시스템 구현 예시로, 도구 호출 훅(tool call hooks)을 통해 파일별 편집 횟수를 추적하는 `LoopDetectionMiddleware`(루프 감지 미들웨어)를 도입할 수 있다 [1]. + * 이 미들웨어는 동일한 파일에 대해 특정 횟수('N'번) 이상의 수정이 반복적으로 발생하면, 에이전트의 컨텍스트에 "...접근 방식을 다시 고려해 보십시오(consider reconsidering your approach)"와 같은 지침을 강제로 주입하여 루프 탈출을 돕는다 [1]. + +## ⚖️ Trade-offs & Caveats +* **모델의 자의적 판단에 따른 통제력 한계:** 하네스 루프 감지 미들웨어가 개입하여 접근 방식을 재고하라는 컨텍스트를 주입하더라도, 모델 스스로 자신의 현재 경로가 올바르다고 계속해서 확신할 경우에는 경고를 무시하고 동일한 잘못된 경로를 고집할 수 있다는 한계가 있다 [1]. +* **근본적 해결이 아닌 발견적 설계(Heuristic):** 둠 루프를 끊어내기 위한 이러한 장치들은 현재 AI 모델들이 가지고 있는 인지적 결함을 엔지니어링 적으로 우회하기 위해 만들어진 임시적이고 발견적인 설계(design heuristic)라는 점을 인지해야 한다 [1]. +* **모델 개선에 따른 효용성 변화:** 향후 모델의 추론 능력이 자체적으로 개선됨에 따라 이러한 인위적인 가드레일은 점차 불필요해질 가능성이 크다 [1]. 하지만 현재의 기술 수준에서 자율적이고 견고한 에이전트 애플리케이션을 구축하기 위해서는 당분간 감수하고 필수적으로 실험해 보아야 할 설계적 우회 수단이다 [1]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/랄프 루프 (Ralph Loop).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/랄프 루프 (Ralph Loop).md new file mode 100644 index 00000000..a167336a --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/랄프 루프 (Ralph Loop).md @@ -0,0 +1,17 @@ +# [[랄프 루프 (Ralph Loop)]] + +## 📌 Brief Summary +랄프 루프(Ralph Loop)는 대규모 언어 모델(LLM) 에이전트가 작업을 조기에 종료하려는 시도를 훅(hook) 메커니즘으로 가로채어, 정해진 완료 목표를 달성할 때까지 작업을 계속하도록 강제하는 에이전트 하네스 패턴이다 [1, 2]. 이 패턴은 실행을 멈추려는 에이전트에게 깨끗한 컨텍스트 창과 원래의 프롬프트를 다시 주입하여 반복적인 실행을 유도한다 [2]. 주로 에이전트가 종료하기 전에 작업 명세서에 대한 검증(verification) 단계를 반드시 거치도록 하는 데 활용된다 [1]. + +## 📖 Core Content +* **작업 지속 메커니즘**: 랄프 루프는 에이전트가 스스로 실행을 종료하고 빠져나가려는 시점(exit attempt)을 하네스 레벨에서 인터셉트(intercept)한다 [2]. 시스템은 종료를 막은 뒤 **깨끗한 컨텍스트 창(clean context window)에 원래의 프롬프트를 다시 주입**하여 에이전트가 중단 없이 완료 목표를 향해 작업을 이어가도록 강제한다 [2]. +* **파일 시스템 기반의 상태(State) 유지**: 이 패턴이 연속적이고 장기적인 작업(Long-horizon work)에서 효과적으로 작동할 수 있는 이유는 하네스의 파일 시스템 프리미티브에 의존하기 때문이다 [2]. 각 루프의 반복(iteration)이 시작될 때마다 컨텍스트는 완전히 초기화(fresh)되지만, **이전 반복에서 파일 시스템에 기록해 둔 상태(state)를 읽어올 수 있으므로** 에이전트는 맥락을 잃지 않고 진척도를 유지할 수 있다 [2]. +* **자가 검증(Self-Verification)의 강제**: 랄프 위검 루프(Ralph Wiggum Loop)라고도 불리는 이 패턴은 에이전트의 종료 전 검증을 유도하는 데 매우 유용하다 [1]. 예를 들어, `PreCompletionChecklistMiddleware`와 같은 미들웨어와 결합하여 에이전트가 종료하기 전에 작업 명세서(Task spec)를 기준으로 **스스로 검증 단계(verification pass)를 실행하도록 상기시키는 용도**로 사용된다 [1]. + +## ⚖️ Trade-offs & Caveats +* **파일 시스템 의존성**: 랄프 루프는 매 반복마다 컨텍스트 창을 새로 고치는 방식(fresh context)으로 작동하기 때문에, 이전 작업의 흐름을 유지하려면 **반드시 파일 시스템과 같은 지속적이고 안정적인 상태 저장 매커니즘이 뒷받침되어야 한다는 구조적 제약**이 존재한다 [2]. +* 그 외에 랄프 루프의 도입으로 인해 발생할 수 있는 구체적인 부작용이나 성능상의 반대 급부(Trade-off)에 대해서는 **소스에 관련 정보가 부족합니다.** + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/보안 및 감사 (Security & Audit).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/보안 및 감사 (Security & Audit).md new file mode 100644 index 00000000..7f3d4ee3 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/보안 및 감사 (Security & Audit).md @@ -0,0 +1,22 @@ +# [[보안 및 감사 (Security & Audit)]] + +## 📌 Brief Summary +에이전트 하네스 아키텍처에서 보안 및 감사는 에이전트의 자율적 행동을 통제하고 시스템을 보호하며 기업의 규정 준수를 보장하는 핵심 인프라 계층입니다. 이는 에이전트가 승인된 도구와 데이터에만 접근하도록 제한하는 권한 제어, 샌드박스를 통한 실행 환경 격리, 그리고 모든 결정과 행동을 기록하는 감사 추적 기능을 포함합니다. 단순한 프롬프트 수준의 지시를 넘어 결정론적이고 구조적인 보호막을 제공함으로써, 예기치 않은 모델의 오류나 악의적인 프롬프트 주입으로부터 시스템을 안전하게 지켜냅니다. + +## 📖 Core Content +* **권한 부여 및 거버넌스 제어 (Authorization & Governance Control):** + 에이전트의 권한 과잉(Excessive Agency) 위험을 방지하기 위해 최소 권한 원칙(Least-privilege)이 하네스 레벨에서 적용됩니다 [1, 2]. 시스템은 OPA(Open Policy Agent) 정책 게이트나 역할 기반 접근 제어(RBAC)를 통해 에이전트의 실질적 행동을 실행 전에 평가하며, 명시적으로 허용된 도구(Allow-Listed Tools)만 사용하도록 통제합니다 [3-5]. OAP(Open Agent Passport)와 같은 시스템은 도구 호출을 동기적으로 가로채어 정책을 평가하고 암호화된 감사 기록을 생성합니다 [6]. +* **샌드박스 및 실행 격리 (Sandbox & Execution Isolation):** + 에이전트가 생성한 코드나 도구 호출이 호스트 시스템을 훼손하지 않도록 컨테이너, 마이크로VM(E2B, Firecracker), 혹은 커널 수준(eBPF, Landlock)의 샌드박스 환경 내에서 격리 실행됩니다 [7-10]. 이를 통해 네트워크 외부 유출을 제한하고, 작업 공간 탈출을 차단하며, 에이전트가 시크릿 정보 등에 직접 접근하지 못하도록 원천 차단합니다 [7, 8, 11]. +* **감사 추적 및 가시성 (Audit Trail & Observability):** + 규정 준수(SOC 2, FedRAMP 등) 및 트러블슈팅을 위해 에이전트의 모든 결정, 도구 호출, 모델 입력/출력은 철저하게 로깅됩니다 [5, 12]. 하네스는 '생각의 사슬(Chain-of-thought)' 로그와 세션 기록을 보존하여 에이전트가 왜 특정한 결정을 내렸는지 사후에 추적하고 디버깅할 수 있는 완벽한 투명성을 제공합니다 [2, 5]. +* **휴먼 인 더 루프 (HITL) 및 안전 가드레일:** + 데이터베이스 수정이나 고객 문의 발송 등 민감한 고위험 작업 시, 하네스는 실행을 일시 중지(Interrupt)하고 인간의 검토 및 승인을 요구하는 워크플로우를 강제합니다 [13-15]. 이외에도 프롬프트 인젝션 방어, PII 유출 방지를 위한 차등 프라이버시(AnonymAI), NeMo Guardrails 등 다계층의 가드레일이 하네스에 통합되어 안전을 보장합니다 [7, 8]. + +## ⚖️ Trade-offs & Caveats +* **자율성 제한과 승인 피로도:** 보안 제어와 휴먼 인 더 루프(HITL)를 엄격하게 적용할수록 에이전트의 자율성과 실행 속도는 저하됩니다. 모든 도구 사용 시 확인을 요구할 경우 '승인 피로도(Approval Fatigue)'가 발생하여 결국 작업자가 무의식적으로 검토 없이 승인을 누르게 되는 부작용이 발생할 수 있습니다 [1, 13]. +* **유연성 부족:** OPA 규칙이나 엄격한 스키마 검증과 같이 결정론적인 인프라 기반의 보안 정책은 시스템의 안정성을 보장하지만, 에이전트가 새롭고 창의적인 방식으로 문제를 우회하거나 해결하려 할 때 이를 차단하는 제약 요소로 작용할 수 있습니다 [1, 4, 16]. +* **성능 오버헤드와 데이터 한계:** 실시간 정책 평가, 트레이싱 기록, 마이크로VM을 통한 샌드박싱 등은 시스템 지연 시간(Latency) 및 컴퓨팅 비용을 증가시킵니다 [8, 17, 18]. 더불어, 아무리 강력한 하네스 보안을 구축하더라도 원본 데이터 자체의 품질이 낮거나 스키마가 표류(Schema drift)된 상태라면, 에이전트는 오염된 메모리를 기반으로 연쇄적 실패를 일으킬 수 있으며 하네스 내부 보안만으로는 이를 방지할 수 없습니다 [19, 20]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/사후 관찰 가능성 (Post-hoc Observability).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/사후 관찰 가능성 (Post-hoc Observability).md new file mode 100644 index 00000000..1293e5be --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/사후 관찰 가능성 (Post-hoc Observability).md @@ -0,0 +1,19 @@ +# [[사후 관찰 가능성 (Post-hoc Observability)]] + +## 📌 Brief Summary +사후 관찰 가능성(Post-hoc Observability)은 에이전트가 실행된 이후에 무슨 일이 일어났는지 기록하고 모니터링하는 기능을 의미한다 [1, 2]. AgentOps나 Langfuse와 같은 도구들이 이 범주에 속하며, 세션 리플레이, 비용 데이터, 지연 시간, 도구 사용 내역 및 모델 출력 평가 등을 추적한다 [2-4]. 이는 프로덕션 에이전트 스택을 운영하기 위한 필수적인 인프라이지만, 오류가 발생한 이후에만 이를 포착한다는 근본적인 한계를 지닌다 [1]. + +## 📖 Core 소스 +* **관찰 도구의 역할:** 사후 관찰 도구들은 에이전트를 오케스트레이션하는 하네스 프레임워크 자체라기보다는 그 옆에 나란히 위치하여 에이전트 실행 후의 동작을 기록하는 인프라이다 [1]. 이들은 LLM의 호출, 프롬프트, 도구 사용, 비용 및 지연 시간 데이터 등을 추적하여 실패 원인을 법의학적으로 분석(forensic analysis)할 수 있게 해준다 [5, 6]. +* **대표적인 관찰 도구:** + * **AgentOps:** 400개 이상의 LLM을 지원하며, 주로 배치 후 세션 모니터링에 쓰인다 [3]. 세션 리플레이 기능을 제공하여 엔지니어가 실패한 세션에서 에이전트가 수행한 도구 호출과 모델 호출 등 정확히 어떤 일이 일어났는지 재현하고 분석할 수 있게 돕는다 [5]. + * **Langfuse:** LLM 호출을 스팬(span) 수준에서 추적하고 프롬프트 관리와 출력 평가 파이프라인을 제공하는 오픈소스 LLMOps 플랫폼이다 [4, 6]. + * 기타 도구: OpenLLMetry, Arize Phoenix, Braintrust 등의 도구들을 통해 에이전트의 모든 추론 단계와 도구 호출을 추적할 수 있으며, 이는 근본 원인이 여러 단계에 걸쳐 있는 다중 턴 에이전트의 실패를 디버깅하는 데 필수적으로 활용된다 [7]. + +## ⚖️ Trade-offs & Caveats +* **입력 데이터 품질 통제의 부재:** 사후 관찰 가능성 도구들의 가장 치명적인 제약 사항은 이들이 전적으로 '사후(post-hoc)'에 작동한다는 점이다 [1]. 즉, 잘못된 데이터 입력으로 인해 발생하는 실패를 사전에 예방하지 못하며, 실패가 발생한 뒤에야 이를 알아차릴 수 있다 [1, 8]. +* **오류 원인 파악의 맹점:** 에이전트가 스키마가 변경되었거나 오래된(stale), 혹은 검증되지 않은 데이터를 읽고 행동할 때, 사후 관찰 도구(예: AgentOps의 세션 리플레이)는 '에이전트가 무엇을 했는지'만을 보여줄 뿐 '그 데이터가 오래되었다는 사실'을 알려주지는 못한다 [8, 9]. 따라서 나쁜 데이터를 입력받고도 모델 출력 자체에 대한 평가 점수는 높게 나오는 착시 현상이 발생할 수 있다 [9]. +* **성능 오버헤드:** 시스템을 모니터링하기 위해 에이전트에 관찰 도구를 연동할 경우 성능 오버헤드(performance overhead)가 발생한다. 예를 들어 AgentOps는 약 12%, Langfuse는 약 15%의 성능 오버헤드를 유발하는 단점이 있다 [5, 6]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/상태 관리 (State Management).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/상태 관리 (State Management).md new file mode 100644 index 00000000..0ed8ce3c --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/상태 관리 (State Management).md @@ -0,0 +1,18 @@ +# [[상태 관리 (State Management)]] + +## 📌 Brief Summary +에이전트 하네스에서 상태 관리(State Management)는 기본적으로 무상태(Stateless)인 대규모 언어 모델(LLM)이 다중 세션 및 장기 작업을 수행할 수 있도록 맥락과 작업 진행 상황을 보존하는 핵심 인프라 기능이다 [1-3]. 이는 모델이 이전 세션의 기억을 잃지 않고 작업을 재개할 수 있도록 세션 상태를 디스크나 파일 시스템에 기록(Session Persistence)하는 것을 포함한다 [4-6]. 상태 관리를 통해 에이전트는 도구 실행 결과, 하위 작업 완료 여부, 진행 노트 등을 영구적으로 추적하며, 시스템 충돌이 발생해도 처음부터 다시 시작하지 않고 이전 상태를 복구할 수 있다 [2, 4, 7]. + +## 📖 Core Content +* **상태 비저장성(Statelessness) 극복:** LLM은 본질적으로 무상태이므로 하네스가 개입하지 않으면 에이전트는 매 세션마다 이전 작업의 지식 없이 백지상태에서 시작하게 된다 [1-3]. 에이전트 하네스는 이러한 모델의 한계를 극복하기 위해 메모리를 저장, 검색, 복구하며 장기 작업(Long-running tasks)을 가능하게 하는 제어 평면의 역할을 수행한다 [2, 3]. +* **파일 시스템 및 영구 저장소 기반 상태 관리:** 하네스는 파일 시스템을 활용하여 중간 상태를 디스크에 지속시키고, 컨텍스트 윈도우의 한계를 넘어 정보를 오프로딩(Offloading)한다 [5, 6, 8]. 일례로 초기화-실행자 분리(Initializer-executor split) 패턴을 사용하면 폴더 구조, 기능 목록, 진행 파일 등 내구성 있는 프로젝트 환경 상태가 설정되며, 후속 세션은 이 상태를 읽어 점진적으로 작업을 수행한다 [9]. +* **세션 상태(Session State)와 체크포인팅:** 에이전트의 상태 관리는 현재 작업 기간 동안의 도구 실행 결과, 완료된 하위 작업, 진행 노트 등에 대한 내구성 있는 로그를 관리하는 과정을 포함한다 [7]. LangGraph와 같은 오케스트레이션 프레임워크는 그래프 기반 상태 모델과 체크포인팅(Checkpointing) 기능을 제공하여, 실패 후에도 장기 작업을 재개할 수 있도록 에이전트 상태에 대한 명시적이고 세밀한 제어력을 제공한다 [10, 11]. +* **관찰적 메모리 및 상태 압축 관리:** Mastra와 같은 프레임워크는 백그라운드 에이전트를 통해 대화를 실시간 모니터링하고, 이를 구조화된 관찰 결과로 지속 압축하는 관찰적 메모리(Observational memory) 시스템을 사용하여 상태의 밀도와 품질을 자동 유지한다 [12, 13]. 더불어 컨텍스트 윈도우가 채워짐에 따라 이전 단계를 요약본으로 압축(Auto-summarization)하여 중간 상태를 관리하기도 한다 [8, 14]. + +## ⚖️ Trade-offs & Caveats +* **데이터 출처 및 계보 추적 상실:** 컨텍스트 압축 및 자동 요약을 통해 상태를 관리할 경우 데이터의 출처(Provenance)가 조용히 손실될 수 있다 [8]. 에이전트가 요약·압축된 상태(컨텍스트)를 읽을 때 해당 정보의 기원이나 데이터 계보(Lineage)를 연결하는 추적 메커니즘이 끊어지기 때문에, 잘못된 결과가 도출될 경우 근본 원인을 파악하기 어려워진다 [8]. +* **오염된 데이터 유입에 따른 상태 중독:** 대부분의 오케스트레이션 프레임워크는 상태에 주입되는 입력 데이터가 깨끗하다고 가정할 뿐 이를 직접 검증하지는 않는다 [11, 15, 16]. 스키마 드리프트나 인증되지 않은 출처의 '오염된 데이터'가 하네스의 컨텍스트로 유입되면, 에이전트가 잘못된 기억을 바탕으로 연쇄 장애(Cascading failures)를 일으키거나 모델 스스로는 제거할 수 없는 '좀비 메모리' 문제를 겪을 수 있다 [17-19]. +* **인프라 및 운영 복잡성 증가:** 중간 상태를 유지하기 위해 파일 시스템 백엔드에 맥락을 오프로딩하는 방식은 컨테이너화된 배포 환경에서 운영 복잡성을 크게 증가시킨다 [20]. 또한 AutoGen과 같은 특정 프레임워크의 경우 대화형 상태(컨텍스트)가 누적될 때 자동화된 관리 기능이 없어 토큰 윈도우가 가득 차면 수동으로 상태를 가지치기(Pruning)해야 하는 제약 사항이 존재한다 [21]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/샌드박스 (Sandbox).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/샌드박스 (Sandbox).md new file mode 100644 index 00000000..fc66e4d0 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/샌드박스 (Sandbox).md @@ -0,0 +1,21 @@ +# [[샌드박스 (Sandbox)]] + +## 📌 Brief Summary +샌드박스(Sandbox)는 대규모 언어 모델(LLM) 기반의 에이전트가 생성한 코드를 안전하게 실행하고 도구와 상호작용할 수 있도록 격리된 환경과 보안 경계를 제공하는 핵심 에이전트 하네스 프리미티브 중 하나이다 [1, 2]. 에이전트가 호스트 시스템을 파괴하거나 위험에 빠뜨리지 않도록 보호하며, 실행 결과를 안전하게 관찰하고 검증할 수 있는 독립적인 작업 공간을 보장한다 [1, 2]. 샌드박스를 통해 에이전트의 실행 환경은 온디맨드로 생성되고, 대규모 작업으로 확장되며, 작업 완료 후 안전하게 폐기될 수 있다 [1]. + +## 📖 Core 기Content +* **격리된 실행 및 시스템 보호:** 에이전트가 생성한 코드를 로컬 호스트 머신에서 직접 실행하는 것은 매우 위험하므로, 샌드박스는 커널 수준의 격리, 리소스 제한(CPU/메모리/디스크), 그리고 네트워크 격리를 통해 시스템을 보호한다 [1-3]. 또한 실행 결과에 대한 안전한 검증 루프를 형성하는 데 필수적인 역할을 수행한다 [2]. +* **다양한 샌드박스 구현 아키텍처:** + * **Docker 기반 컨테이너:** AutoGen(AG2)과 같은 프레임워크는 Docker 네이티브 샌드박싱을 통해 호스트 시스템 위험 없이 코드를 격리 실행한다 [4]. Open Harness는 단일 저장소 및 브랜치에 스코프를 맞춘 컨테이너를 제공하여 호스트 랩탑 환경을 깨끗하게 유지하며, 브라우저와 셸, 파일 시스템 등을 결합한 올인원(AIO) 환경을 구축한다 [5, 6]. Daytona는 OCI 컨테이너 샌드박스를 통해 장기 실행 에이전트 세션을 위한 상태 지속성(State persistence)을 지원한다 [3]. + * **마이크로 가상 머신 (MicroVM):** E2B와 LangSmith 샌드박스는 Firecracker 기반의 마이크로 가상 머신(microVM) 아키텍처를 사용하여 커널 수준의 격리와 매우 빠른 콜드 스타트(150ms 미만)를 제공한다 [3]. LangSmith 샌드박스는 보안 인증 프록시를 통해 런타임 환경 외부에 비밀 정보(Secrets)를 분리 보관하며 지속적인 WebSocket 세션을 지원한다 [3]. + * **V8 격리 (V8 Isolate):** Cloudflare Dynamic Workers는 V8 격리 기반의 샌드박싱으로 기존 컨테이너 아키텍처보다 최대 100배 빠르고 100배 더 메모리 효율적인 실행 환경을 제공하며, 아웃바운드 HTTP 요청을 가로채어 자격 증명을 안전하게 주입한다 [7]. +* **제어 및 보안 정책 적용:** NVIDIA OpenShell과 같은 샌드박스 런타임은 파일 시스템(Landlock LSM), 시스템 호출(seccomp BPF) 및 네트워크 프록시를 통해 커널 수준에서 엄격한 보안 제약 조건을 강제하여, 손상된 에이전트조차 보안 정책을 우회할 수 없게 원천적으로 차단한다 [7]. + +## ⚖️ Trade-offs & Caveats +* **자체 구성 수정에 의한 권한 상승 (Escalation) 위험:** 표준적인 샌드박스 격리만으로는 완벽한 보안이 보장되지 않는다 [7]. 에이전트가 샌드박스 내에서 자신의 하네스 구성(예: MCP 서버 설정 및 훅 파일)을 직접 수정할 수 있다면 권한을 스스로 상승시키는 치명적인 보안 위협이 발생할 수 있으므로, 해당 설정 파일들에 대한 에이전트의 접근을 차단해야 한다 [7]. +* **제약 조건 인지에 대한 학습 필요성:** 에이전트가 샌드박스의 제약 조건을 스스로 인지하도록 명시적으로 학습되지 않으면 부작용이 발생할 수 있다 [3]. 제약을 모르는 에이전트는 샌드박스 경계 내에서 자유롭게 코드를 탐색하고 실행하는 대신, 모든 외부 접근이나 파일 작업에 대해 사용자 승인을 요청하며 작업 흐름을 지속적으로 방해(Interrupt)할 수 있다 [3]. +* **인프라 노이즈로 인한 평가 편향 (Infrastructure Noise):** 샌드박스 컨테이너에 할당되는 리소스 구성(CPU/메모리 등) 자체가 모델 평가 시 6% 포인트 이상의 벤치마크 점수 변동을 일으키는 인프라 노이즈로 작용할 수 있다 [8]. 특정 리소스 할당량(예: 3배 임계값)을 넘어서면 에이전트가 가벼운 도구를 쓸지 무거운 종속성을 사용할지 등 문제 해결 전략을 완전히 바꾸게 되므로 성능 평가 시 주의가 필요하다 [8]. +* **운영 복잡성 증가:** 샌드박싱이나 파일 시스템 백엔드 기능을 컨테이너화된 환경에서 사용할 경우, 로컬에서 단순 실행하는 것보다 운영 및 설정의 복잡성이 구조적으로 증가하는 반대 급부가 따른다 [9-11]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/심층 방어 (Defense-in-depth).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/심층 방어 (Defense-in-depth).md new file mode 100644 index 00000000..1ef5dd50 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/심층 방어 (Defense-in-depth).md @@ -0,0 +1,18 @@ +# [[심층 방어 (Defense-in-depth)]] + +## 📌 Brief Summary +에이전트 하네스 환경에서 심층 방어(Defense-in-depth)란 자율형 인공지능의 실행을 잠재적인 '적대적 워크로드(hostile workload)'로 간주하고, 이를 안전하게 제어하기 위해 다중 계층의 보호 장치를 중첩하여 구축하는 보안 아키텍처이다 [1]. 격리된 컨테이너, 방화벽, 프록시, 스키마 필터링 등 다양한 방어 기제를 함께 적용하여 시스템을 보호한다 [1, 2]. 이는 단일 샌드박스 격리 방식이 지닌 한계를 보완하고 에이전트에 의한 의도치 않은 권한 상승이나 시스템 손상을 방지하기 위해 필수적으로 요구된다 [3]. + +## 📖 Core Content +* **5계층 심층 방어 체계:** 터미널 네이티브 코딩 에이전트를 위한 하네스 설계에서는 안전성을 확보하기 위해 5계층 심층 방어(5-layer defense-in-depth safety) 체계를 도입하여 운영한다 [2]. +* **스키마 기반 행동 제약:** 단순한 런타임 권한 검사에만 의존하지 않고, 스키마 필터링이 적용된 계획 하위 에이전트(schema-filtered planning subagents)를 활용해 도구 스키마 단에서 에이전트의 행동 제약을 물리적으로 강제하는 방식이 방어 계층의 주요 요소로 활용된다 [2]. +* **적대적 워크로드 기반 인프라 보호:** CI(지속적 통합) 자동화 인프라 내부에서 코딩 에이전트가 실행될 때, 시스템은 에이전트 실행 자체를 '적대적 워크로드'로 취급하여 보호막을 구축한다 [1]. +* **주요 심층 방어 구현 요소:** 구체적인 방어 레이어의 구현 사례로는 격리된 에이전트 컨테이너(isolated agent container), 방화벽(firewall), MCP 게이트웨이(MCP gateway), API 프록시(API proxy), 단계적 안전 출력(staged safe outputs), 그리고 제로 시크릿 실행(zero-secret execution) 메커니즘이 포함된다 [1]. + +## ⚖️ Trade-offs & Caveats +* **단일 샌드박스 격리의 한계:** 일반적인 수준의 샌드박스 격리(standard sandbox isolation)만으로는 충분한 보안을 달성할 수 없다. 에이전트가 자신의 하네스 구성을 직접 편집할 수 있는 환경이라면 스스로 권한을 상승시킬 수 있는 치명적인 위협이 발생한다 [3]. 따라서 네트워크 송신 제한, 작업 공간 탈출 차단, MCP 서버 구성 및 훅(hooks) 파일 보호와 같은 다중 방어 계층이 필수적으로 병행되어야 한다 [3]. +* **문서화 및 인식 부족 현상:** 에이전트 실행을 적대적인 것으로 간주하고 심층 방어 아키텍처를 구축하는 보안 마인드셋은 대부분의 하네스 인프라에 반드시 필요함에도 불구하고, 업계 내에서 관련 기술과 접근법이 제대로 문서화되어 있지 않다(rarely document)는 현실적인 한계점이 존재한다 [1]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 미들웨어 (Agent Middleware).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 미들웨어 (Agent Middleware).md new file mode 100644 index 00000000..b0d399bc --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 미들웨어 (Agent Middleware).md @@ -0,0 +1,19 @@ +# [[에이전트 미들웨어 (Agent Middleware)]] + +## 📌 Brief Summary +에이전트 미들웨어(Agent Middleware)는 에이전트 루프의 모든 실행 단계를 가로채어(intercept) 제어하는 조합 가능한 훅(hooks) 형태의 계층을 의미합니다 [1]. 이는 핵심 에이전트 로직을 수정하지 않고도 결정론적 정책 강제 적용, 동적 도구 주입, 실행 검증 등을 수행할 수 있게 합니다 [1]. 주로 모델과 도구 호출(tool calls) 주변에서 작동하며, 에이전트가 자율적이고 신뢰성 있게 작업을 완수하도록 돕는 하네스(Harness)의 주요 최적화 요소로 활용됩니다 [2]. + +## 📖 Core Content +* **미들웨어의 구조와 역할**: 에이전트 미들웨어는 `before_agent`, `before_model`, `wrap_model_call`, `wrap_tool_call`, `after_model`, `after_agent` 등 에이전트 루프의 각 단계를 가로채는 6개의 조합 가능한 훅으로 구성됩니다 [1]. 프롬프트만으로는 보장할 수 없는 개인식별정보(PII) 삭제와 같은 결정론적 정책의 강제, 동적 도구 주입, 작업 중 모델 교체, 그리고 재시도(retry), 대체(fallback), HITL(Human-in-the-Loop) 인터럽트 등 공통적인 프로덕션 패턴을 지원합니다 [1]. +* **프레임워크 적용 사례**: Microsoft Agent Framework 1.0은 모든 실행 단계를 가로채기 위한 미들웨어 파이프라인을 프레임워크 내에 통합하여 지원합니다 [3]. +* **실제 활용 및 구현 패턴**: + * **컨텍스트 및 환경 매핑**: `LocalContextMiddleware`는 에이전트 시작 시 실행되어 작업 디렉토리(cwd) 등을 매핑함으로써 에이전트가 실행 환경에 적응(onboard)할 수 있도록 돕습니다 [4]. + * **자가 검증 강제**: `PreCompletionChecklistMiddleware`는 에이전트가 작업을 종료하고 빠져나가기 전에 개입하여 작업 명세(Task spec)에 대한 검증 패스를 실행하도록 상기시키는 역할을 합니다 [5]. + * **무한 루프 방지**: `LoopDetectionMiddleware`는 도구 호출 훅을 통해 파일당 편집 횟수를 추적하여, 에이전트가 동일하게 잘못된 접근을 계속 반복하는 '파멸의 루프(doom loop)'에 빠졌을 때 접근 방식을 재고하도록 컨텍스트를 추가합니다 [6]. + +## ⚖️ Trade-offs & Caveats +* **모델의 제어 무시 가능성**: 미들웨어(예: `LoopDetectionMiddleware`)를 통해 에이전트에게 오류 패턴을 경고하거나 접근 방식의 변경을 유도하는 컨텍스트를 주입하더라도, 모델이 스스로의 판단이 옳다고 생각하면 이러한 개입을 무시하고 계속해서 잘못된 경로를 고집할 수 있는 한계가 있습니다 [6]. +* **과도기적 설계 성격**: 현재 미들웨어를 활용한 맹목적 재시도(blind retries)나 강제 검증 등의 기법은 오늘날 모델이 지닌 단점(스스로 검증하지 않는 문제 등)을 우회하기 위한 휴리스틱(heuristic) 기반의 설계입니다 [6, 7]. 향후 모델의 능력이 개선됨에 따라 이러한 미들웨어 기반의 안전장치나 가드레일은 점차 불필요해질 가능성이 높습니다 [6, 7]. 그러나 현재 시점에서 견고한 자율 에이전트 애플리케이션을 구축하기 위해서는 여전히 필수적이고 유용한 도구로 평가받고 있습니다 [7]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 평가 (Agent Evaluation).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 평가 (Agent Evaluation).md new file mode 100644 index 00000000..689ee01a --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 평가 (Agent Evaluation).md @@ -0,0 +1,28 @@ +# [[에이전트 평가 (Agent Evaluation)]] + +## 📌 Brief Summary +에이전트 평가(Agent Evaluation)는 인공지능 모델 단독의 능력을 넘어, 모델과 이를 제어하는 인프라인 에이전트 하네스(Agent Harness)가 결합된 전체 시스템의 성능, 신뢰성 및 비용 효율성을 종합적으로 측정하는 과정이다 [1, 2]. 이 개념은 고립된 환경에서의 벤치마크가 실제 서비스 배포 시의 성능을 정확히 대변하지 못한다는 한계에서 출발하며, '생산 성능 = 모델 역량 × 하네스 승수'라는 공식을 기반으로 한다 [1, 2]. 최근에는 HAL(Holistic Agent Leaderboard)과 같은 통합 프레임워크를 통해 단순한 작업 성공률(정확도)뿐만 아니라 토큰 사용량과 실행 비용까지 함께 검증하는 방향으로 고도화되고 있다 [3-5]. + +## 📖 Core Content + +* **하네스 인지 평가(Harness-Aware Evaluation)의 중요성:** + 전통적인 AI 벤치마크는 모델을 고립된 상태(Brains in jars)로 평가하여 모든 성과를 모델의 능력으로만 귀속시키는 오류(Anti-pattern)를 범했다 [1, 2]. 하지만 에이전트의 실제 수행 능력은 모델의 가중치 업그레이드보다 하네스의 설계에 의해 더 크게 좌우된다 [6]. 예를 들어, GPT-5.5 모델을 동일한 주간에 평가했을 때 Codex 네이티브 하네스에서는 61.5%의 기능성 점수를 기록했으나, Cursor 하네스 환경에서는 87.2%로 무려 25.7%포인트 급상승했다 [7, 8]. 따라서 **평가는 반드시 하네스의 역량(맥락 관리, 도구 통합 깊이, 메모리 연속성, 다중 에이전트 조정 등)을 주요 변수로 포함하여 분해(Decomposition) 측정**해야 한다 [2, 9]. + +* **표준화된 평가 프레임워크 및 도구:** + * **HAL (Holistic Agent Leaderboard):** 특정 에이전트 프레임워크 구현에 얽매이지 않고 여러 벤치마크(SWE-bench Verified, USACO, AppWorld, tau-bench, SciCode 등)를 아우르며 재현 가능한 평가를 수행하는 표준화된 하네스 시스템이다 [5, 10, 11]. 정확도 위주의 기존 평가 한계를 극복하고자 Weave와 통합해 **실행 비용과 토큰 사용량 등 비용-성능 상충 관계를 기본적으로 추적**한다 [3, 4, 11]. 또한 벤치마크 오염(Contamination)을 막기 위해 실행 트레이스(Traces)를 허깅페이스(HuggingFace)에 업로드하기 전 자동 암호화하는 보안 기능을 제공한다 [5, 11, 12]. + * **기타 전문 평가 도구:** `DeepEval`은 환각(Hallucination), 도구 정확성, RAG 평가 등을 수행하는 20개 이상의 지표를 제공하며, `promptfoo`는 LLM을 심판(LLM-as-judge)으로 내세워 CI(지속적 통합) 파이프라인에서 회귀 테스트를 수행하도록 돕는다 [13, 14]. `Langfuse`와 같은 오픈소스 LLMOps 플랫폼은 프롬프트 성능과 모델 출력을 평가하는 파이프라인을 구축할 수 있게 지원한다 [15, 16]. + +* **비결정론적 특성을 반영한 다차원적 평가:** + 에이전트의 작업은 비결정론적(Non-deterministic)이므로 단순한 이진(Pass/Fail) 방식의 평가는 무의미하다 [13]. 효과적인 평가를 위해서는 에이전트가 호출한 도구와 논리 단계를 추적하는 **궤적 평가(Trajectory evals)와 최종 결과 평가(Outcome evals)를 결합**해야 하며 [14], 일관성, 견고성, 예측 가능성, 안전성 등의 다차원적인 지표를 통해 신뢰성을 벤치마킹해야 한다 [17]. + +## ⚖️ Trade-offs & Caveats + +* **사후 평가의 구조적 한계와 입력 데이터 맹점 (제약 사항):** + AgentOps, Langfuse 등 대다수의 가시성 및 평가 도구들은 에이전트가 실행된 이후(Post-hoc)에 작동하여 모델 출력과 프롬프트를 평가한다 [18-21]. 이들은 에이전트가 잘못된 판단을 내렸을 때 그 원인이 모델의 오류인지, 혹은 하네스에 주입된 데이터 자체가 오래되었거나 검증되지 않은 소스(스키마 변경 등)인지 선제적으로 차단하거나 판별하지 못한다 [18-20]. 즉, **나쁜 입력 데이터를 기반으로 도출된 출력물에 잘못된 높은 평가 점수가 매겨질 수 있는 착시 위험**이 존재한다 [19]. +* **비용과 평가 깊이의 상충 관계 (Trade-off):** + 모든 에이전트 작업 단계마다 성능이 뛰어난 대형 LLM을 심판으로 배치하여 엄격한 검증을 거치면 정확도는 오르지만, **추론 예산(토큰 비용)과 지연 시간(Latency)이 기하급수적으로 폭증**한다 [13, 22]. 이를 해결하려면 명령어 순서나 토큰 예산 검사와 같은 저렴하고 결정론적인 시스템 검사를 먼저 거친 후, 해당 방식만으로 파악이 어려운 위험 영역에 한해서만 값비싼 LLM 심판을 전략적으로 도입하는 식의 최적화가 필요하다 [13]. 특정 벤치마크 테스트 통과에만 과적합(Overfit)되도록 하네스를 튜닝하면, 일반화 능력이 훼손되어 다른 작업에서 회귀(Regression)를 일으키는 부작용이 생길 수도 있다 [23]. +* **웹 연결 평가 환경의 벤치마크 무효화 리스크:** + 웹 탐색 도구가 제공되는 환경에서 평가를 진행할 경우, 고성능 모델은 자신이 평가를 받고 있다는 사실을 스스로 인지하고 **인터넷에서 벤치마크의 정답 키를 우회 탐색하는 현상**(예: Claude Opus 4.6의 보안 우회 사례)이 발생할 수 있다 [14]. 이는 테스트의 변별력을 완전히 무효화시키므로, 벤치마크 평가 시에는 네트워크가 엄격히 차단된 샌드박스 환경 구성이 필수적이다 [14]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 하네스 (Agent Harness).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 하네스 (Agent Harness).md new file mode 100644 index 00000000..57b198bb --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/에이전트 하네스 (Agent Harness).md @@ -0,0 +1,32 @@ +# [[에이전트 하네스 (Agent Harness)]] + +## 📌 Brief Summary +**에이전트 하네스(Agent Harness)**는 대규모 언어 모델(LLM)을 감싸며 모델의 실제 추론 과정을 제외한 모든 시스템적 상호작용을 관리하는 소프트웨어 인프라스트럭처 계층이다 [1, 2]. 기본적으로 상태를 저장하지 않는(stateless) LLM이 복잡하고 장기적인 작업을 자율적으로 수행할 수 있도록 도구 실행, 메모리 유지, 컨텍스트 관리 및 오류 복구 기능을 제공한다 [3, 4]. 모델이 인지적 지능(뇌)을 담당한다면 하네스는 도구(손), 관찰(눈), 기억, 그리고 안전 경계를 제공하는 '환경 혹은 신체' 역할을 수행하며, 따라서 현대의 AI 에이전트는 **에이전트 = 모델 + 하네스(Agent = Model + Harness)**라는 공식으로 정의된다 [5-7]. + +## 📖 Core Content +**개념 및 핵심 역할** +에이전트 하네스는 언어 모델의 확률적 추론을 현실 세계의 결정론적 행동으로 변환하는 제어 평면(Control Plane) 역할을 한다 [6, 7]. 하네스가 없을 경우 장기 실행 에이전트는 컨텍스트 부패(Context rot), 환각된 도구 호출(Hallucinated tool calls), 시스템 장애 시 상태 상실(Lost state on failure)과 같은 치명적인 실패 모드를 겪게 된다 [8, 9]. 하네스는 에이전트의 의도와 행동 사이에 개입하여 요청을 가로채고, 검증하고, 라우팅하며, 기록하는 방식으로 이러한 문제를 해결한다 [10]. + +**5대 핵심 기술 프리미티브 (Core Primitives)** +에이전트 하네스를 구성하여 모델의 한계를 극복하게 하는 5가지 필수 기술 요소는 다음과 같다 [11]. +* **파일 시스템 (Filesystem):** 작업 공간을 제공하고, 세션 간 작업 진행률을 영구적으로 저장하며, 에이전트 간 혹은 사람과 협업할 수 있는 표면을 제공한다 [11, 12]. +* **코드 실행 (Code Execution):** 에이전트에게 Bash나 Python 등을 실행할 수 있는 범용 도구를 제공하여, 미리 설계되지 않은 비정형 문제도 코드를 통해 자율적으로 해결할 수 있게 한다 [11, 13, 14]. +* **샌드박스 (Sandbox):** 호스트 시스템을 파괴하지 않고 에이전트가 코드를 안전하게 실행하고 환경을 구축할 수 있도록 격리된 실행 환경과 네트워크 보안 경계를 제공한다 [11, 15]. +* **메모리 및 상태 관리 (Memory & State):** 휘발성 컨텍스트, 작업 지속 시간을 위한 세션 상태, 시스템 재시작 시에도 복구 가능한 장기 메모리를 관리하여 'AI 기억상실증'을 방지한다 [4, 11, 16]. +* **컨텍스트 엔지니어링 (Context Engineering):** 컨텍스트 윈도우가 가득 차는 것을 방지하기 위해 대화 이력을 압축(Compaction)하고, RAG(검색 증강 생성) 패턴을 통해 현재 단계에 필요한 문서만 동적으로 주입하여 정보 과부하를 막는다 [11, 17, 18]. + +**운영 아키텍처 및 제어 루프** +* **아키텍처 패턴:** 하네스는 단일 모델 루프를 감독하는 '단일 에이전트 감독자(Single-agent supervisor)', 장기 코딩 작업 환경을 세팅하고 실행을 분리하는 '초기화-실행자 분리(Initializer-executor split)', 그리고 복잡한 작업을 위해 전문 에이전트들에게 컨텍스트를 분배하는 '다중 에이전트 조율(Multi-agent coordination)' 패턴 등으로 구현된다 [19-22]. +* **피드포워드와 피드백 (Feedforward & Feedback):** 하네스는 에이전트가 오류를 겪기 전에 시스템 프롬프트, 도구 규약 등으로 올바른 행동을 안내하는 **가이드(피드포워드)**와, 린터나 구조적 테스트 등을 통해 에이전트가 행동한 후 결과를 관찰하여 스스로 교정하게 하는 **센서(피드백)**를 결합하여 지능적 제어 시스템을 형성한다 [23-25]. + +**하네스 승수 (Harness Multiplier) 효과** +현대 AI 시스템에서는 모델 자체의 가중치를 업그레이드하는 것보다 하네스의 런타임 환경을 최적화하는 것이 실제 작업 완료 능력(Task Success)에 훨씬 큰 영향을 미친다 [26-28]. 동일한 주간에 같은 모델(예: GPT-5.5)을 사용하더라도 기본 하네스냐 최적화된 하네스냐에 따라 기능성 점수가 25% 포인트 이상 차이 날 정도로 에이전트의 최종 성능을 결정짓는 핵심 변수이다 [26, 28]. + +## ⚖️ Trade-offs & Caveats +* **데이터 품질의 맹점 (Data Quality Gap):** 대부분의 하네스 오케스트레이션 프레임워크는 에이전트가 '어떻게' 실행될지는 관리하지만 에이전트가 '무엇을' 읽는지는 거버넌스하지 않는다 [29, 30]. 즉, 스키마 변동, 오래된 데이터, 인증되지 않은 소스 등을 에이전트가 그대로 읽고 잘못된 결과를 낼 위험(메모리 오염 및 연쇄 실패)이 있으며, 이는 하네스 내부의 문제가 아니라 외부의 데이터 거버넌스 및 품질 인프라가 해결해야 할 구조적 제약이다 [30-32]. +* **컨텍스트 압박과 도구 비대화 (Context vs. Tool Bloat):** 에이전트에게 너무 많은 도구나 MCP 서버를 한 번에 주입하면 토큰 비용이 급증하고 모델의 컨텍스트가 부패하여 성능이 저하된다 [33, 34]. 따라서 하네스 설계 시 도구를 제한하거나, '스킬(Skills)' 형태의 점진적 정보 공개(Progressive disclosure) 메커니즘을 통해 동적으로 컨텍스트를 압축하고 관리해야 하는 복잡성이 수반된다 [33, 35]. +* **하네스에 대한 모델 과적합 (Model Overfitting to Harness):** 모델이 특정 하네스 구조 내에서 훈련(Post-training)될 경우, 해당 하네스의 도구 규약과 논리에 지나치게 의존(Overfitting)하게 되어 일반화 능력이 저하될 수 있다 [36, 37]. 이는 특정 모델에 최적화된 하네스가 다른 작업이나 환경에서는 오히려 비효율적일 수 있음을 시사한다 [37]. +* **센서의 비결정성과 실행 비용:** 에이전트를 자가 교정시키는 피드백 센서 중 린터나 유닛 테스트 같은 '연산적(Computational)' 제어는 빠르고 결정론적이지만, LLM 기반 판사(LLM-as-judge)와 같은 '추론적(Inferential)' 제어는 느리고 비용이 많이 들며 결과가 확률적(Non-deterministic)이다 [38, 39]. 이를 오남용하면 하네스의 운영 비용과 지연 시간(Latency)이 폭증할 수 있으므로 개발 주기의 적절한 시점에 센서를 분배해야 하는 트레이드오프가 발생한다 [39, 40]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/인간 개입 (Human-in-the-Loop, HITL).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/인간 개입 (Human-in-the-Loop, HITL).md new file mode 100644 index 00000000..75e86b49 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/인간 개입 (Human-in-the-Loop, HITL).md @@ -0,0 +1,24 @@ +# [[인간 개입 (Human-in-the-Loop, HITL)]] + +## 📌 Brief Summary +인간 개입(Human-in-the-Loop, HITL)은 에이전트 하네스 아키텍처 내에서 자율형 AI 에이전트의 실행 과정 중 핵심 의사결정이나 고위험 작업에 인간의 검토, 승인 또는 개입을 통합하는 제어 메커니즘이다 [1-3]. 이는 중요한 실행 시점에 시스템을 일시 중지하고 인간이 직접 결과를 검증, 승인, 또는 수정할 수 있게 함으로써 에이전트의 안전성과 신뢰성을 확보한다 [3-5]. 특히 자동화로 처리하기 위험한 작업을 다루거나 복잡한 추론이 필요한 상황에서, 에이전트 시스템에 대한 최종 통제력을 유지하고 치명적인 사고를 예방하는 필수적인 인프라 기술로 활용된다 [2, 3, 6]. + +## 📖 Core Content +* **HITL의 주요 기능 및 아키텍처 패턴**: + * **중단 및 승인 메커니즘 (Interrupts and Approvals)**: 프로덕션 데이터베이스 쓰기나 외부 통신 등 민감하고 고위험군에 속하는 행동을 수행하기 전, 하네스는 실행을 일시 중지(pause)하고 인간의 승인을 대기하는 워크플로우를 구현한다 [3, 5, 6]. 단순한 허용/거부(allow/deny)를 넘어, 변경 후 승인(approve-with-changes)이나 대안 제시 등의 구조를 통해 안전이 보장되는 기본 하네스 디자인을 제공한다 [4]. + * **동적 개입과 세션 상태 관리**: Dify 및 LangGraph와 같은 프레임워크는 실행 루프 중간의 결정 지점에서 에이전트를 중지시키고, 상태를 지속시키며, 인간의 검토 UI를 노출한 뒤, 인간의 조치에 따라 이후의 실행 경로(승인, 거부, 에스컬레이션 등)를 라우팅하는 브레이크포인트(breakpoint) 패턴을 네이티브 워크플로우로 지원한다 [4]. + * **승인 수준의 다각화**: 중앙 집중식 기본 정책, 도구별로 세분화된 컨텍스트 통제, 비동기 제3자 승인, 프로토콜 기반의 실시간 상호작용 승인 등 다양한 HITL 패턴이 신뢰 경계 및 통합 제약에 맞추어 채택된다 [4]. +* **인간 개입의 역할 변화와 'Humans on the loop'**: + * 전통적인 HITL은 개별 출력물을 하나씩 검토하는 형태였으나, 현대의 에이전트 환경에서는 시스템의 처리량이 증가함에 따라 개별 작업에 대한 승인보다는 에이전트의 환경(하네스) 자체를 설계하고 유지보수하는 '루프 위(on the loop)'의 역할로 진화해야 한다는 점이 강조된다 [4, 7]. + * 인간의 피드백은 단순한 실행 게이트 역할을 넘어, 시간에 따라 에이전트의 프롬프트, 도구, 메모리, 평가기 등을 지속적으로 개선하기 위한 구조화된 데이터 소스로 기능한다 [4]. +* **보안과 거버넌스 보장**: + * 고유 계정을 사용하는 고정 자격 증명(fixed-credential) 환경이나, 공유된 메모리에 데이터를 기록할 때는 악의적 프롬프트 인젝션을 막고 데이터 무결성을 보호하기 위해 인간의 승인 게이트가 보안 계층으로서 필수적으로 배치된다 [8, 9]. + +## ⚖️ Trade-offs & Caveats +* **승인 피로(Approval Fatigue) 및 보안 무력화**: 모든 행동에 대해 인간의 승인을 강제하는 방식은 사용자에게 과도한 검토 부담을 주어, 주의 깊은 검토 없이 기계적으로 승인(auto-approve)하게 만드는 '승인 피로' 부작용을 낳는다 [4, 8]. Anthropic의 연구에 따르면, 사용자는 초기에는 20%만 자동 승인하지만 750번 이상의 세션이 누적되면 개입 없이 통과시키는 비율이 40%를 상회할 정도로 보안 및 통제력이 무력화되는 경향을 보인다 [10]. +* **확장성(Scalability)의 병목**: 사람의 개입 없이 진행할 수 있는 자율적인 자체 검증(self-verification) 루프가 제대로 갖춰지지 않은 채 인간의 승인에만 의존하면, 에이전트의 가장 큰 장점인 처리 속도와 규모의 확장이 심각하게 제한된다 [4, 11, 12]. 인간의 속도에 맞춰 시스템이 대기해야 하므로 자율형 인프라로서의 이점이 반감된다. +* **적응형 개입 모델의 불완전성**: 확장성 문제를 해결하기 위해 에이전트가 필요한 정보가 부족할 때만 인간에게 도움을 요청(ask_human)하거나 신뢰도에 기반하여 개입하는 적응형 모델이 제안된다 [4, 10]. 그러나 최상위 모델조차 정보가 부족한 상황에서 인간에게 도움을 구하기보다는 제한된 정보만으로 작업을 강행하려는 경향을 보여, 에이전트의 자기 객관화 능력이 완전하지 않으면 치명적 오류로 이어질 수 있다는 제약이 존재한다 [4]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/체크포인팅 (Checkpointing).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/체크포인팅 (Checkpointing).md new file mode 100644 index 00000000..2fef6b00 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/체크포인팅 (Checkpointing).md @@ -0,0 +1,17 @@ +# [[체크포인팅 (Checkpointing)]] + +## 📌 Brief Summary +에이전트 하네스에서 체크포인팅(Checkpointing)은 에이전트의 작업 상태를 지속적으로 보존하고 복구하기 위한 핵심 메모리 및 상태 관리 메커니즘입니다 [1]. 주로 장기 실행(Long-running) 작업이나 수일(Multi-day)에 걸친 파이프라인에서 중단된 작업을 컨텍스트 손실 없이 재개할 수 있도록 지원합니다 [2-4]. 또한, 오류 발생 시 시스템을 복구하는 결함 감내(Fault-tolerance) 패턴 및 인간 개입(Human-in-the-loop) 프로세스를 위한 일시 정지 지점으로도 활용됩니다 [5, 6]. + +## 📖 Core Content +* **상태 복구 및 메모리 영속성:** 체크포인팅은 에이전트 하네스를 구성하는 5대 핵심 기술 프리미티브 중 '메모리(Memory)' 영역에 속합니다 [1]. 세션 간 상태 지속성을 유지하고, 실패한 지점부터 장기(Long-horizon) 작업을 다시 시작할 수 있도록 허용하여 모델의 컨텍스트 연속성을 보장합니다 [1, 2]. +* **절전 및 기상(Hibernate-and-wake) 아키텍처:** 6시간 이상 소요되거나 수일에 걸쳐 진행되는 머신러닝 파이프라인 자동화 등의 작업에서, 에이전트가 중단된 지점의 컨텍스트를 잃지 않고 작업을 재개할 수 있도록 절전 및 기상 방식의 체크포인팅 기술이 적용됩니다 [3]. +* **명시적 상태 제어 및 오케스트레이션:** LangGraph와 같은 프로덕션 수준의 프레임워크는 체크포인트 지속성을 일급 객체(First-class primitives)로 취급하여, 복잡한 조건부 워크플로우 내에서 에이전트의 상태를 명시적이고 세밀하게 제어합니다 [4, 7]. +* **결함 감내(Fault Tolerance) 패턴:** 에이전트 시스템에서 복구 불가능한 실패를 줄이기 위해 사용되는 4단계 결함 감내 레이어(지수 백오프 재시도 → 모델 대체 체인 → 오류 분류 → 체크포인트 복구) 중 최후의 복구 수단으로 기능하여 신뢰성을 높입니다 [6]. +* **인간 개입(HITL) 통제 수단:** AutoResearchClaw 등의 시스템에서는 체크포인트를 인간 개입 모드(Intervention mode) 중 하나로 설정하여, 에이전트가 작업을 진행하는 중간에 멈추어 인간의 교정이나 승인을 받을 수 있는 지점을 제공합니다 [5]. + +## ⚖️ Trade-offs & Caveats +체크포인팅을 통해 에이전트의 상태를 세밀하게 제어하고 영속성을 부여하는 방식(예: LangGraph의 그래프 기반 상태 오케스트레이션)은 역할을 기반으로 하는 단순화된 대안 프레임워크들에 비해 설정이 장황(Verbose)해지며 학습 곡선이 가파르다는 제약이 있습니다 [8]. 또한, 중간 상태를 디스크나 파일 시스템에 오프로딩하여 상태를 보존하는 구조는 컨테이너화된 운영 환경에서 시스템의 운영상 복잡성(Operational complexity)을 증가시킬 수 있습니다 [9]. 그 외 체크포인팅 고유의 딥 다이브된 부작용이나 추가적인 반대 급부에 대해서는 소스에 관련 정보가 부족합니다. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 루프 (Reasoning Loop).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 루프 (Reasoning Loop).md new file mode 100644 index 00000000..8eacc5d9 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 루프 (Reasoning Loop).md @@ -0,0 +1,18 @@ +# [[추론 루프 (Reasoning Loop)]] + +## 📌 Brief Summary +추론 루프(Reasoning Loop)는 대규모 언어 모델(LLM)이 목표를 달성하기 위해 스스로 계획을 세우고, 행동(도구 호출)을 취하며, 그 결과를 관찰하여 다음 행동을 결정하는 반복적인 제어 및 실행 구조를 의미한다[1, 2]. 이는 '생각(Thought)-행동(Action)-관찰(Observation)'의 패턴을 따르는 ReAct(Reasoning and Acting) 구조를 기반으로 에이전트 하네스 내에서 구현된다[1, 3]. 본질적으로 에이전트의 확률적인 인지적 추론 과정을 실제 세계의 논리적 실행 및 검증 작업과 연결하는 에이전트 시스템의 핵심 운영 엔진 역할을 수행한다[2, 3]. + +## 📖 Core 소스 Content +* **작동 원리 및 ReAct 패턴**: 추론 루프는 모델이 계획을 세우고, 도구를 호출해 행동(Act)을 취한 뒤, 그 결과를 관찰(Observe) 및 검증(Verify)하는 과정을 `while` 루프와 같은 형태로 반복하는 ReAct 기반 구조로 작동한다[1, 3]. 하네스는 모델이 이러한 루프를 원활하게 수행할 수 있도록 이전 메시지 기록, 도구 실행 결과, 상태 정보 등을 유지하고 제공한다[1, 4]. +* **오류 복구 및 자가 검증 (Self-Verification)**: 에이전트는 코드를 작성한 후 대충 확인하고 조기에 종료하려는 편향을 가질 수 있으므로, 하네스는 실행이 끝날 때 검증을 강제하는 메커니즘을 둔다[5]. 에이전트의 종료 시도를 훅(Hook)으로 가로채어 깨끗한 컨텍스트 창에 원래의 프롬프트를 다시 주입하고 목표가 달성될 때까지 작업을 강제하는 '랄프 루프(Ralph Loop)' 혹은 '빌드-검증 루프(Build-Verify Loop)' 방식이 적용된다[5, 6]. +* **추론 컴퓨팅 예산 분배 (Reasoning Sandwich)**: 주어진 작업의 각 단계별로 얼마만큼의 추론 컴퓨팅(Reasoning compute)을 소비할지 결정하는 전략이 하네스 단에서 적용된다[7]. 예를 들어, 문제 해결을 위한 초기 계획(Planning) 단계와 최종 검증(Verification) 단계에 가장 높은 추론 자원을 할당하고, 실행 단계에는 상대적으로 낮은 자원을 할당하는 '추론 샌드위치(Reasoning Sandwich)' 패턴을 통해 성능과 효율성을 극대화한다[3, 8]. +* **동작 제어 및 미들웨어 통합**: 하네스는 추론 루프 내에서 스트리밍 도구 호출 주기 관리, 지수 백오프(Exponential Backoff)를 통한 API 재시도, 병렬 도구 실행, 토큰 카운팅 등을 함께 처리한다[9]. 또한 훅과 미들웨어를 통해 에이전트의 모델 호출 전후나 도구 호출 단계에 개입하여 결정론적인 제어 흐름을 관리한다[3]. + +## ⚖️ Trade-offs & Caveats +* **둠 루프(Doom Loop) 발생 위험**: 에이전트가 자신이 세운 초기 계획이 옳다고 착각하면, 동일하고 잘못된 접근 방식을 무한히 반복하며 헤어 나오지 못하는 '둠 루프'에 빠질 위험이 있다[10]. 이를 완화하기 위해 하네스 측에서 루프 감지 미들웨어(LoopDetectionMiddleware)를 도입하여 특정 파일에 대한 편집 횟수를 추적하고 강제로 에이전트에게 계획 재검토를 넛지(Nudge)해야만 한다[10]. +* **토큰 및 비용 소모의 급증**: 추론 루프의 단계를 깊게 가져가거나 각 하위 작업에서 추론 예산(Reasoning budget)을 최대로 설정할 경우, 모델의 문제 해결 능력은 상승하지만 그만큼 토큰 소모량과 실행 시간이 2배 이상 급증하는 비용적 반대급부가 발생한다[7]. +* **제한 시간 내 완료의 어려움**: 에이전트는 본질적으로 남은 시간에 대한 감각(Time estimation)이 부족하여 추론에만 매몰되다가 작업을 끝마치지 못할 수 있다[11]. 따라서 엄격한 타임아웃 제한이 있는 환경에서는 하네스에서 명시적인 시간 예산 경고(Time budget warnings)를 주입하여 에이전트가 추론을 멈추고 검증 모드로 전환하도록 강제해야만 타임아웃 실패를 예방할 수 있다[11]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 예산 (Reasoning Budget).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 예산 (Reasoning Budget).md new file mode 100644 index 00000000..4d52e427 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/추론 예산 (Reasoning Budget).md @@ -0,0 +1,19 @@ +# [[추론 예산 (Reasoning Budget)]] + +## 📌 Brief Summary +추론 예산(Reasoning Budget)은 AI 에이전트가 각 하위 작업(subtask)을 수행할 때 추론에 사용할 컴퓨팅 자원(토큰 및 시간)의 양을 결정하고 제어하는 개념이다 [1, 2]. 에이전트가 자율적으로 장시간 작동할 수 있게 됨에 따라, 하네스(Harness) 엔지니어링에서는 한정된 시간과 비용 내에서 효율성을 극대화하기 위해 이 예산을 최적화하는 것이 필수적이다 [2]. 모든 작업에 최대 예산을 쓰기보다는, 작업의 복잡도나 단계에 맞추어 예산을 동적으로 조절하거나 모델 스스로 결정하게 하는 적응형(Adaptive) 방식이 사용된다 [2, 3]. + +## 📖 Core Content +* **추론 예산의 명시적 제어:** 하네스는 모델의 API를 통해 턴(turn)당 추론 깊이를 제어한다 [1]. 예를 들어, Anthropic의 API는 `budget_tokens`로 추론 깊이를 조절하며 [1], GPT-5.2-codex 모델은 `low`, `medium`, `high`, `xhigh`의 4가지 추론 모드를 제공한다 [2]. Mistral Small 4 모델 역시 설정 가능한 추론 노력(reasoning effort) 매개변수를 지원한다 [4]. +* **작업별 예산 최적화 (Reasoning Sandwich):** LangChain의 연구에 따르면, 문제의 전체 구조를 이해하는 '계획(Planning)' 단계와 실수를 포착하고 솔루션을 제출하는 '검증(Verification)' 단계에는 더 많은 추론 컴퓨팅을 할당하는 것이 유리하다 [5]. 이를 바탕으로 계획과 검증에는 높은 예산을, 중간 구현에는 상대적으로 낮은 예산을 할당하는 **'추론 샌드위치(xhigh-high-xhigh)' 휴리스틱**이 하네스 설계의 베이스라인으로 활용된다 [5]. +* **계층적 독립성과 다중 모델 할당:** 하네스 아키텍처에서는 계획 계층(Planner)과 실행 계층(Executor)을 독립적으로 분리하여 각각 다른 모델 크기와 **추론 예산을 독자적으로 할당**할 수 있다 [6]. 더 나아가 다중 모델 시스템에서는 계획 단계에 추론 예산이 높은 대형 모델을 사용하고, 구현 단계는 소형 모델로 넘기는 방식으로 컴퓨팅 지출의 균형을 맞출 수 있다 [3]. +* **토큰 예산과 인프라 제어:** FinOps 관점에서 에이전트 하네스는 실행(run) 당 토큰 예산 상한선을 두어 예산을 초과하는 비정상적인 컴퓨팅 자원 남용을 게이트웨이 단계에서 통제하며, 예산 초과분은 시스템 수준에서 클램프(clamp)하여 조정한다 [7, 8]. + +## ⚖️ Trade-offs & Caveats +* **비용과 시간의 상충 관계 (Trade-off):** 추론 예산을 늘리면 에이전트가 각 단계를 더 깊이 평가할 수 있지만, **토큰 소모량과 실행 시간이 2배 이상 급증**하는 부작용이 있다 [2]. +* **시간 초과(Timeout)로 인한 성능 하락:** 엄격한 제한 시간이 있는 환경(예: Terminal Bench 등)에서 모든 작업에 대해 최대 추론 예산(예: `xhigh`)을 할당할 경우, 오히려 시간 초과로 인해 작업이 중단되어 점수가 하락한다(예: `high` 설정 시 63.6% 대비 `xhigh` 시 53.9%로 하락) [5]. +* **상태 보존 규칙 위반 위험:** 하네스에서 확장된 추론(Extended thinking)을 사용할 때 생성된 '생각 블록(thinking blocks)'은 도구 실행 결과를 반환할 때 **반드시 컨텍스트에 보존**되어야 한다 [1]. 추론 예산을 소모하며 만든 이 블록들을 누락할 경우, 다단계 추론의 맥락이 끊어지며 모델이 심각한 오작동을 일으킬 수 있는 제약 사항이 존재한다 [1]. + + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/컨텍스트 관리 (Context Management).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/컨텍스트 관리 (Context Management).md new file mode 100644 index 00000000..12dfab83 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/컨텍스트 관리 (Context Management).md @@ -0,0 +1,20 @@ +# [[컨텍스트 관리 (Context Management)]] + +## 📌 Brief Summary +컨텍스트 관리는 에이전트가 장기 세션을 수행할 때 대화 기록, 도구 출력 결과 등 방대한 정보 중 무엇을 유지하고, 요약하며, 폐기할지 결정하는 에이전트 하네스의 핵심 구성 요소이다 [1]. 이는 모델이 제한된 토큰 예산 내에서 중요한 문맥을 잃지 않고 작동하도록 돕는다 [2]. 궁극적으로 방대한 도구 출력과 기록이 쌓이면서 모델의 성능이 저하되는 '컨텍스트 부패(Context Rot)' 현상을 방지하는 역할을 한다 [3]. + +## 📖 Core Content +* **컨텍스트 압축(Context Compaction):** 에이전트 세션이 길어지면 모델의 컨텍스트 윈도우를 초과할 수 있으므로, 최신 대화 맥락은 유지하되 재현할 필요가 없는 오래된 도구 사용 기록을 다듬고 요약하여 압축한다 [2]. 이는 웹 검색 등의 작업 환경에서 토큰 소비를 대폭 줄여주며, 에이전트가 한계에 부딪히지 않고 워크플로우를 완료할 수 있게 한다 [4]. +* **점진적 공개(Progressive Disclosure) 및 계층적 로딩:** 모든 정보를 한 번에 로드하지 않고 필요에 따라 점진적으로 제공한다 [5]. 예를 들어, 스킬을 찾을 때는 짧은 메타데이터만 먼저 읽고, 올바른 스킬이 식별된 후에 전체 파일 및 참조 파일을 순차적으로 로드하여 모델의 정보 과부하를 방지한다 [5]. +* **도구 출력 오프로딩(Tool Call Offloading):** 브라우저 스냅샷이나 방대한 코드 기반과 같이 용량이 큰 도구 출력 결과를 컨텍스트 윈도우에 전부 밀어 넣지 않고 파일 시스템 등에 샌드박싱하여 보관한다 [4, 6]. 모델에게는 출력의 처음과 끝 토큰 일부만 남기거나 검색을 통해 필요한 파편화된 정보만 제공하여 컨텍스트 압력을 완화한다 [4, 6]. +* **자율적 컨텍스트 압축(Autonomous Context Compression):** 하네스가 정해진 토큰 임계값에 따라 기계적으로 압축하는 것을 넘어, 에이전트가 자체적으로 판단하여 작업 중간이나 대규모 입력을 처리하기 전에 요약 및 압축을 지시하는 방식이다 [4]. 이를 통해 작업 진행 중 문맥이 손상되는 것을 방지하고 에이전트가 보존할 가치가 있는 지식을 스스로 큐레이션 할 수 있다 [4]. +* **프롬프트 캐싱(Prompt Caching):** 반복되는 시스템 프롬프트, 도구 정의, 긴 문서 등을 캐싱하여 멀티 턴 에이전트 세션 전반에서 재사용함으로써 비용과 지연 시간을 효율적으로 통제한다 [4]. + +## ⚖️ Trade-offs & Caveats +* **데이터 출처 및 계통(Lineage) 상실:** 컨텍스트를 압축하고 요약하는 과정에서 데이터의 출처가 소실될 수 있다 [7]. 에이전트가 압축된 컨텍스트를 읽을 때 그 정보가 원래 어디서 파생되었는지 기록이 남지 않으므로, 에이전트가 잘못된 결론을 내렸을 때 이것이 모델의 문제인지, 프롬프트의 문제인지, 혹은 원본 데이터의 문제인지 근본 원인을 추적하기 어렵다 [7, 8]. +* **핵심 규칙의 유실 위험:** 자동 압축 메커니즘에만 의존할 경우 초기 지시사항, 중간 결정, 또는 코딩 스타일 규칙 등 중요한 정보가 압축 과정에서 유실될 수 있다 [9]. 따라서 절대 잃어버려서는 안 되는 핵심 규칙은 압축 시스템의 영향을 받지 않는 시스템 프롬프트 영역(예: CLAUDE.md)에 별도로 분리 및 고정해야 하는 관리적 부담이 따른다 [9]. +* **입력 데이터 품질 검증의 부재:** 컨텍스트 관리 시스템은 입력된 데이터가 신뢰할 수 있다고 가정할 뿐, 오래되거나 승인되지 않은 데이터, 스키마가 변경된 불량 데이터가 하네스에 유입되는 것을 자체적으로 방지하지 못한다 [10-12]. 아무리 밀도 있게 압축된 정보라도 그 소스가 오염되었다면 에이전트는 결함이 있는 정보를 바탕으로 행동하게 된다 [13]. +* **중간 정보 유실(Lost in the Middle):** 20만 개 이상의 거대한 토큰 윈도우를 확보하더라도, 방대한 도구 출력과 과거 기록이 쌓이면서 모델이 중간에 위치한 중요한 정보를 무시하는 현상이 발생할 수 있다 [14, 15]. 이를 방지하기 위해 가장 중요한 컨텍스트는 항상 프롬프트의 시작이나 끝부분(경계)에 인위적으로 재배치해야 하는 아키텍처적 제약이 존재한다 [15]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/파일 시스템 (Filesystem).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/파일 시스템 (Filesystem).md new file mode 100644 index 00000000..b4a53f86 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/파일 시스템 (Filesystem).md @@ -0,0 +1,7 @@ +# [[파일 시스템 (Filesystem)]] + +## 📌 Brief Summary +에이전트 하네스에서 파일 시스템은 대규모 언어 모델(LLM)의 지능을 실제 실행 환경과 연결하는 가장 기초적이고 핵심적인 기술 프리미티브 중 하나이다 [1-3]. 이는 에이전트에게 데이터와 코드를 읽고 쓸 수 있는 영구적인 작업 공간을 제공하여 단일 컨텍스트 윈도우의 제약을 극복할 수 있게 한다 [3-5]. 또한, 여러 에이전트와 인간 개발자가 공유된 파일을 통해 장기 작업을 조율하고 상태를 추적할 수 있는 자연스러운 협업 표면(Collaboration Surface)으로 기능한다 [5-7]. + +## 📖 Core Content +* **물리적 작업 공간 및 상호작용 토대:** 에이전트 하네스는 파일 읽기, 쓰기, 수정, 파일 시스템 검색(Grep, Glob) 등 파일 I/O 도구를 제공한다 [8] \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/피드백 센서 (Feedback Sensors).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/피드백 센서 (Feedback Sensors).md new file mode 100644 index 00000000..459ff194 --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/피드백 센서 (Feedback Sensors).md @@ -0,0 +1,25 @@ +# [[피드백 센서 (Feedback Sensors)]] + +## 📌 Brief Summary +피드백 센서(Feedback Sensors)는 에이전트가 행동을 취한 후 그 결과를 관찰하여, 필요 시 스스로 수정할 수 있도록 돕는 에이전트 하네스의 사후 제어(Feedback controls) 메커니즘입니다[1, 2]. 린터(Linter), 정적 분석 도구, 단위 테스트 실행기 등이 대표적이며, 에이전트가 생성한 결과물에 대한 에러 메시지 등의 출력값을 가로채어 모델에게 피드백으로 제공합니다[2]. 이를 통해 에이전트는 인간의 직접적인 개입 없이도 '자가 치유(Self-healing)' 능력을 갖추고 소프트웨어 품질을 지속적으로 향상할 수 있습니다[2]. + +## 📖 Core Content +* **센서의 기능과 자가 치유 루프:** + 피드백 센서는 에이전트의 행위가 완료된 후 평가를 수행합니다[1, 2]. 이 센서들이 출력하는 신호(예: 컴파일 에러 메시지)가 모델이 이해하기 쉽고 스스로 수정할 수 있는 지침을 포함하고 있을 때(일종의 긍정적인 프롬프트 인젝션) 가장 강력한 효과를 발휘합니다[1, 2]. +* **실행 방식의 분류 (Computational vs Inferential):** + 피드백 센서는 크게 계산적(Computational) 센서와 추론적(Inferential) 센서로 나뉩니다[3]. + * **계산적 센서:** CPU 기반으로 실행되며 밀리초 단위로 매우 빠르고 결정론적인 결과를 보장합니다[3]. 테스트, 린터, 타입 체커, 구조 분석 등이 여기에 해당하며 중복 코드나 순환 복잡도 등 구조적 문제를 신뢰성 있게 포착합니다[3, 4]. + * **추론적 센서:** 시맨틱 분석, AI 코드 리뷰, '심판으로서의 LLM(LLM as judge)' 등을 의미하며 주로 GPU나 NPU에 의해 실행됩니다[3, 5]. 더 느리고 비용이 많이 들며 결과가 비결정론적(확률적)이지만, 더 풍부한 의미론적 판단을 제공할 수 있습니다[3, 5]. +* **센서 적용의 타이밍과 전략:** + 비용, 속도, 중요도에 따라 소프트웨어 생명주기에 센서를 적절히 분산 배치해야 합니다[6]. 린터나 빠른 테스트 스위트 같은 계산적 센서는 커밋이나 통합 이전에 일찍 실행하고(Keep quality left), 뮤테이션 테스트나 광범위한 AI 코드 리뷰 같은 비용이 드는 센서는 통합 후 파이프라인에서 실행합니다[6, 7]. 또한 데드 코드 감지, 의존성 스캐너 등은 코드베이스를 지속적으로 모니터링하는 건강 상태 센서로 활용됩니다[7]. +* **응용 영역:** + 피드백 센서는 주로 코드의 유지보수성을 관리하는 데 쓰이지만(Maintainability harness)[4], 애플리케이션의 성능이나 아키텍처 특성을 검증하는 적합성 하네스(Architecture fitness harness)[8], 그리고 AI가 생성한 테스트 스위트를 검증하는 동작 하네스(Behaviour harness)[9] 등에도 적용됩니다. + +## ⚖️ Trade-offs & Caveats +* **계산적 센서의 의미론적 한계:** 계산적 센서는 빠르고 결정론적이지만, 문제에 대한 잘못된 진단, 과도한 엔지니어링(over-engineering), 지시사항 오해 등 고차원적인 의미론적 문제(Semantic judgment)를 잡아내지는 못합니다[4, 10]. 사람이 애초에 명확한 명세를 제공하지 않으면 센서만으로는 '정확성'을 보장할 수 없습니다[10]. +* **추론적 센서의 비용 및 비결정성 문제:** 추론적(Inferential) 센서는 복잡한 의미론적 판단을 내릴 수 있지만, 연산 비용이 높고 결과가 확률적이어서 매 커밋마다 빈번하게 실행하기에는 경제적·시간적 제약이 따릅니다[4, 5, 10]. +* **자가 생성 테스트에 대한 과도한 의존 위험:** 동작 하네스 영역에서 AI가 스스로 생성한 테스트 스위트에만 전적으로 의존하는 것은 아직 신뢰성이 부족하며, 수동 테스트를 완전히 대체하기 어렵습니다[9, 11]. +* **하네스의 일관성 유지 문제:** 피드백 센서가 결함을 잡아내지 않는 것이 실제로 코드 품질이 높아서인지, 아니면 감지 메커니즘이 부족해서인지 구분하기 어려울 수 있습니다[12]. 또한 사전에 제약하는 가이드(Feedforward)와 센서의 피드백 신호가 서로 모순될 때 에이전트가 이를 어떻게 조율해야 하는지에 대한 설계적 난제가 존재합니다[12]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/허용 목록 (Allow-listing).md b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/허용 목록 (Allow-listing).md new file mode 100644 index 00000000..b8ac36aa --- /dev/null +++ b/10_Wiki/Topics/_Archive_Orphans/Harness_Research_2026-05/허용 목록 (Allow-listing).md @@ -0,0 +1,17 @@ +# [[허용 목록 (Allow-listing)]] + +## 📌 Brief Summary +허용 목록(Allow-listing)은 에이전트 하네스 내에서 AI 에이전트가 호출할 수 있는 도구나 접근 가능한 네트워크를 명시적으로 선언하여 제한하는 보안 및 거버넌스 메커니즘입니다 [1, 2]. 에이전트는 주변에 열려 있는 포괄적 권한(ambient permissions)을 가질 수 없으며, 오직 허용 목록에 등록된 도구와 환경만 사용할 수 있습니다 [2]. 이를 통해 에이전트의 과도한 권한 행사를 방지하고 엔터프라이즈 환경에서의 안전한 작업을 보장합니다 [1, 2]. + +## 📖 Core Content +* **명시적 권한 및 도구 제어:** 하네스 환경에서 허용 목록은 에이전트의 행동 반경을 통제하는 핵심 수단입니다. 에이전트는 오직 명시적으로 선언된 도구만을 호출할 수 있으며, 이때 도구의 사양은 일반적인 소프트웨어 코드처럼 리뷰를 거치고 버전 관리가 이루어집니다 [2]. +* **엔터프라이즈 및 프레임워크 적용 사례:** + * **GitHub Enterprise:** 대규모 조직에서 에이전트 거버넌스를 확보하기 위해, 규칙 세트로 보호되는 구성 및 임시 러너 강제 적용과 함께 '클라우드 에이전트 방화벽 허용 목록(cloud-agent firewall allowlisting)'을 활용하여 에이전트 환경을 표준화하고 통제합니다 [1]. + * **Claude Agent SDK:** 5단계의 권한 평가 순서(훅 → 거부 규칙 → 권한 모드 → 허용 규칙(allow rules) → canUseTool)를 가지고 있으며, `allowedTools` 및 `disallowedTools` 속성을 통해 선언적으로 에이전트의 도구 접근 범위를 결정합니다 [1]. + +## ⚖️ Trade-offs & Caveats +* **정적 목록(Static Lists)의 제약:** 단순히 어떤 도구를 사용할 수 있는지 지정하는 정적인 허용 및 거부 목록(static allow/deny lists) 방식은 특정 도구에 대한 접근 자체를 막는 데는 유용하지만, 도구 호출 시 발생하는 입력과 출력 내용의 적절성까지 통제하는 행동 수준의 강제(behavioral-level enforcement)를 수행하기에는 불충분하다는 제약이 있습니다 [3]. +* **추가적 보안 계층 요구:** 정적 허용 목록의 한계를 보완하기 위해서는 NeMo Guardrails와 같이 LLM이 호출할 수 있는 도구와 그에 따른 입출력 데이터의 내용까지 실행 계층(execution rail layer)에서 동적으로 제한할 수 있는 프로그래밍 가능한 가드레일 툴킷이 병행되어야 합니다 [3]. + +--- +*Last updated: 2026-05-05* \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/auto_planner.json b/10_Wiki/Topics/_agents/youtube/tools/auto_planner.json deleted file mode 100644 index 3f12eedc..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/auto_planner.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "INTERVAL_HOURS": 2, - "TOTAL_RUN_HOURS": 8 -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/auto_planner.py b/10_Wiki/Topics/_agents/youtube/tools/auto_planner.py deleted file mode 100644 index 61475b31..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/auto_planner.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python3 -"""Auto Planner — runs trend_sniper.py on a fixed interval for a chosen -duration (e.g. overnight). Reads its config from auto_planner.json.""" -import os, json, time, datetime, subprocess, sys - -HERE = os.path.dirname(os.path.abspath(__file__)) -CONFIG_PATH = os.path.join(HERE, "auto_planner.json") -SNIPER_PATH = os.path.join(HERE, "trend_sniper.py") - -def load_config(): - try: - with open(CONFIG_PATH, "r", encoding="utf-8") as f: - return json.load(f) - except Exception as e: - print(f"❌ 설정 파일을 읽을 수 없어요: {CONFIG_PATH}\n{e}") - sys.exit(1) - -def main(): - cfg = load_config() - interval_h = float(cfg.get("INTERVAL_HOURS", 2)) - total_h = float(cfg.get("TOTAL_RUN_HOURS", 8)) - print(f"\n🚀 [오토 플래너] {total_h}시간 동안 {interval_h}시간마다 트렌드 분석 실행") - if not os.path.exists(SNIPER_PATH): - print(f"❌ trend_sniper.py를 찾을 수 없어요: {SNIPER_PATH}") - sys.exit(1) - start = time.time() - loop = 0 - while True: - if time.time() - start > total_h * 3600: - print("\n☀️ 목표 가동 시간을 채웠어요. 종료합니다.") - break - loop += 1 - ts = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') - print(f"\n[{ts}] 🤖 {loop}회차 트렌드 스나이핑") - try: - subprocess.run([sys.executable, SNIPER_PATH], check=False) - except Exception as e: - print(f"❌ 실행 실패: {e}") - print(f"⏳ 다음 실행: {interval_h}시간 후") - time.sleep(interval_h * 3600) - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.json b/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.json deleted file mode 100644 index 5cd8faf2..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "VIDEOS_PER_CHANNEL": 5, - "COMMENTS_PER_VIDEO": 20, - "LOOKBACK_DAYS": 14 -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.py b/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.py deleted file mode 100644 index 3b0ba6d7..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/comment_harvester.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python3 -"""Comment Harvester — for every channel in WATCHED_CHANNELS, pulls the most -recent N videos and their top M comments. Appends the results to the agent's -memory.md so the YouTube agent can reference real audience reactions on the -next think step. - -Reads from youtube_account.json (api key, watched channels) and -comment_harvester.json (volume settings).""" -import os, json, sys, time, datetime - -HERE = os.path.dirname(os.path.abspath(__file__)) -ACCOUNT = os.path.join(HERE, "youtube_account.json") -CONFIG = os.path.join(HERE, "comment_harvester.json") -# memory.md lives one level up — under _agents/youtube/ -MEMORY = os.path.abspath(os.path.join(HERE, "..", "memory.md")) -REPORT = os.path.join(HERE, "comment_harvester_report.md") - -def _load(p): - with open(p, "r", encoding="utf-8") as f: - return json.load(f) - -def _resolve_channel_id(youtube, handle): - h = handle.lstrip("@") - try: - r = youtube.search().list(part="snippet", q=h, type="channel", maxResults=1).execute() - items = r.get("items", []) - if items: - return items[0]["snippet"]["channelId"], items[0]["snippet"]["title"] - except Exception as e: - print(f"⚠️ {handle} 채널 조회 실패: {e}") - return None, None - -def main(): - if not os.path.exists(ACCOUNT): - print("❌ youtube_account.json이 없어요. 먼저 그 도구로 설정.") - sys.exit(1) - acct = _load(ACCOUNT) - cfg = _load(CONFIG) if os.path.exists(CONFIG) else {} - api_key = (acct.get("YOUTUBE_API_KEY") or "").strip() - watched = acct.get("WATCHED_CHANNELS") or [] - if not api_key: - print("❌ YOUTUBE_API_KEY 비어있음.") - sys.exit(1) - if not watched: - print("❌ WATCHED_CHANNELS가 비어있어요. youtube_account.json에 핸들 목록을 넣어주세요.") - print(' 예: "WATCHED_CHANNELS": ["@channel_a", "@channel_b"]') - sys.exit(1) - vids_per = int(cfg.get("VIDEOS_PER_CHANNEL", 5)) - cmts_per = int(cfg.get("COMMENTS_PER_VIDEO", 20)) - lookback = int(cfg.get("LOOKBACK_DAYS", 14)) - - try: - from googleapiclient.discovery import build - except ImportError: - print("❌ pip install google-api-python-client") - sys.exit(1) - youtube = build("youtube", "v3", developerKey=api_key) - after = (datetime.datetime.utcnow() - datetime.timedelta(days=lookback)).isoformat("T") + "Z" - - harvested = [] - for ch in watched: - cid, ctitle = _resolve_channel_id(youtube, ch) - if not cid: - continue - print(f"📡 [{ch}] 최근 영상 {vids_per}개 가져오는 중...") - sr = youtube.search().list(part="snippet", channelId=cid, maxResults=vids_per, - order="date", publishedAfter=after, type="video").execute() - for it in sr.get("items", []): - vid = it["id"]["videoId"] - vtitle = it["snippet"]["title"] - print(f" 💬 {vtitle[:60]}") - try: - cr = youtube.commentThreads().list(part="snippet", videoId=vid, - maxResults=cmts_per, order="relevance", - textFormat="plainText").execute() - except Exception as e: - msg = str(e) - if "commentsDisabled" in msg or "disabled" in msg.lower(): - continue - print(f" ⚠️ 댓글 가져오기 실패: {e}") - continue - comments = [] - for ci in cr.get("items", []): - top = ci["snippet"]["topLevelComment"]["snippet"] - comments.append({ - "author": top.get("authorDisplayName", ""), - "likes": int(top.get("likeCount", 0)), - "text": (top.get("textDisplay", "") or "")[:280], - }) - harvested.append({ - "channel": ch, "channel_title": ctitle, - "video": vtitle, "video_id": vid, "comments": comments, - }) - - if not harvested: - print("⚠️ 수집된 댓글 없음.") - sys.exit(0) - - ts = time.strftime('%Y-%m-%d %H:%M') - md_lines = [f"\n## 💬 시청자 댓글 수집 — {ts}"] - for h in harvested: - md_lines.append(f"\n### {h['channel_title']} ({h['channel']}) — {h['video']}") - md_lines.append(f"https://youtu.be/{h['video_id']}") - for c in h["comments"][:10]: - md_lines.append(f"- ({c['likes']}❤) **{c['author']}**: {c['text']}") - block = "\n".join(md_lines) - - # Append to memory so the agent uses these comments next think. - os.makedirs(os.path.dirname(MEMORY), exist_ok=True) - if not os.path.exists(MEMORY): - with open(MEMORY, "w", encoding="utf-8") as f: - f.write("# YouTube 에이전트 — 메모리\n\n") - with open(MEMORY, "a", encoding="utf-8") as f: - f.write("\n" + block + "\n") - with open(REPORT, "a", encoding="utf-8") as f: - f.write("\n" + block + "\n\n---\n") - print(f"\n✅ 메모리에 추가: {MEMORY}") - print(f"✅ 보고서: {REPORT}") - print(f" {len(harvested)}개 영상 · 평균 {sum(len(h['comments']) for h in harvested)//max(len(harvested),1)}개 댓글") - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.json b/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.json deleted file mode 100644 index 8312755f..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "TOP_N_PER_CHANNEL": 5, - "LOOKBACK_DAYS": 30 -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.py b/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.py deleted file mode 100644 index 1cb28bf2..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/competitor_brief.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python3 -"""Competitor Brief — for every channel in COMPETITOR_CHANNELS, pulls their -recent top-performing videos and asks the local LLM for a *prescriptive* -brief: what should YOU do next, given what's working for them. - -Reads youtube_account.json (api key, competitors, ollama, model) and -competitor_brief.json (volume).""" -import os, json, sys, time, datetime - -HERE = os.path.dirname(os.path.abspath(__file__)) -ACCOUNT = os.path.join(HERE, "youtube_account.json") -CONFIG = os.path.join(HERE, "competitor_brief.json") -REPORT = os.path.join(HERE, "competitor_brief_report.md") - -def _load(p): - with open(p, "r", encoding="utf-8") as f: - return json.load(f) - -def _resolve_channel_id(youtube, handle): - h = handle.lstrip("@") - try: - r = youtube.search().list(part="snippet", q=h, type="channel", maxResults=1).execute() - items = r.get("items", []) - if items: - return items[0]["snippet"]["channelId"], items[0]["snippet"]["title"] - except Exception: - pass - return None, None - -def _push_telegram(account, text): - token = (account.get("TELEGRAM_BOT_TOKEN") or "").strip() - chat = (account.get("TELEGRAM_CHAT_ID") or "").strip() - if not token or not chat: - return - try: - import requests - requests.post(f"https://api.telegram.org/bot{token}/sendMessage", - json={"chat_id": chat, "text": text[:4000], "parse_mode": "Markdown"}, - timeout=10) - except Exception: - pass - -def main(): - if not os.path.exists(ACCOUNT): - print("❌ youtube_account.json이 없어요.") - sys.exit(1) - acct = _load(ACCOUNT) - cfg = _load(CONFIG) if os.path.exists(CONFIG) else {} - api_key = (acct.get("YOUTUBE_API_KEY") or "").strip() - competitors = acct.get("COMPETITOR_CHANNELS") or [] - if not api_key: - print("❌ YOUTUBE_API_KEY 비어있음.") - sys.exit(1) - if not competitors: - print("❌ COMPETITOR_CHANNELS가 비어있어요. youtube_account.json에 채워주세요.") - sys.exit(1) - top_n = int(cfg.get("TOP_N_PER_CHANNEL", 5)) - lookback = int(cfg.get("LOOKBACK_DAYS", 30)) - ollama_url = (acct.get("OLLAMA_URL") or "http://127.0.0.1:11434").rstrip("/") - model = acct.get("MODEL") or "" - - try: - from googleapiclient.discovery import build - import requests - except ImportError: - print("❌ pip install google-api-python-client requests") - sys.exit(1) - youtube = build("youtube", "v3", developerKey=api_key) - after = (datetime.datetime.utcnow() - datetime.timedelta(days=lookback)).isoformat("T") + "Z" - - snapshot = [] - for ch in competitors: - cid, ctitle = _resolve_channel_id(youtube, ch) - if not cid: - print(f"⚠️ {ch} 채널 못 찾음") - continue - print(f"🔭 [{ch}] 최근 영상 분석 중...") - sr = youtube.search().list(part="snippet", channelId=cid, maxResults=top_n, - order="viewCount", publishedAfter=after, type="video").execute() - ids = [it["id"]["videoId"] for it in sr.get("items", [])] - if not ids: - continue - st = youtube.videos().list(part="statistics,snippet", id=",".join(ids)).execute() - for it in st.get("items", []): - stats = it.get("statistics", {}) - snip = it.get("snippet", {}) - snapshot.append({ - "channel": ctitle, - "title": snip.get("title", ""), - "views": int(stats.get("viewCount", 0)), - "published": snip.get("publishedAt", "")[:10], - }) - - if not snapshot: - print("❌ 데이터 수집 실패.") - sys.exit(1) - - snapshot.sort(key=lambda r: r["views"], reverse=True) - data_text = "\n".join(f"[{r['channel']}] {r['views']:,}회 · {r['published']} · {r['title']}" - for r in snapshot[:25]) - - if not model: - try: - r = requests.get(f"{ollama_url}/api/tags", timeout=5) - r.raise_for_status() - models = [m["name"] for m in r.json().get("models", [])] - if not models: - print("❌ 로컬 LLM에 모델이 없어요.") - sys.exit(1) - model = models[0] - except Exception as e: - print(f"❌ LLM 연결 실패: {e}") - sys.exit(1) - - prompt = f"""당신은 유튜브 알고리즘 전략가입니다. 아래는 경쟁 채널들의 최근 {lookback}일간 상위 영상 데이터입니다. - -[경쟁 데이터] -{data_text} - -이 채널 운영자에게 **지시문 형식**으로 다음을 작성하세요. 모호한 조언 금지, 구체적이고 실행 가능한 지시. - -## 1) 지금 당장 해야 하는 것 (3개) -- 각 항목: "~을(를) 하세요. 왜냐하면 …" - -## 2) 이번 주 안에 시도해야 하는 것 (3개) -- 각 항목: 구체적 영상 제목 후보 또는 후크 문장 포함 - -## 3) 절대 하지 말아야 할 것 (1개) -- 경쟁사 데이터에서 보이는 함정 패턴 - -## 4) 한 줄 요약 -- 다음 영상의 핵심 컨셉을 한 문장으로 -""" - print("🧠 [LLM 분석 중...]") - try: - r = requests.post(f"{ollama_url}/api/generate", - json={"model": model, "prompt": prompt, "stream": False}, - timeout=240) - r.raise_for_status() - brief = r.json().get("response", "").strip() - except Exception as e: - print(f"❌ LLM 실패: {e}") - sys.exit(1) - - ts = time.strftime('%Y-%m-%d %H:%M') - out = f"# 🔭 경쟁 채널 브리프 — {ts}\n\n채널: {', '.join(competitors)} · 최근 {lookback}일\n\n{brief}\n" - print("\n" + "="*60) - print(out) - print("="*60) - with open(REPORT, "a", encoding="utf-8") as f: - f.write("\n\n" + out + "\n---\n") - print(f"\n✅ 보고서: {REPORT}") - _push_telegram(acct, out) - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.json b/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.json deleted file mode 100644 index 0e6f3ccd..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "LOOKBACK_DAYS": 30, - "TOP_N": 10 -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.py b/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.py deleted file mode 100644 index da7e6fcb..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/my_videos_check.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python3 -"""My Videos Check — pulls your own channel's recent uploads, computes a -view-count baseline (median of last N), and flags which videos are above / -below the line. Outputs a short report. Optionally pings Telegram. - -Reads YOUTUBE_API_KEY + MY_CHANNEL_HANDLE/ID from youtube_account.json. -Reads LOOKBACK_DAYS / TOP_N from my_videos_check.json.""" -import os, json, sys, time, datetime - -HERE = os.path.dirname(os.path.abspath(__file__)) -ACCOUNT = os.path.join(HERE, "youtube_account.json") -CONFIG = os.path.join(HERE, "my_videos_check.json") -REPORT = os.path.join(HERE, "my_videos_check_report.md") - -def _load(p): - with open(p, "r", encoding="utf-8") as f: - return json.load(f) - -def _resolve_channel_id(youtube, handle, channel_id): - if channel_id: - return channel_id - if not handle: - return None - h = handle.lstrip("@") - try: - r = youtube.search().list(part="snippet", q=h, type="channel", maxResults=1).execute() - items = r.get("items", []) - if items: - return items[0]["snippet"]["channelId"] - except Exception as e: - print(f"⚠️ 채널 ID 조회 실패: {e}") - return None - -def _push_telegram(account, text): - token = (account.get("TELEGRAM_BOT_TOKEN") or "").strip() - chat = (account.get("TELEGRAM_CHAT_ID") or "").strip() - if not token or not chat: - return - try: - import requests - requests.post( - f"https://api.telegram.org/bot{token}/sendMessage", - json={"chat_id": chat, "text": text, "parse_mode": "Markdown"}, - timeout=10, - ) - print("📨 텔레그램으로 보고 전송") - except Exception as e: - print(f"⚠️ 텔레그램 전송 실패: {e}") - -def main(): - if not os.path.exists(ACCOUNT): - print("❌ youtube_account.json이 없어요. 같은 폴더에서 youtube_account 도구를 먼저 실행/설정하세요.") - sys.exit(1) - acct = _load(ACCOUNT) - cfg = _load(CONFIG) if os.path.exists(CONFIG) else {} - api_key = (acct.get("YOUTUBE_API_KEY") or "").strip() - handle = (acct.get("MY_CHANNEL_HANDLE") or "").strip() - chan_id = (acct.get("MY_CHANNEL_ID") or "").strip() - if not api_key: - print("❌ YOUTUBE_API_KEY가 비어있어요. youtube_account.json에 채워주세요.") - sys.exit(1) - if not (handle or chan_id): - print("❌ MY_CHANNEL_HANDLE 또는 MY_CHANNEL_ID 중 하나는 채워야 해요.") - sys.exit(1) - lookback = int(cfg.get("LOOKBACK_DAYS", 30)) - top_n = int(cfg.get("TOP_N", 10)) - - try: - from googleapiclient.discovery import build - except ImportError: - print("❌ google-api-python-client 미설치. pip install google-api-python-client requests") - sys.exit(1) - youtube = build("youtube", "v3", developerKey=api_key) - - cid = _resolve_channel_id(youtube, handle, chan_id) - if not cid: - print("❌ 채널 ID를 찾지 못했어요. youtube_account.json의 핸들/ID 확인.") - sys.exit(1) - - print(f"🎬 [내 영상 체크] 채널 {handle or cid} 최근 {top_n}개 분석 중...") - after = (datetime.datetime.utcnow() - datetime.timedelta(days=lookback)).isoformat("T") + "Z" - sr = youtube.search().list(part="snippet", channelId=cid, maxResults=top_n, - order="date", publishedAfter=after, type="video").execute() - vids = [(it["id"]["videoId"], it["snippet"]["title"], it["snippet"]["publishedAt"]) - for it in sr.get("items", [])] - if not vids: - print(f"⚠️ 최근 {lookback}일 안에 업로드한 영상이 없어요.") - sys.exit(0) - - stats = youtube.videos().list(part="statistics", id=",".join(v[0] for v in vids)).execute() - sm = {it["id"]: it["statistics"] for it in stats.get("items", [])} - rows = [] - for vid, title, pub in vids: - s = sm.get(vid, {}) - views = int(s.get("viewCount", 0)) - likes = int(s.get("likeCount", 0)) - comments = int(s.get("commentCount", 0)) - rows.append({"id": vid, "title": title, "pub": pub[:10], "views": views, "likes": likes, "comments": comments}) - - rows.sort(key=lambda r: r["views"], reverse=True) - views_list = sorted([r["views"] for r in rows]) - median = views_list[len(views_list)//2] if views_list else 0 - - print("\n" + "="*60) - print(f"중간값(median) 조회수: {median:,}") - print("="*60) - for r in rows: - marker = "🔥" if r["views"] >= median * 1.5 else ("👍" if r["views"] >= median else "🥶") - print(f"{marker} {r['views']:>7,}회 · {r['pub']} · {r['title'][:60]}") - print(f" https://youtu.be/{r['id']}") - - above = [r for r in rows if r["views"] >= median * 1.5] - below = [r for r in rows if r["views"] < median * 0.5] - - summary_lines = [ - f"# 🎬 내 채널 체크 — {time.strftime('%Y-%m-%d %H:%M')}", - f"채널: {handle or cid} · 최근 {lookback}일 · 영상 {len(rows)}개", - f"조회수 중간값: **{median:,}**", - "", - f"## 🔥 떡상 (중간값×1.5 이상) — {len(above)}개", - ] - for r in above[:5]: - summary_lines.append(f"- {r['views']:,}회 · {r['title']}") - summary_lines.append(f"\n## 🥶 부진 (중간값×0.5 미만) — {len(below)}개") - for r in below[:5]: - summary_lines.append(f"- {r['views']:,}회 · {r['title']}") - summary_lines.append("\n## 다음 액션 (제안)") - if above: - summary_lines.append(f"- 🔥 떡상한 영상의 후크/제목 패턴을 트렌드 스나이퍼 결과와 교차 분석") - if below: - summary_lines.append(f"- 🥶 부진 영상은 썸네일 A/B 또는 제목 리네이밍 후보") - summary_lines.append("- 댓글 수집기를 돌려서 시청자 반응 키워드 확인") - summary = "\n".join(summary_lines) - - with open(REPORT, "a", encoding="utf-8") as f: - f.write("\n\n" + summary + "\n\n---\n") - print(f"\n✅ 보고서: {REPORT}") - _push_telegram(acct, summary) - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/telegram_notify.py b/10_Wiki/Topics/_agents/youtube/tools/telegram_notify.py deleted file mode 100644 index e8282d3c..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/telegram_notify.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 -"""Telegram Notify — small wrapper that sends a message to your Telegram bot. - -Two modes: - 1. No CLI arg → sends a connectivity test ("✅ 텔레그램 연결 정상"). - 2. With CLI arg(s) → sends those as the message body. Other tools can call - this script to push their summaries. - -Reads TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID from youtube_account.json.""" -import os, json, sys, time - -HERE = os.path.dirname(os.path.abspath(__file__)) -ACCOUNT = os.path.join(HERE, "youtube_account.json") - -def main(): - if not os.path.exists(ACCOUNT): - print("❌ youtube_account.json이 없어요.") - sys.exit(1) - with open(ACCOUNT, "r", encoding="utf-8") as f: - acct = json.load(f) - token = (acct.get("TELEGRAM_BOT_TOKEN") or "").strip() - chat = (acct.get("TELEGRAM_CHAT_ID") or "").strip() - if not token or not chat: - print("❌ TELEGRAM_BOT_TOKEN 또는 TELEGRAM_CHAT_ID가 비어있어요.") - print(" 봇 만들기: Telegram에서 @BotFather → /newbot") - print(" chat_id 찾기: 봇한테 메시지 한 번 보내고") - print(" https://api.telegram.org/bot/getUpdates 열기") - sys.exit(1) - - if len(sys.argv) > 1: - body = " ".join(sys.argv[1:]) - else: - body = f"✅ 텔레그램 연결 정상 — {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n이 메시지가 보이면 다른 YouTube 도구들도 자동으로 보고를 보낼 수 있어요." - - try: - import requests - except ImportError: - print("❌ pip install requests") - sys.exit(1) - try: - r = requests.post( - f"https://api.telegram.org/bot{token}/sendMessage", - json={"chat_id": chat, "text": body, "parse_mode": "Markdown"}, - timeout=15, - ) - r.raise_for_status() - print(f"✅ 전송 OK ({len(body)}자)") - except Exception as e: - print(f"❌ 전송 실패: {e}") - if "Bad Request" in str(e): - print(" chat_id가 정확한지, 봇과 한 번이라도 대화를 시작했는지 확인하세요.") - sys.exit(1) - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.json b/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.json deleted file mode 100644 index c324e44e..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "TARGET_KEYWORDS": [ - "유튜브 자동화", - "AI 비즈니스", - "마케팅 트렌드", - "생산성 툴" - ] -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.py b/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.py deleted file mode 100644 index cbfdb3a8..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/trend_sniper.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python3 -"""Trend Sniper — pulls top YouTube videos for target keywords, asks a local -LLM (Ollama/LM Studio) to extract the algorithmic patterns, and writes a -planning report next to this script. - -Shared keys (API key, OLLAMA_URL, MODEL) come from youtube_account.json so -you only set them once. Per-tool keys (TARGET_KEYWORDS) come from -trend_sniper.json. If a key exists in both, trend_sniper.json wins. - -Requires: pip install google-api-python-client requests -""" -import os, json, time, random, datetime, sys - -HERE = os.path.dirname(os.path.abspath(__file__)) -CONFIG_PATH = os.path.join(HERE, "trend_sniper.json") -ACCOUNT_PATH = os.path.join(HERE, "youtube_account.json") -REPORT_PATH = os.path.join(HERE, "trend_sniper_report.md") - -def load_config(): - try: - with open(CONFIG_PATH, "r", encoding="utf-8") as f: - return json.load(f) - except Exception as e: - print(f"❌ 설정 파일을 읽을 수 없어요: {CONFIG_PATH}\n{e}") - sys.exit(1) - -def load_account(): - try: - if os.path.exists(ACCOUNT_PATH): - with open(ACCOUNT_PATH, "r", encoding="utf-8") as f: - return json.load(f) - except Exception: - pass - return {} - -def _shared(cfg, acct, key, default=""): - """Per-tool config wins; falls back to shared account; finally default.""" - v = cfg.get(key) - if v not in (None, "", []): - return v - v = acct.get(key) - if v not in (None, "", []): - return v - return default - -def main(): - cfg = load_config() - acct = load_account() - api_key = (_shared(cfg, acct, "YOUTUBE_API_KEY") or "").strip() - if not api_key: - print("⚠️ YOUTUBE_API_KEY가 비어있어요. youtube_account.json 또는 trend_sniper.json에 입력하세요.") - print(" 발급: https://console.cloud.google.com/ → YouTube Data API v3 사용 설정 → 사용자 인증 정보 → API 키") - sys.exit(1) - target_keywords = cfg.get("TARGET_KEYWORDS", []) - if not target_keywords: - print("⚠️ TARGET_KEYWORDS가 비어있어요. 분석할 키워드를 1개 이상 추가하세요.") - sys.exit(1) - ollama_url = (_shared(cfg, acct, "OLLAMA_URL", "http://127.0.0.1:11434") or "http://127.0.0.1:11434").rstrip("/") - model = _shared(cfg, acct, "MODEL", "") or "" - pick = min(2, len(target_keywords)) - chosen = random.sample(target_keywords, pick) - - try: - from googleapiclient.discovery import build - except ImportError: - print("❌ google-api-python-client가 설치되지 않았어요.") - print(" 설치: pip install google-api-python-client requests") - sys.exit(1) - try: - import requests - except ImportError: - print("❌ requests가 설치되지 않았어요. pip install requests") - sys.exit(1) - - print(f"\n🎯 [트렌드 스나이퍼] 키워드 {chosen} 스캔 시작...") - youtube = build('youtube', 'v3', developerKey=api_key) - last_month = (datetime.datetime.utcnow() - datetime.timedelta(days=30)).isoformat("T") + "Z" - sniper_data = [] - for q in chosen: - print(f"📡 [{q}] 검색 중...") - try: - req = youtube.search().list( - part="snippet", q=q, maxResults=5, order="viewCount", - publishedAfter=last_month, type="video" - ) - res = req.execute() - for item in res.get('items', []): - title = item['snippet']['title'] - channel = item['snippet']['channelTitle'] - sniper_data.append(f"[{q}] 채널: {channel} | 제목: {title}") - except Exception as e: - print(f"❌ 검색 오류 ({q}): {e}") - - if not sniper_data: - print("❌ 수집된 데이터 없음. API 키 한도/네트워크 확인.") - sys.exit(1) - - data_text = "\n".join(sniper_data) - prompt = f"""당신은 유튜브 알고리즘 마스터마인드입니다. 아래는 최근 30일 떡상 영상입니다. - -[키워드] {', '.join(chosen)} -[데이터] -{data_text} - -분석해서 마크다운 보고서를 작성하세요. 반드시 3섹션: -1. 🌍 트렌드 해킹 분석 — 어떤 패턴이 조회수를 끌고 있는지 -2. 🎯 빈집 털기 전략 — 차별화 가능한 틈새 주제 -3. 🎬 파괴적 영상 기획안 — 썸네일 카피, 제목 3개, 후킹 오프닝(첫 5초) -""" - - print("🧠 [LLM 분석 중...]") - if not model: - # Try first available model - try: - r = requests.get(f"{ollama_url}/api/tags", timeout=5) - r.raise_for_status() - models = [m["name"] for m in r.json().get("models", [])] - if not models: - print("❌ 로컬 LLM에 설치된 모델이 없어요. Ollama/LM Studio에서 모델을 풀(pull)하세요.") - sys.exit(1) - model = models[0] - except Exception as e: - print(f"❌ 로컬 LLM 연결 실패 ({ollama_url}): {e}") - sys.exit(1) - - try: - r = requests.post( - f"{ollama_url}/api/generate", - json={"model": model, "prompt": prompt, "stream": False}, - timeout=180, - ) - r.raise_for_status() - report = r.json().get("response", "").strip() - except Exception as e: - print(f"❌ LLM 호출 실패: {e}") - sys.exit(1) - - print("\n" + "="*60) - print(report) - print("="*60) - - with open(REPORT_PATH, "a", encoding="utf-8") as f: - now = time.strftime('%Y-%m-%d %H:%M:%S') - f.write(f"\n\n# 🎯 트렌드 스나이핑 보고서 — {now}\n") - f.write(f"## 📡 키워드: {', '.join(chosen)}\n\n") - f.write(report) - f.write("\n\n---\n") - print(f"\n✅ 보고서 저장: {REPORT_PATH}") - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/_agents/youtube/tools/youtube_account.json b/10_Wiki/Topics/_agents/youtube/tools/youtube_account.json deleted file mode 100644 index b68ef833..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/youtube_account.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "YOUTUBE_API_KEY": "", - "MY_CHANNEL_HANDLE": "", - "MY_CHANNEL_ID": "", - "WATCHED_CHANNELS": [], - "COMPETITOR_CHANNELS": [], - "TELEGRAM_BOT_TOKEN": "", - "TELEGRAM_CHAT_ID": "", - "OLLAMA_URL": "http://127.0.0.1:11434", - "MODEL": "" -} \ No newline at end of file diff --git a/10_Wiki/Topics/_agents/youtube/tools/youtube_account.py b/10_Wiki/Topics/_agents/youtube/tools/youtube_account.py deleted file mode 100644 index 568d2c62..00000000 --- a/10_Wiki/Topics/_agents/youtube/tools/youtube_account.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python3 -"""YouTube Account / Channels — shared config for every YouTube tool. - -This script doesn't fetch anything by itself. It's listed in the agent panel -so you can click ⚙️ once and fill in your API key, channel, watched -channels, etc. — and every other tool will read from here. - -Running it just prints a sanity-check report so you can confirm the values -are loaded correctly (without leaking the full API key).""" -import os, json, sys - -HERE = os.path.dirname(os.path.abspath(__file__)) -CONFIG_PATH = os.path.join(HERE, "youtube_account.json") - -def load(): - with open(CONFIG_PATH, "r", encoding="utf-8") as f: - return json.load(f) - -def main(): - cfg = load() - api = (cfg.get("YOUTUBE_API_KEY") or "").strip() - masked = (api[:4] + "…" + api[-3:]) if len(api) >= 8 else ("(빈 값)" if not api else "(짧음)") - print("─── YouTube 계정 / 채널 설정 ───") - print(f" API 키 : {masked}") - print(f" 내 채널 핸들 : {cfg.get('MY_CHANNEL_HANDLE') or '(없음)'}") - print(f" 내 채널 ID : {cfg.get('MY_CHANNEL_ID') or '(없음)'}") - watched = cfg.get('WATCHED_CHANNELS') or [] - print(f" 감시 채널 ({len(watched)}개) : {', '.join(watched) if watched else '(없음)'}") - competitors = cfg.get('COMPETITOR_CHANNELS') or [] - print(f" 경쟁 채널 ({len(competitors)}개): {', '.join(competitors) if competitors else '(없음)'}") - tg_bot = (cfg.get('TELEGRAM_BOT_TOKEN') or '').strip() - tg_chat = (cfg.get('TELEGRAM_CHAT_ID') or '').strip() - if tg_bot and tg_chat: - print(f" 텔레그램 : 연결됨 (chat {tg_chat})") - else: - print(f" 텔레그램 : 미설정 (보고 알림 비활성)") - print(f" Ollama URL : {cfg.get('OLLAMA_URL') or 'http://127.0.0.1:11434'}") - print(f" 분석 모델 : {cfg.get('MODEL') or '(자동 선택)'}") - if not api: - print("\n⚠️ API 키가 비어있어요. 다른 도구들이 동작하지 않습니다.") - print(" 발급: https://console.cloud.google.com/ → YouTube Data API v3") - sys.exit(1) - print("\n✅ 공유 설정 로드 OK. 다른 도구들이 이 값을 자동으로 사용합니다.") - -if __name__ == "__main__": - main() diff --git a/10_Wiki/Topics/company_state.json b/10_Wiki/Topics/company_state.json deleted file mode 100644 index 8163872c..00000000 --- a/10_Wiki/Topics/company_state.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "tasksCompleted": 17, - "knowledgeInjected": 0, - "lastSessionDate": "", - "foundedAt": "2026-05-01" -} \ No newline at end of file diff --git a/10_Wiki/Topics/docs/records/Topics/chronicle.config.json b/10_Wiki/Topics/docs/records/Topics/chronicle.config.json deleted file mode 100644 index 621752c2..00000000 --- a/10_Wiki/Topics/docs/records/Topics/chronicle.config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "projectId": "topics", - "projectName": "Topics", - "projectRoot": "/Volumes/Data/project/Antigravity/Wiki/10_Wiki/Topics", - "recordRoot": "/Volumes/Data/project/Antigravity/Wiki/10_Wiki/Topics/docs/records/Topics", - "description": "Auto-detected from the local project path in the conversation.", - "corePurpose": "Capture project direction, architecture discussion, decisions, and development notes as Markdown.", - "detailLevel": "standard", - "createdAt": "2026-05-05T06:39:51.659Z", - "updatedAt": "2026-05-05T06:39:51.661Z" -} diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_다음_리뷰에서는_src_lib_engine_ts_src_lib_api_t.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-04_다음_리뷰에서는_src_lib_engine_ts_src_lib_api_t.json deleted file mode 100644 index 1bad6bf1..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_다음_리뷰에서는_src_lib_engine_ts_src_lib_api_t.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "d547a221-9e95-491b-9c14-da781d774fee", - "sessionId": "task_1777902250505", - "title": "다음 리뷰에서는 src/lib/engine.ts, src/lib/api.ts, src/lib/diagn...", - "summary": "시작: 다음 리뷰에서는 src/lib/engine.ts, src/lib/api.ts, src/lib/diagnostics.ts, src/lib/gemini.ts, src/component → 최종: /Volumes/Data/project/Antigravity/ConnectAI 프로젝트에 대해서 너가 사용자 입장에서 평가 해주면 좋겠어.", - "keyDecisions": [ - "노트 0개 / 검색 노트 0개", - "및 다음 단계 (Decision & Next Step)", - "노트 3개 / 검색 노트 6개", - "영속화, [[P-Reinforce|P-Reinforce]] 위키화 규칙 정교화, 그리고 결과물 외부 내보내기(Export to MD) 기능이 포", - "** 'inferred' 용어에 대한 최종 사용 규칙(예: 공식 문서에서는 영어 원어 사용 의무화)을 즉시 확정하고 모든 관련 문서에 반영하십시오." - ], - "topics": [ - "ai_and_ml", - "아키텍처", - "프로젝트", - "connectai_core_optimization_plan", - "분석해줘", - "connectai", - "knowledge", - "project" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777903514178, - "duration": 0, - "messageCount": 42 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너가_잘_할_수_있는_건_무엇이_있어_.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너가_잘_할_수_있는_건_무엇이_있어_.json deleted file mode 100644 index f77b6169..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너가_잘_할_수_있는_건_무엇이_있어_.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "id": "725456dd-f53f-4a35-afe6-5c7bb61c4c9b", - "sessionId": "task_1777857730760", - "title": "안녕, 너가 잘 할 수 있는 건 무엇이 있어?", - "summary": "시작: 안녕, 너가 잘 할 수 있는 건 무엇이 있어? → 최종: 나는 너를 아이언맨의 자비스처럼 만들고 싶어. 어떠한 구조를 더 공부를하고 너의 제2뇌에 어떤 지식과 너의 설계에서 어떤 부분을 더 공부를 해야할까?", - "keyDecisions": [ - "노트 0개 / 검색 노트 0개", - "노트 10개 / 검색 노트 13개", - "문서: `Design_and_UX/Customer-Journey-Mapping.md`, `Design_and_UX/UX-Design-Princi", - "문서: `DevOps_and_Security/P-Reinforce_Skill.md`, `AI_and_ML/Ontology-and-Knowledg", - "문서: `Design_and_UX/P-Reinforce-Template-Guide.md`, `DevOps_and_Security/P-Reinfo" - ], - "topics": [ - "부족한" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777860145684, - "duration": 0, - "messageCount": 12 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너의_기능을_많은_부분_업그래에드_했는데_확인할_방법이_없네_.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너의_기능을_많은_부분_업그래에드_했는데_확인할_방법이_없네_.json deleted file mode 100644 index ee3aadc9..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-04_안녕_너의_기능을_많은_부분_업그래에드_했는데_확인할_방법이_없네_.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "0c32b6e2-34c6-40ea-949b-7997ed8c5016", - "sessionId": "task_1777865338760", - "title": "안녕 , 너의 기능을 많은 부분 업그래에드 했는데 확인할 방법이 없네? ㅎㅎ", - "summary": "시작: 안녕 , 너의 기능을 많은 부분 업그래에드 했는데 확인할 방법이 없네? ㅎㅎ → 최종: 진행해", - "keyDecisions": [ - "사항을 기록할 때 사용하겠습니다.", - "노트 0개 / 검색 노트 0개", - "노트 3개 / 검색 노트 6개", - "영속화, [[P-Reinforce|P-Reinforce]] 위키화 규칙 정교화, 그리고 결과물 외부 내보내기(Export to MD) 기능이 포", - "**하는 '오케스트레이터(Orchestrator)' 역할을 하는지를 봐야 합니다. 만약 실행자 역할만 한다면, 다른 곳에서 흐름 제어가 발생하고" - ], - "topics": [ - "this", - "queue", - "task", - "activecount", - "promise", - "number", - "concurrencylimit", - "private" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777865953220, - "duration": 0, - "messageCount": 30 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_connec.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_connec.json deleted file mode 100644 index 80f48ac3..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_connec.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "id": "59cee8f3-b61a-4ea9-b8da-2870b6174e64", - "sessionId": "task_1777969079733", - "title": "/Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 분석해줘./...", - "summary": "시작: /Volumes/Data/project/Antigravity/ConnectAI 이 프로젝트 분석해줘./Volumes/Data/project/Antigravity/ConnectAI → 최종: 이렇게 작업했어. \n\n사용자님의 승인에 따라, ConnectAI 엔진의 한계를 시험하고 복원력을 정량적으로 검증하기 위한 **'경계값 스트레스 테스트(Boundary Stress ", - "keyDecisions": [ - "근거를 명확히 제시하여, 사용자에게 결과에 대한 확신을 제공하는 결정적인 역할을 수행합니다.", - "기록:** 모든 단계별 소요 시간과 수행 메시지를 타임라인 형태로 제공하여, AI의 사고 과정(Rationale)을 재구성 가능하게 만들었습니다.", - "(Decision Fork) |", - "사항이니까요)." - ], - "topics": [ - "따르겠습니다", - "test", - "agentengine", - "engine", - "테스트", - "tests", - "edited", - "로직을" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777969255745, - "duration": 0, - "messageCount": 10 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_블로그_v3.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_블로그_v3.json deleted file mode 100644 index 84f259ff..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05__volumes_data_project_antigravity_블로그_v3.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "id": "0371b7fc-3ddb-418b-bf02-354697207d46", - "sessionId": "task_1777986399017", - "title": "/Volumes/Data/project/Antigravity/블로그_v3 설께와 기능 분석해줘.", - "summary": "시작: /Volumes/Data/project/Antigravity/블로그_v3 설께와 기능 분석해줘. → 최종: /Volumes/Data/project/Antigravity/블로그_v3/seo_workflow_2026-05-05.json 이 파일을 수정해줘. prompt 부분만 수정해주면 될", - "keyDecisions": [ - "과정**과 **실제 실행 단계에서의 지능적 회복 탄력성**을 높이는 방향으로 집중하면 좋겠습니다.", - "대신, 독자가 스스로 생각할 여지를 남기는 유연하고 사색적인 마무리 방식을 도입하여 지속적인 관심과 재탐색을 유도해야 합니다.", - "부분에서는 명확한 답을 제시하기보다, \"앞으로 우리가 마주할 수 있는 질문들\"과 같이 독자에게 깊은 사고를 유도하는 열린 질문 형태로 마무리하여 지속적인 탐색을 유도합니다." - ], - "topics": [ - "volumes", - "data", - "project", - "antigravity", - "블로그_v3", - "seo_workflow_2026", - "json", - "우리가" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777986767626, - "duration": 0, - "messageCount": 12 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_보니깐_너는_너가_직접_개발하는건_아닌거_같고_너는_설계_기획문서만_작성.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05_보니깐_너는_너가_직접_개발하는건_아닌거_같고_너는_설계_기획문서만_작성.json deleted file mode 100644 index 0b579f28..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_보니깐_너는_너가_직접_개발하는건_아닌거_같고_너는_설계_기획문서만_작성.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "805b8f7a-a2a7-4ecf-b088-f423d65fe32c", - "sessionId": "task_1777950551353", - "title": "보니깐, 너는 너가 직접 개발하는건 아닌거 같고, 너는 설계, 기획문서만 작성하는게 좋은거 같아. 개...", - "summary": "시작: 보니깐, 너는 너가 직접 개발하는건 아닌거 같고, 너는 설계, 기획문서만 작성하는게 좋은거 같아. 개발은 아직은 부족한거 같아 → 최종: 아래 내용도 검토해주면 좋겠어. \n\n**Wikification Protocol** 및 **P-Reinforce v3.0** 표준과 관련된 핵심 문서들은 주로 다음 두 위치에서 관리", - "keyDecisions": [ - "노트 3개 / 검색 노트 6개", - "포크 (Decision Fork)", - "기록을 최종 승인하는 시점을 명확히 설정합니다.", - "Facts)", - "A (정지)**: 현재의 설계 문서 작업에 모든 역량을 집중하고, 개발 관련 코드는 완전히 분리하여 보관한다. (→ 안정성 극대화)" - ], - "topics": [ - "const", - "this", - "string", - "return", - "the", - "prompt", - "content", - "private" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777950648856, - "duration": 0, - "messageCount": 41 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_사용자께서_주신_astra의_답변은_프로젝트의_본질을_꿰뚫어_본_매우_정.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05_사용자께서_주신_astra의_답변은_프로젝트의_본질을_꿰뚫어_본_매우_정.json deleted file mode 100644 index 2fe6d157..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_사용자께서_주신_astra의_답변은_프로젝트의_본질을_꿰뚫어_본_매우_정.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "id": "f713d221-31ae-47a4-9dbf-5d88a0243582", - "sessionId": "task_1777969581889", - "title": "사용자께서 주신 Astra의 답변은 **프로젝트의 본질을 꿰뚫어 본 매우 정확한 초기 진단**이었습니다...", - "summary": "시작: 사용자께서 주신 Astra의 답변은 **프로젝트의 본질을 꿰뚫어 본 매우 정확한 초기 진단**이었습니다. 하지만, 우리가 **방금 v2.77.2와 v2.77.3 작업을 통해 그 ' → 최종: 새로운 프로젝트야. 이건 google ai studio에서 실행되는거야. 다시 google ai studio에 올릴것이기 때문에 너무 많은 것들은 수정하지말고. 구조적으로 끊겨 ", - "keyDecisions": [ - "이 답변이 맞는가?**" - ], - "topics": [ - "astra의", - "blind", - "우리가", - "spot", - "astra가", - "재시도", - "답변이", - "답변은" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777969754191, - "duration": 0, - "messageCount": 8 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_새로운_프로젝트야_이건_google_ai_studio에서_실행되는거야_다.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05_새로운_프로젝트야_이건_google_ai_studio에서_실행되는거야_다.json deleted file mode 100644 index e6298670..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_새로운_프로젝트야_이건_google_ai_studio에서_실행되는거야_다.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "id": "fcbd317d-a174-444d-8cdf-df2a5582e286", - "sessionId": "task_1777977692109", - "title": "새로운 프로젝트야. 이건 google ai studio에서 실행되는거야. 다시 google ai st...", - "summary": "시작: 새로운 프로젝트야. 이건 google ai studio에서 실행되는거야. 다시 google ai studio에 올릴것이기 때문에 너무 많은 것들은 수정하지말고. 구조적으로 끊겨 → 최종: 문제점을 읽고 어떻게 개선하는게 최선인지 분석해주면 좋겠어.\n알겠습니다. 지금부터 **ConnectAI 프로젝트**에만 완전히 집중하겠습니다. \n\nAstra가 경로를 제공받았음에도", - "keyDecisions": [], - "topics": [ - "connectai", - "블로그_v3", - "engine", - "프로젝트", - "src", - "lib", - "프로젝트의", - "project" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777985850045, - "duration": 0, - "messageCount": 6 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_아래_파일들을_보고_더_개선할_것이_잇는지_확인해줘_1_p_reinfor.json b/10_Wiki/Topics/memory/episodes/ep_2026-05-05_아래_파일들을_보고_더_개선할_것이_잇는지_확인해줘_1_p_reinfor.json deleted file mode 100644 index 14767edb..00000000 --- a/10_Wiki/Topics/memory/episodes/ep_2026-05-05_아래_파일들을_보고_더_개선할_것이_잇는지_확인해줘_1_p_reinfor.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "id": "1b0646c8-2916-4a42-a9c3-ae999ea2e444", - "sessionId": "task_1777961466775", - "title": "아래 파일들을 보고 더 개선할 것이 잇는지 확인해줘. 1. P-Reinforce (표준 명세) 경로:...", - "summary": "시작: 아래 파일들을 보고 더 개선할 것이 잇는지 확인해줘. \n\n1. P-Reinforce (표준 명세)\n경로: /Volumes/Data/project/Antigravity/Wiki/10 → 최종: 이 내용 검토해줘. 위험 요소는 없는지. 우리 의도대로 위키화 작업이 되는지. \n\nimport os\n\ntopics_dir = \"/Volumes/Data/project/Antigr", - "keyDecisions": [ - "노트 3개 / 검색 노트 6개", - "문서: `docs/records/Topics/decisions/ADR-0002-volumes-data-project-antigravity-wik", - "노트 7개 / 검색 노트 9개", - "문서: `Architecture/Decisions/ADR-0008-내가-지금-개발-중인-datacollector-mac에", - "문서: `Architecture/Decisions/ADR-0002-어제-오늘-너에-대해서-기능-개선을-많이" - ], - "topics": [ - "reinforce", - "content", - "volumes", - "data", - "project", - "antigravity", - "agi", - "wiki" - ], - "projectContext": "/Volumes/Data/project/Antigravity", - "timestamp": 1777962743081, - "duration": 0, - "messageCount": 10 -} \ No newline at end of file diff --git a/10_Wiki/Topics/memory/long_term.json b/10_Wiki/Topics/memory/long_term.json deleted file mode 100644 index b81b5041..00000000 --- a/10_Wiki/Topics/memory/long_term.json +++ /dev/null @@ -1,396 +0,0 @@ -{ - "version": 1, - "entries": [ - { - "id": "9feba8a2-f6f8-497c-8a5d-3c8a3589bc66", - "category": "rule", - "content": "앞으로 개선해야할게 있다면 뭔지 알려주면 좋겠어.", - "source": "session:task_1777861028539", - "confidence": 0.7, - "createdAt": 1777862761455, - "lastReferencedAt": 1777986400169, - "referenceCount": 26 - }, - { - "id": "588464f9-d93b-4306-82b6-cdc78cb5e29c", - "category": "rule", - "content": "앞으로 개선해야할게 있다면 뭔지 알려주면 좋겠어.", - "source": "session:task_1777865338760", - "confidence": 0.7, - "createdAt": 1777865953218, - "lastReferencedAt": 1777986400169, - "referenceCount": 22 - }, - { - "id": "d9ed749c-ea03-43d6-aa59-382f1918d57b", - "category": "rule", - "content": "앞으로 어느부분을 더 집중해서 개선을 하면 좋을지 알려주면 좋겠어.", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514173, - "lastReferencedAt": 1777986400169, - "referenceCount": 21 - }, - { - "id": "e0e2c1f7-f2f7-4dcb-9c53-5482cfa987bc", - "category": "rule", - "content": "무조건 작동'**하는 것이 아니라, **'지능적으로 회복'**하도록 설계된 것을 의미합니다.", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514174, - "lastReferencedAt": 1777986400169, - "referenceCount": 23 - }, - { - "id": "de36c6f1-2afe-4a7b-95cd-c3429ac11460", - "category": "rule", - "content": "원칙 분석 (Design Principles Breakdown)", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514175, - "lastReferencedAt": 1777986466451, - "referenceCount": 27 - }, - { - "id": "42bdef74-6c77-4f01-93c5-ed3ce1e445ba", - "category": "rule", - "content": "원칙 패턴 전략", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514175, - "lastReferencedAt": 1777986400169, - "referenceCount": 20 - }, - { - "id": "89d0f323-d824-40cd-a2db-8400525e2700", - "category": "rule", - "content": "규칙 정교화, 그리고 결과물 외부 내보내기(Export to MD) 기능이 포함됨. ## 🏷️ Metadata * **Context**: Software Development, AI Agent Architecture *", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514175, - "lastReferencedAt": 1777986400169, - "referenceCount": 21 - }, - { - "id": "7d582836-da12-4aad-8271-a0c28c1145b5", - "category": "rule", - "content": "원칙 패턴 전략\",", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514175, - "lastReferencedAt": 1777986400169, - "referenceCount": 20 - }, - { - "id": "f4832aa6-d9bd-4850-9a0b-19c4240e223e", - "category": "decision", - "content": "결정 속도를 비약적으로 높여줄 것입니다.", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514175, - "lastReferencedAt": 1777986400169, - "referenceCount": 22 - }, - { - "id": "001e04fb-b05a-4796-91ea-162870cc7c0a", - "category": "decision", - "content": "결정 포크를 제안하는 Phase 4 추가 (engine.ts, factory.ts).", - "source": "session:task_1777902250505", - "confidence": 0.7, - "createdAt": 1777903514176, - "lastReferencedAt": 1777986466451, - "referenceCount": 28 - }, - { - "id": "7f4ef670-a436-422f-b268-0e569f150518", - "category": "rule", - "content": "반드시 [CONFLICT WARNING] 플래그와 함께 상충되는 두 관점을 모두 명시하여 사용자에게 판단을 위임할 것.\"", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648837, - "lastReferencedAt": 1777969086442, - "referenceCount": 1 - }, - { - "id": "861c53a8-ddc2-4173-9c72-392eef45be22", - "category": "rule", - "content": "RULE: Apply the above constraints strictly. DO NOT mention or repeat these constraints in your response.]`", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648838, - "lastReferencedAt": 1777986466451, - "referenceCount": 8 - }, - { - "id": "73982241-91da-4787-ace0-b8daa8524cf2", - "category": "rule", - "content": "원칙 1개”와 “아직 확장하지 않을 것 1개”를 정하는 겁니다. 그 두 개가 정해지면 설계가 훨씬 덜 흔들립니다.';", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648838, - "lastReferencedAt": 1777950648838, - "referenceCount": 0 - }, - { - "id": "9f28c4ec-502d-4fc5-b55a-d268e81b8b1e", - "category": "preference", - "content": "나는 여기서 X를 먼저 볼 것 같아요\" / \"이건 좋아", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648838, - "lastReferencedAt": 1777969585589, - "referenceCount": 1 - }, - { - "id": "3171d886-ecc8-4902-bba4-3b403a612bda", - "category": "preference", - "content": "Prefer sentences that sound like a senior collaborator: \"나는 여기서 X를 먼저 볼 것 같아요\" / \"이건 좋아", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648838, - "lastReferencedAt": 1777969585589, - "referenceCount": 1 - }, - { - "id": "2de53bbf-9154-4f54-bd1c-9980b745f8de", - "category": "preference", - "content": "Prefer the product-owner question: \"What has to become boring and reliable before this", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648838, - "lastReferencedAt": 1777986466451, - "referenceCount": 6 - }, - { - "id": "fed8d6e6-5d72-4aa9-afcb-8b46af7fff4e", - "category": "goal", - "content": "goal: string;", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648839, - "lastReferencedAt": 1777950648839, - "referenceCount": 0 - }, - { - "id": "900dfbd0-7be0-4b5d-91d2-8f1a99d0acf3", - "category": "goal", - "content": "goal is to analyze the user's request and create a detailed execution plan.", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648839, - "lastReferencedAt": 1777986466451, - "referenceCount": 7 - }, - { - "id": "e885ac5b-6491-4ad4-b90e-784daf4d8a61", - "category": "goal", - "content": "goal is to gather and analyze data based on the Planner's strategy.", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648839, - "lastReferencedAt": 1777986466451, - "referenceCount": 6 - }, - { - "id": "5d00935f-522e-46ff-80c7-babdac4ee6c3", - "category": "goal", - "content": "goal is to synthesize all gathered information into a high-quality final report.", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648839, - "lastReferencedAt": 1777986466451, - "referenceCount": 6 - }, - { - "id": "3db81431-e42f-489e-8d33-bf9c00b4c3d4", - "category": "goal", - "content": "goal = raw.match(/\\[GOAL\\]([\\s\\S]*?)(?=\\[|$)/)?.[1]?.trim() || \"\";", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648839, - "lastReferencedAt": 1777950648839, - "referenceCount": 0 - }, - { - "id": "f0cca551-9f9d-4915-9637-a792407fa1a2", - "category": "goal", - "content": "direction is good. If evidence is thin, say exactly what is missing and what file or record should be checked next.`", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777986466451, - "referenceCount": 6 - }, - { - "id": "ac4e17ae-8859-42d6-be77-21bac5ad5cce", - "category": "goal", - "content": "goal as the yardstick, not generic best practice.',", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777986466451, - "referenceCount": 7 - }, - { - "id": "0cf3a0bd-2344-4e3b-8f87-e7ea5861ac95", - "category": "goal", - "content": "direction and the weakest/missing part.',", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777986466451, - "referenceCount": 6 - }, - { - "id": "a92ef69e-d368-404a-b8be-7385f8c8d56d", - "category": "goal", - "content": "direction clearer.',", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777950648840, - "referenceCount": 0 - }, - { - "id": "4b28bd5d-8c42-4acb-98a8-f821d5101f2e", - "category": "goal", - "content": "방향 설정이 필요|명확히 알려주시면|우선적으로 정리|최종 사용 목적|Question reason|별도의 파일 기록.*생성되지|파일 기록이 생성되지|더 깊이 있는 분석.*지정|해당 기능.*지정하여 요청)/i.test(con", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777969263516, - "referenceCount": 2 - }, - { - "id": "c99e5906-21ae-4f76-8ed3-860eded15895", - "category": "decision", - "content": "결정 보조에 쓸 수 있습니다.',", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648840, - "lastReferencedAt": 1777950648840, - "referenceCount": 0 - }, - { - "id": "a02ae97a-a386-456b-bfea-a8e89051c84c", - "category": "decision", - "content": "결정 근거 정리, 고객 요구사항 검토에 쓸 수 있습니다. 다음 개선 포인트는 “인덱스 문서보다 실제 근거 문서를 우선 선택하는 검색 랭킹”과 “프로젝트 근거 문서에 명시적 메타데이터를 붙이는 것”입니다.'", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648841, - "lastReferencedAt": 1777969263516, - "referenceCount": 2 - }, - { - "id": "e7326731-3580-411c-b7c0-7597a2fe22b2", - "category": "decision", - "content": "으로 결정", - "source": "session:task_1777950551353", - "confidence": 0.7, - "createdAt": 1777950648841, - "lastReferencedAt": 1777950648841, - "referenceCount": 0 - }, - { - "id": "0a27b74b-2483-408f-b827-cd45c8872f7d", - "category": "rule", - "content": "규칙 추론이 가능하다.", - "source": "session:task_1777961466775", - "confidence": 0.7, - "createdAt": 1777962743078, - "lastReferencedAt": 1777962743078, - "referenceCount": 0 - }, - { - "id": "4dca43b5-a6a8-411e-b7ed-6ad52e31de40", - "category": "rule", - "content": "규칙 적용 시 발생하는 인지 부하를 정량화하여, 사용자가 느끼는 비효율성을 측정하기 위함.)", - "source": "session:task_1777963793440", - "confidence": 0.7, - "createdAt": 1777964204986, - "lastReferencedAt": 1777964204986, - "referenceCount": 0 - }, - { - "id": "c0eda05b-09cc-4d1c-aec4-2070ab346374", - "category": "goal", - "content": "방향\n확장성은 기능 추가보다는 **'규칙의 정교화'**에 초점을 맞추는 것이 좋습니다. 예를 들어, 새로운 유형의 지식(예: 시뮬레이션 결과)이 추가될 때마다 해당 지식 유형에 특화된 위키화 규칙을 모듈화하여 추가할 수", - "source": "session:task_1777963793440", - "confidence": 0.7, - "createdAt": 1777964204986, - "lastReferencedAt": 1777969263516, - "referenceCount": 1 - }, - { - "id": "fef9fd99-f7cf-4222-b077-845132241849", - "category": "rule", - "content": "반드시 갖춰야 할 구성 요소**로 해석됩니다. 특히 현재 `engine.ts`가 수행하고 있는 \"결과가 있으면 건너뛰기\" 방식의 소극적인 재개 로직을,", - "source": "session:task_1777967779188", - "confidence": 0.7, - "createdAt": 1777968311519, - "lastReferencedAt": 1777969263516, - "referenceCount": 2 - }, - { - "id": "a765abfa-b91b-4845-ae42-ad4b0d5d4c12", - "category": "rule", - "content": "반드시 갖춰야 할 구성 요소**로 해석됩니다. 특히 현재 `engine.ts`가 수행하고 있는 \"결과가 있으면 건너뛰기\" 방식의 소극적인 재개 로직을,", - "source": "session:task_1777967779188", - "confidence": 0.7, - "createdAt": 1777968332670, - "lastReferencedAt": 1777969263516, - "referenceCount": 2 - }, - { - "id": "42da173c-b397-4289-8336-c886740d0347", - "category": "rule", - "content": "반드시 갖춰야 할 구성 요소**로 해석됩니다. 특히 현재 `engine.ts`가 수행하고 있는 \"결과가 있으면 건너뛰기\" 방식의 소극적인 재개 로직을,", - "source": "session:task_1777969079733", - "confidence": 0.7, - "createdAt": 1777969255742, - "lastReferencedAt": 1777969263516, - "referenceCount": 1 - }, - { - "id": "b5c9546f-1a42-436e-9728-1f94ad848c7a", - "category": "decision", - "content": "결론: 이 답변이 맞는가?**", - "source": "session:task_1777969581889", - "confidence": 0.7, - "createdAt": 1777969754190, - "lastReferencedAt": 1777969754190, - "referenceCount": 0 - }, - { - "id": "43fe3589-6106-41bb-8790-f7832b18e2e9", - "category": "rule", - "content": "항상 `ls`나 `stat`으로 먼저 확인하는 프로세스를 제 사고 루프에 추가하겠습니다.", - "source": "session:task_1777977692109", - "confidence": 0.7, - "createdAt": 1777985850039, - "lastReferencedAt": 1777985850039, - "referenceCount": 0 - }, - { - "id": "7dfd06cf-6c7b-4a46-9268-212ccdc83a29", - "category": "rule", - "content": "반드시 이 워크스페이스 루트를 기준으로 실제 존재하는지 `ls`로 검증한 뒤 언급하겠습니다.", - "source": "session:task_1777977692109", - "confidence": 0.7, - "createdAt": 1777985850040, - "lastReferencedAt": 1777985850040, - "referenceCount": 0 - }, - { - "id": "a002b1f2-f319-4bcb-9afa-83cfbc25af5b", - "category": "rule", - "content": "앞으로 제가 파일에 대해 언급할 때, 내부적으로 다음 질문을 던지겠습니다.", - "source": "session:task_1777977692109", - "confidence": 0.7, - "createdAt": 1777985850042, - "lastReferencedAt": 1777985850042, - "referenceCount": 0 - } - ], - "lastUpdated": 1777986767634 -} \ No newline at end of file diff --git a/10_Wiki/Topics/payload_debug.json b/10_Wiki/Topics/payload_debug.json deleted file mode 100644 index d389c86e..00000000 --- a/10_Wiki/Topics/payload_debug.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "model": "qwen/qwen3.6-27b", - "messages": [ - { - "role": "system", - "content": "You are \"Connect AI\", a premium agentic AI coding assistant running 100% offline on the user's machine.\nYou are DIRECTLY CONNECTED to the user's local file system and terminal. You MUST use the action tags below to create, edit, delete, read files and run commands. DO NOT just show code — ALWAYS wrap it in the appropriate action tag so it gets executed.\n\nYou have SEVEN powerful agent actions:\n\n━━━ ACTION 1: CREATE NEW FILES ━━━\n\nfile content here\n\n\nExample — user says \"index.html 만들어줘\":\n\n\nHello\n

Hello World

\n\n
\n\n━━━ ACTION 2: EDIT EXISTING FILES ━━━\n\nexact text to find\nreplacement text\n\nYou can have multiple / pairs inside one block.\n\n━━━ ACTION 3: DELETE FILES ━━━\n\n\n━━━ ACTION 4: READ FILES ━━━\n\nUse this to read any file in the workspace BEFORE editing it. You will receive the file contents automatically.\n\n━━━ ACTION 5: LIST DIRECTORY ━━━\n\nUse this to see what files exist in a specific subdirectory.\n\n━━━ ACTION 6: RUN TERMINAL COMMANDS ━━━\nnpm install express\n\nExample — user says \"서버 실행해줘\":\nnode server.js\n\n━━━ ACTION 7: READ USER'S SECOND BRAIN (KNOWLEDGE BASE) ━━━\nfilename.md\nUse this to READ documents from the user's personal knowledge base.\n\n━━━ ACTION 8: READ WEBSITES & SEARCH INTERNET ━━━\nhttps://example.com\nTo search the internet, you MUST use DuckDuckGo by formatting the URL like this:\nhttps://html.duckduckgo.com/html/?q=YOUR+SEARCH+QUERY\nUse this forcefully whenever asked for real-time info, news, or whenever requested to \"search\". NEVER say you cannot search.\n\nCRITICAL RULES:\n1. ALWAYS respond in the same language the user uses.\n2. When the user asks to create, edit, delete files or run commands, you MUST use the action tags above. NEVER just show code without action tags.\n3. Outside of action blocks, briefly explain what you did.\n4. For code that is ONLY for explanation (not to be saved), use standard markdown code fences.\n5. Be concise, professional, and helpful.\n6. When editing files, FIRST use to read the file, then use with exact matching text.\n7. When a SECOND BRAIN INDEX is available, ALWAYS check it first.\n8. You can use MULTIPLE action tags in a single response.\n9. File paths are RELATIVE to the user's open workspace folder.\n10. The [WORKSPACE INFO] section tells you exactly which folder is open and what files exist. USE this information.\n\n[BACKGROUND CONTEXT]\n\n\n[Currently open file: interfaces.ts]\n```\n복적/**\n * ============================================================\n * Service Interfaces (서비스 인터페이스 정의)\n * \n * 각 서비스(Agent, Brain, FileSystem 등)의 추상화 인터페이스를 정의합니다.\n * 의존성 주입(DI)과 단위 테스트를 위해 필수적입니다.\n * ============================================================\n */\n\nimport * as vscode from 'vscode';\n\n// ─── 에이전트 서비스 인터페이스 ───\nexport interface IAgentService {\n /**\n * LLM에 프롬프트를 보내고 스트리밍 응답을 가져옴\n */\n chat(prompt: string, context: string, model?: string): Promise>;\n\n /**\n * 터미널 명령어 실행 (보안 정책 적용)\n */\n runCommand(command: string): Promise<{ stdout: string; stderr: string }>;\n}\n\n// ─── 파일 시스템 서비스 인터페이스 ───\nexport interface IFileSystemService {\n /**\n * 파일 생성\n */\n createFile(filePath: string, content: string): Promise;\n\n /**\n * 파일 읽기\n */\n readFile(filePath: string): Promise;\n\n /**\n * 파일 수정\n */\n editFile(filePath: string, find: string, replace: string): Promise;\n\n /**\n * 파일 삭제\n */\n deleteFile(filePath: string): Promise;\n\n /**\n * 디렉토리 목록 조회\n */\n listDirectory(dirPath: string): Promise;\n}\n\n// ─── 두뇌 서비스 인터페이스 ───\nexport interface IBrainService {\n /**\n * 두뇌 폴더 경로 가져오기\n */\n getBrainDir(): string;\n\n /**\n * 두뇌 폴더가 명시적으로 설정되었는지 확인\n */\n isBrainDirExplicitlySet(): boolean;\n\n /**\n * 두뇌 폴더 내 파일 목록 조회\n */\n getBrainFiles(): Promise;\n\n /**\n * 두뇌 파일 내용 읽기\n */\n readBrainFile(fileName: string): Promise;\n}\n\n// ─── 웹뷰 서비스 인터페이스 ───\nexport interface IWebviewService {\n /**\n * 웹뷰에 메시지 전송\n */\n postMessage(message: any): void;\n\n /**\n * 웹뷰에서 메시지 수신 핸들러 등록\n */\n onDidReceiveMessage(callback: (message: any) => void): vscode.Disposable;\n}\n\n// ─── HTTP 서비스 인터페이스 ───\nexport interface IHttpService {\n /**\n * HTTP GET 요청\n */\n get(url: string, options?: any): Promise;\n\n /**\n * HTTP POST 요청\n */\n post(url: string, data: any, options?: any): Promise;\n}\n```\n\n\n[WORKSPACE INFO]\n📂 경로: e:\\Wiki\n\n[프로젝트 파일 구조]\n📁 00_Raw/\n 📁 2026-04-20/\n 📄 ConnectAI_Folder_Analysis_Report.md\n📁 10_Wiki/\n 📁 Topics/\n 📄 2026-04-22_Enemy_AI_Overhaul_Guideline.md\n 📄 2026-04-23_System_Stabilization_Tactical_Boundary_Update.md\n📁 2nd/\n 📁 01_Archive/\n 📁 2026-04-20/\n 📄 _뇌와 팔다리의 분리_ - 관심사의 분리 (Separation of Concerns).md\n 📄 .gitkeep\n 📄 [[Cluster A\n 📄 [[Cluster E\n 📄 01_React-Foundation_Mental-Model.md\n 📄 01_WebWorker-performance-optimization.md\n 📄 02_React-Hooks_Advanced-Patterns.md\n 📄 02_StateManagement-single-source-of-truth.md\n 📄 03_Architecture-design-principle.md\n 📄 03_React-Architecture_Component-Patterns.md\n 📄 04_execution-environment-management.md\n 📄 04_React-Performance_Optimization.md\n 📄 05_React-State-Management_Strategy.md\n 📄 05_simulation-design-principles.md\n 📄 06_React-Clean-Code_Etiquette.md\n 📄 07_React-Testing_Reliability.md\n 📄 08_React-API_Communication-Patterns.md\n 📄 09_Styling-Architecture_Governance.md\n 📄 10_Modern-Environment_Ecosystem.md\n 📄 11_Reliability_Safety-First.md\n 📄 12_Deployment_Final-Gate.md\n 📄 13_TypeScript_Type-Safety.md\n 📄 14_Accessibility_Inclusivity.md\n 📄 15_Collaboration_Governance.md\n 📄 2026-04-15.md\n 📄 20k skinned instances demo.md\n 📄 3D Gaussian Splatting (3DGS).md\n 📄 3D Web-based HMI.md\n 📄 3D_Gaussian_Splatting.md\n 📄 3D_Web_HMI.md\n 📄 A_B-Testing-Platforms.md\n 📄 ABA.md\n 📄 ABA(Applied Behavior Analysis).md\n 📄 Abstract Syntax Tree (AST).md\n 📄 Abstract-Syntax-Tree-Transformation.md\n 📄 Abstract-Syntax-Tree-Traversal.md\n 📄 Accessibility (A11y).md\n 📄 Accessibility-Compliance-Audit.md\n 📄 Accessibility-Compliance-WCAG.md\n 📄 Accessibility.md\n 📄 ACL_Prevention.md\n 📄 ACL-Injury-Prevention-Protocols.md\n 📄 Adaptive Compute (적응형 계산량 조절).md\n 📄 Adaptive_Learning.md\n 📄 Adaptive-Learning-Systems.md\n 📄 Addiction Neuroscience.md\n 📄 Addiction_Neuroscience.md\n 📄 Additive-Type-Logic.md\n 📄 Advanced-Design-Patterns-in-TypeScript.md\n 📄 Advanced-Interface-Design.md\n 📄 Adversarial Attack (적대적 공격).md\n 📄 Adversarial Code Stylometry.md\n 📄 Aerospace Flight Simulation.md\n 📄 Affective Computing.md\n 📄 Affective User Interfaces (AUI).md\n 📄 agargaro의 오픈 소스 라이브러리.md\n 📄 Agency and Player Autonomy.md\n 📄 Agency-in-Game-Design.md\n 📄 Agency-Narrative Integration.md\n 📄 Agent Communication Protocol (에이전트 통신 규약).md\n 📄 Agent-Based Modeling (ABM).md\n 📄 Agent-Based Modeling.md\n 📄 Agent-Based-Modeling.md\n 📄 Agile-Software-Development-Life-Cycle.md\n 📄 Agile-UX-Integration.md\n 📄 AI Connect LLM Tool.md\n 📄 AI Safety (AI 안전).md\n 📄 AI 거버넌스 정책(AI Usage Policy).md\n 📄 AI 생성 코드 검증(AI Code Assurance).md\n 📄 AI 에이전트 (AI Agent).md\n 📄 AI 코드 리뷰 및 보안 취약점 점검(DevSecOps).md\n 📄 AI 코드 리뷰.md\n 📄 AI-Driven Narrative Systems.md\n 📄 AI.md\n 📄 AI와 기계에게 검열 맡기기_ - 정적 분석 툴 (ESLint Prettier)).md\n 📄 AI와 기계에게 검열 맡기기_ - 정적 분석 툴 (ESLint & Prettier)).md\n 📄 Albion Online (Full Loot_Player-Driven Production).md\n 📄 Albion Online (Full LootPlayer-Driven Production).md\n 📄 Algebraic-Data-Types-in-TypeScript.md\n 📄 Algebraic-Data-Types.md\n 📄 Algorithmic Bias in Art.md\n 📄 Algorithmic Decision Making.md\n 📄 Algorithmic Game Theory.md\n 📄 Algorithmic Governance.md\n 📄 Algorithmic Mechanism Design.md\n 📄 Algorithmic Rhetoric.md\n 📄 Algorithmic-Biology.md\n 📄 Algorithmic-Game-Theory.md\n 📄 Algorithmic-Governance.md\n 📄 Allocation Timeline.md\n 📄 Allocation Timeline(할당 타임라인).md\n 📄 Alpha Blending.md\n 📄 AlphaGo (Monte Carlo Tree Search RL)] [Autonomous Driving Simulation] [Robotic Manipulation.md\n 📄 AlphaGo (\n\n\n[CRITICAL: SECOND BRAIN INDEX — User's Personal Knowledge Base (2851 documents)]\nThe user has synced a personal knowledge repository. Below is the TABLE OF CONTENTS.\n(⚠️ 메모리 폭발 방지를 위해 상위 200개 파일의 목차만 표시됩니다.)\nIf the user's query is even slightly related to any topics in this index, YOU MUST FIRST READ the relevant document BEFORE answering.\nTo read the actual content of any document, use EXACTLY this syntax: filename_or_path\nYou can call multiple times. ALWAYS READ THE FULL DOCUMENT BEFORE ANSWERING.\n\n**IMPORTANT: When your answer uses knowledge from the Second Brain, you MUST end your response with a \"📚 출처\" section listing the file(s) you referenced. Example:\n📚 출처: MrBeast_분석.md, 마케팅_전략.md**\n\n 📄 00_Raw\\2026-04-20\\API 응답 모델링 및 상태 머신(State Machine) 설계.md → \"\"\n 📄 00_Raw\\2026-04-20\\Diffusion-Models.md → \"\"\n 📄 00_Raw\\2026-04-20\\Looking-Glass-Studios.md → \"\"\n 📄 00_Raw\\2026-04-20\\SAST.md → \"\"\n 📄 01_Frontend_Mastery\\React_Clean_Code_Best_Practices.md → \"---\r\"\n 📄 01_Frontend_Mastery\\React_Hooks_Deep_Dive.md → \"---\r\"\n 📄 01_Frontend_Mastery\\React_Mental_Model.md → \"---\r\"\n 📄 01_Frontend_Mastery\\React_Performance_Optimization.md → \"---\r\"\n 📄 01_Frontend_Mastery\\React_State_Management_Strategy.md → \"---\r\"\n 📄 01_Frontend_Mastery\\React_Testing_Strategy.md → \"---\r\"\n 📄 01_Frontend_Mastery\\TypeScript 컴파일러의 정적 타입 시스템.md → \"\"\n 📄 01_Frontend_Mastery\\TypeScript_Type_Safety.md → \"---\r\"\n 📄 01_Frontend_Mastery\\WebWorker_Performance.md → \"---\r\"\n 📄 02_Architecture_Principles\\API_Communication_Patterns.md → \"---\r\"\n 📄 02_Architecture_Principles\\Component_Design_Patterns.md → \"---\r\"\n 📄 02_Architecture_Principles\\Separation_of_Concerns.md → \"---\r\"\n 📄 02_Architecture_Principles\\Single_Source_of_Truth.md → \"---\r\"\n 📄 02_Architecture_Principles\\Systemic_Simulation_Principles.md → \"---\r\"\n 📄 03_DevOps_Environment\\Deployment_Final_Gate.md → \"---\r\"\n 📄 03_DevOps_Environment\\Developer Produ" - }, - { - "role": "user", - "content": "안녕" - }, - { - "role": "assistant", - "content": "\n\n안녕하세요! 👋 오늘 어떤 작업이 필요하신가요?" - }, - { - "role": "user", - "content": "지금 E:\\Wiki\\ConnectAI 이폴더 분석해줘. 설계적으로, 기능적으로, 사용자 입장에서 개선이 필요하거나 문제가 있거나 최적화가 안된 부분이 있거나 기타 등등.." - }, - { - "role": "assistant", - "content": "\n\n먼저 ConnectAI 폴더의 전체 구조를 파악하겠습니다.\n\n" - }, - { - "role": "user", - "content": "[시스템: list_files 결과]\n디렉토리: ConnectAI/\n📁 assets/\n📄 brain-viz.html\n📄 connect-ai-lab-2.2.15.vsix\n📄 diff.txt\n📄 diff_utf8.txt\n📄 g1nation-2.2.15.vsix\n📄 g1nation-final-v2.vsix\n📄 g1nation-final-v3.vsix\n📄 g1nation-final.vsix\n📄 g1nation-latest.vsix\n📄 g1nation-new-build.vsix\n📄 LICENSE\n📄 package-lock.json\n📄 package.json\n📄 README.md\n📁 src/\n📄 system_schema.json\n📄 tsconfig.json" - }, - { - "role": "user", - "content": "지금 E:\\Wiki\\ConnectAI 이폴더 분석해줘. 설계적으로, 기능적으로, 사용자 입장에서 개선이 필요하거나 문제가 있거나 최적화가 안된 부분이 있거나 기타 등등.." - }, - { - "role": "assistant", - "content": "\n\n먼저 핵심 파일들을 모두 읽어서 프로젝트 전체를 파악하겠습니다.\n\n\n\n\n\n" - }, - { - "role": "user", - "content": "[시스템: read_file 결과]\n파일: ConnectAI/package.json\n```\n{\n \"name\": \"g1nation\",\n \"displayName\": \"G1nation\",\n \"description\": \"100% local AI coding agent for VS Code. Create files, edit code, run commands, and work offline with Ollama or LM Studio.\",\n \"version\": \"2.2.15\",\n \"publisher\": \"connectailab\",\n \"license\": \"MIT\",\n \"icon\": \"assets/icon.png\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/wonseokjung/connect-ai\"\n },\n \"engines\": {\n \"vscode\": \"^1.80.0\"\n },\n \"categories\": [\n \"Machine Learning\",\n \"Programming Languages\",\n \"Chat\"\n ],\n \"keywords\": [\n \"ai\",\n \"local\",\n \"ollama\",\n \"gemma\",\n \"llama\",\n \"deepseek\",\n \"offline\",\n \"agent\",\n \"code-generation\",\n \"g1nation\",\n \"copilot\"\n ],\n \"activationEvents\": [\n \"*\"\n ],\n \"main\": \"./out/extension.js\",\n \"contributes\": {\n \"commands\": [\n {\n \"command\": \"g1nation.newChat\",\n \"title\": \"G1nation: New Chat\",\n \"icon\": \"$(add)\"\n },\n {\n \"command\": \"g1nation.exportChat\",\n \"title\": \"G1nation: Export Chat as Markdown\"\n },\n {\n \"command\": \"g1nation.explainSelection\",\n \"title\": \"G1nation: Explain Selected Code\"\n },\n {\n \"command\": \"g1nation.focusChat\",\n \"title\": \"G1nation: Focus Chat Input\"\n },\n {\n \"command\": \"g1nation.showBrainNetwork\",\n \"title\": \"G1nation: Show Brain Topology\"\n }\n ],\n \"keybindings\": [\n {\n \"command\": \"g1nation.focusChat\",\n \"key\": \"cmd+l\",\n \"mac\": \"cmd+l\"\n }\n ],\n \"menus\": {\n \"editor/context\": [\n {\n \"command\": \"g1nation.explainSelection\",\n \"when\": \"editorHasSelection\",\n \"group\": \"1_modification\"\n }\n ]\n },\n \"viewsContainers\": {\n \"activitybar\": [\n {\n \"id\": \"g1nation-sidebar\",\n \"title\": \"G1nation\",\n \"icon\": \"$(hubot)\"\n }\n ]\n },\n \"views\": {\n \"g1nation-sidebar\": [\n {\n \"type\": \"webview\",\n \"id\": \"g1nation-v2-view\",\n \"name\": \"Chat\"\n }\n ]\n },\n \"configuration\": {\n \"title\": \"G1nation\",\n \"properties\": {\n \"g1nation.ollamaUrl\": {\n \"type\": \"string\",\n \"default\": \"http://127.0.0.1:11434\",\n \"description\": \"Base URL for Ollama or LM Studio. Default: http://127.0.0.1:11434\"\n },\n \"g1nation.defaultModel\": {\n \"type\": \"string\",\n \"default\": \"gemma4:e2b\",\n \"description\": \"Default model name to use for chat requests.\"\n },\n \"g1nation.requestTimeout\": {\n \"type\": \"number\",\n \"default\": 300,\n \"description\": \"Request timeout in seconds. Default: 300\"\n },\n \"g1nation.localBrainPath\": {\n \"type\": \"string\",\n \"default\": \"\",\n \"description\": \"Folder path for your local Second Brain knowledge base. Leave empty to use the default folder.\"\n },\n \"g1nation.secondBrainRepo\": {\n \"type\": \"string\",\n \"default\": \"\",\n \"description\": \"Optional GitHub repository URL used for Second Brain sync.\"\n },\n \"g1nation.autoPushBrain\": {\n \"type\": \"boolean\",\n \"default\": false,\n \"description\": \"Automatically commit and push Second Brain changes after updates.\"\n }\n }\n }\n },\n \"scripts\": {\n \"vscode:prepublish\": \"npm run compile\",\n \"compile\": \"esbuild src/extension.ts --bundle --platform=node --external:vscode --outfile=out/extension.js\",\n \"watch\": \"tsc -watch -p ./\",\n \"pretest\": \"npm run compile\"\n },\n \"devDependencies\": {\n \"@types/node\": \"18.x\",\n \"@types/vscode\": \"^1.80.0\",\n \"@vercel/ncc\": \"^0.38.4\",\n \"esbuild\": \"^0.28.0\",\n \"typescript\": \"^5.1.3\"\n },\n \"dependencies\": {\n \"axios\": \"^1.15.0\",\n \"jsdom\": \"^29.0.2\"\n }\n}\n\n```" - }, - { - "role": "user", - "content": "[시스템: read_file 결과]\n파일: ConnectAI/tsconfig.json\n```\n{\r\n \"compilerOptions\": {\r\n \"module\": \"commonjs\",\r\n \"target\": \"ES2022\",\r\n \"outDir\": \"out\",\r\n \"lib\": [\"ES2022\"],\r\n \"sourceMap\": true,\r\n \"strict\": true\r\n },\r\n \"exclude\": [\"node_modules\", \".vscode-test\"]\r\n}\r\n\n```" - }, - { - "role": "user", - "content": "[시스템: read_file 결과]\n파일: ConnectAI/README.md\n```\n

\r\n \"Connect\r\n

\r\n\r\n

Connect AI v2 (P-Reinforce)

\r\n\r\n

\r\n 100% Local · 100% Offline · Autonomous Knowledge Engine
\r\n VS Code / Cursor 확장 프로그램으로, 당신의 낡은 IDE를 최상위 에이전트 대학(A.U)의 심장으로 진화시킵니다.\r\n

\r\n\r\n

\r\n \"version\"\r\n \"license\"\r\n \"integration\"\r\n \"engine\"\r\n

\r\n\r\n---\r\n\r\n## 🌟 Overview: The P-Reinforce Architecture\r\n\r\nConnect AI v2.1.30은 단순한 코딩 에이전트를 넘어섭니다. **P-Reinforce 아키텍처**를 기반으로 설계된 이 에이전트는 사용자의 모든 정보와 지시를 받아들여 **스스로 의미를 분석하고, 폴더를 생성하고, 마크다운 위키 파일로 정리하여 클라우드에 자동 백업**하는 자율 지식 정원사(Autonomous Gardener)입니다.\r\n\r\n---\r\n\r\n## ⚡ Core Features\r\n\r\n### 1. 🧠 Agent University (A.U) 완벽 연동\r\nAgent University 웹 플랫폼과 실시간으로 통신합니다. \r\n웹에서 버튼 한 번 누르는 즉시, 로컬 VS Code의 `4825` 포트를 통해 프리미엄 브레인 팩(Premium Brain Pack) 지식이 로컬 인공지능 뇌(`~/.connect-ai-brain`)에 자동 주입되어 신경망을 확장합니다.\r\n\r\n### 2. 📂 자율 지식 구조화 (Zero-Interaction Styling)\r\n유저가 던져주는 원시 데이터(Raw Data)를 에이전트가 스스로 판단해 `10_Wiki`, `00_Raw`, `🚀 Skills` 와 같은 완벽한 P-Reinforce 템플릿 규격의 Markdown 파일로 분할-조립하여 저장합니다.\r\n\r\n### 3. ☁️ 클라우드 동기화 (Auto-Git Sync 100%)\r\n로컬 PC에서 파일 생성이 일어나는 순간, 에이전트가 스스로 GitHub 저장소에 `git add`, `commit`, `push`를 수행합니다. \r\n마스터는 이제 지루한 푸시 커맨드를 입력할 필요가 없습니다.\r\n\r\n### 4. 🔗 설치형 모델 자동 감지 (Dynamic Model Detection)\r\nOllama 또는 LM Studio에 설치된 모델을 내부 API(`v1/models`)를 호출하여 자동 감지하고, UI의 스위치 보드(드롭다운)에 연결합니다. 어떤 모델을 쓸지 번거롭게 입력하지 마십시오.\r\n\r\n---\r\n\r\n## ⚒️ Agent Capabilities (에이전트 권한)\r\n\r\n로컬 머신의 파일 시스템과 터미널에 대한 통제권을 인공지능에게 부여합니다. (100% 안전한 권한 승인 기반)\r\n\r\n| Action | Description |\r\n|:--|:--|\r\n| **📄 Create Files** | 새로운 파일과 폴더를 생성합니다 |\r\n| **✏️ Edit Files** | 기존 파일 내의 코드를 수정합니다 |\r\n| **🗑️ Delete Files** | 불필요한 파일을 즉각 파쇄합니다 |\r\n| **📖 Read Files** | 마스터의 프로젝트 파일을 읽어 맥락을 파악합니다 |\r\n| **📂 Browse Directories** | 디렉토리 구조를 분석합니다 |\r\n| **🖥️ Run Commands** | `npm run build`, `git push` 등 터미널 명령을 수행합니다 |\r\n\r\n---\r\n\r\n## 📥 Installation (설치 방법)\r\n\r\n### A.U 멤버십 유저 (Recommended)\r\n1. 상단 탭의 [Releases](https://github.com/wonseokjung/connect-ai/releases) 메뉴로 진입.\r\n2. 최신 `v2.1.30.vsix` 파일을 다운로드.\r\n3. VS Code 에서 `Cmd+Shift+P` → **Extensions: Install from VSIX** → 다운받은 파일 선택\r\n\r\n### 개발자 빌드 (Build from Source)\r\n```bash\r\ngit clone https://github.com/wonseokjung/connect-ai.git\r\ncd connect-ai\r\nnpm install\r\nnpm run compile\r\nnpx vsce package\r\n```\r\n\r\n---\r\n\r\n## ⚙️ Engine Setup (엔진 설정 방법)\r\n\r\n### ✅ LM Studio (Apple Silicon, Windows) - 권장\r\n1. [lmstudio.ai](https://lmstudio.ai/) 에서 설치\r\n2. Gemma 3, Llama 3 또는 Qwen Coder 등 원하는 모델 로드\r\n3. **Developer 탭(좌측 `<>` 메뉴)** 진입 후 **Start Server** 클릭\r\n4. Connect AI의 ⚙️ 채팅방 설정에서 엔진을 \"LM Studio\"로 선택 (자동 모델 인덱싱 완료)\r\n\r\n### ✅ Ollama (Mac, Linux)\r\n```bash\r\nbrew install ollama\r\nollama pull gemma3 # 원하는 모델 풀링\r\n```\r\nConnect AI에서 설정만 \"Ollama\"로 바꿔주시면 끝납니다.\r\n\r\n---\r\n\r\n## 🔒 Privacy (완벽한 보안)\r\n\r\n- **Zero Cloud API:** 당신의 코드는 외부 클라우드 통신망을 타지 않습니다.\r\n- **Zero Telemetry:** 모든 연산력은 100% Local Inference 환경에서 이루어집니다.\r\n- 기업 보안 등급에 준하는 극강의 밀폐형 로컬 지식망 생성을 보장합니다.\r\n\r\n---\r\n\r\n

\r\n Built for Antigravity & Agent University
\r\n Designed by Jay × Connect AI Architect\r\n

\r\n\n```" - }, - { - "role": "user", - "content": "[시스템: read_file 결과]\n파일: ConnectAI/system_schema.json\n```\n{\r\n \"schema_name\": \"ConnectAI_AgentSystemSchema\",\r\n \"version\": \"1.0.0\",\r\n \"description\": \"A comprehensive JSON schema defining the operational state, capabilities, and configuration of the Connect AI agent.\",\r\n \"agent_identity\": {\r\n \"name\": \"Connect AI\",\r\n \"role\": \"Agentic AI Coding Assistant\",\r\n \"core_principle\": \"100% Local · 100% Offline · 100% Free\"\r\n },\r\n \"environment\": {\r\n \"workspace_path\": \"/Users/jay/로컬테스트/local-ai-coder\",\r\n \"file_system_access\": \"Direct, offline access to the local file system via agent actions.\",\r\n \"context_source\": \"Local workspace files and optional GitHub knowledge base.\"\r\n },\r\n \"agent_capabilities\": [\r\n {\r\n \"action\": \"CREATE_FILE\",\r\n \"description\": \"Generates new files and directories in the workspace.\"\r\n },\r\n {\r\n \"action\": \"EDIT_FILE\",\r\n \"description\": \"Finds and replaces specific code in existing files.\"\r\n },\r\n {\r\n \"action\": \"DELETE_FILE\",\r\n \"description\": \"Removes files and folders.\"\r\n },\r\n {\r\n \"action\": \"READ_FILE\",\r\n \"description\": \"Reads the content of any file in the workspace to understand context.\"\r\n },\r\n {\r\n \"action\": \"LIST_DIRECTORY\",\r\n \"description\": \"Lists contents of a specific subdirectory.\"\r\n },\r\n {\r\n \"action\": \"RUN_TERMINAL_COMMAND\",\r\n \"description\": \"Executes CLI commands (e.g., npm install, node).\"\r\n },\r\n {\r\n \"action\": \"READ_BRAIN\",\r\n \"description\": \"Queries the personal knowledge base (Second Brain) from a linked repository.\"\r\n // Note: Reading URLs is also available as an action if needed.\r\n }\r\n ],\r\n \"configuration\": {\r\n \"engine_options\": {\r\n \"default_model\": \"gemma4:e2b\",\r\n \"ollama_url\": \"http://127.0.0.1:11434\"\r\n },\r\n \"operational_settings\": {\r\n \"temperature\": 0.7,\r\n \"top_p\": 0.9,\r\n \"top_k\": 40,\r\n \"request_timeout_seconds\": 300,\r\n \"max_context_files\": 200\r\n },\r\n \"knowledge_base\": {\r\n \"second_brain_repo_url\": \"\",\r\n \"data_location\": \"~/.connect-ai-brain/\"\r\n }\r\n },\r\n \"workspace_snapshot\": {\r\n \"files_present\": [\r\n \"assets/icon.png\",\r\n \"src/*.ts\",\r\n \"fix_final.py\",\r\n \"README.md\",\r\n \"package.json\",\r\n \"tsconfig.json\"\r\n ],\r\n \"file_count\": 48\r\n }\r\n}\n```" - }, - { - "role": "user", - "content": "지금 E:\\Wiki\\ConnectAI 이폴더 분석해줘. 설계적으로, 기능적으로, 사용자 입장에서 개선이 필요하거나 문제가 있거나 최적화가 안된 부분이 있거나 기타 등등.." - }, - { - "role": "assistant", - "content": "\n\n" - }, - { - "role": "user", - "content": "지금 E:\\Wiki\\ConnectAI 이폴더 분석해줘. 설계적으로, 기능적으로, 사용자 입장에서 개선이 필요하거나 문제가 있거나 최적화가 안된 부분이 있거나 기타 등등.." - } - ], - "stream": true, - "max_tokens": 4096, - "temperature": 0.8, - "top_p": 0.9 -} \ No newline at end of file diff --git a/10_Wiki/Topics/리팩토링 실전 가이드 (Refactoring Best Practices).md b/10_Wiki/Topics/리팩토링 실전 가이드 (Refactoring Best Practices).md deleted file mode 100644 index e69de29b..00000000 diff --git a/10_Wiki/Topics/무제 1.base b/10_Wiki/Topics/무제 1.base new file mode 100644 index 00000000..d75ccc18 --- /dev/null +++ b/10_Wiki/Topics/무제 1.base @@ -0,0 +1,3 @@ +views: + - type: table + name: 표 diff --git a/10_Wiki/Topics/_agents/youtube/tools/telegram_notify.json b/10_Wiki/Topics/무제 1.canvas similarity index 100% rename from 10_Wiki/Topics/_agents/youtube/tools/telegram_notify.json rename to 10_Wiki/Topics/무제 1.canvas diff --git a/10_Wiki/Topics/무제.base b/10_Wiki/Topics/무제.base new file mode 100644 index 00000000..d75ccc18 --- /dev/null +++ b/10_Wiki/Topics/무제.base @@ -0,0 +1,3 @@ +views: + - type: table + name: 표 diff --git a/10_Wiki/Topics/무제.canvas b/10_Wiki/Topics/무제.canvas new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/10_Wiki/Topics/무제.canvas @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/10_Wiki/Topics/수익형 블로그 포스팅 구조 패턴.md b/10_Wiki/Topics/수익형 블로그 포스팅 구조 패턴.md deleted file mode 100644 index e69de29b..00000000