+
+ {/* Header */}
+
+ {userId && (
+
+ User ID
+ {userId}
+
+ {copiedUserId && (
+ Copied!
+ )}
+
+ )}
+
+
+
+ AI Oracle
+
+
+
+ The Truth Machine
+
+
+ Decentralized Truth Verification Powered by Cortensor Network
+
+
+
+ {/* Side panel toggle aligned above form */}
+
+
+
+
+
+
+
+
+
+
+
+
+ Ask the Oracle
+
+
+ Submit your query to get verified answers from multiple AI miners
+
+
+
+
+
+
+
+
+
+ {/* Loading State */}
+ {isLoading && (
+
{
+ // Controlled completion; UI will finalize once we decide
+ }}
+ />
+ )}
+
+ {/* Results */}
+ {results && (
+
+
+
+ Latest Result
+
+
+
+ )}
+
+ {/* Query History */}
+
+ {queryHistory.length === 0 ? (
+
No queries yet. Ask the Oracle to see history.
) : (
- 'Verify'
+
)}
-
-
-
- {/* Model Selector */}
-
-
-
-
-
- {/* Loading State */}
- {isLoading && (
- {
- // Controlled completion; UI will finalize once we decide
- }}
- />
- )}
-
- {/* Results */}
- {results && (
-
-
-
- Latest Result
-
-
-
- )}
-
- {/* Query History */}
- {queryHistory.length > 0 && (
-
-
-
- Query History ({queryHistory.length})
-
-
+
+ {showSidePanel && (
+
+ )}
+
+
+ {/* Features */}
+
+
+
+
+ Consensus Verification
+
+ Multiple independent AI miners verify each query for maximum accuracy
+
+
+
+
+
+
+
+ Decentralized Network
+
+ Powered by distributed miners eliminating single points of failure
+
+
+
+
+
+
+
+ AI-Powered Truth
+
+ Advanced AI models work together to provide reliable, fact-checked answers
+
+
+
+
+
+ {/* Footer */}
+
- )}
-
- {/* Features */}
-
-
-
-
- Consensus Verification
-
- Multiple independent AI miners verify each query for maximum accuracy
-
-
-
-
-
-
-
- Decentralized Network
-
- Powered by distributed miners eliminating single points of failure
-
-
-
-
-
-
-
- AI-Powered Truth
-
- Advanced AI models work together to provide reliable, fact-checked answers
-
-
-
-
- {/* Footer */}
-
-
>
)
}
diff --git a/apps/Cortensor-AIOracle/src/lib/external-apis-tavily.ts b/apps/Cortensor-AIOracle/src/lib/external-apis-tavily.ts
new file mode 100644
index 0000000..8e4e009
--- /dev/null
+++ b/apps/Cortensor-AIOracle/src/lib/external-apis-tavily.ts
@@ -0,0 +1,240 @@
+// Tavily AI Search - Primary source for fact-checking and real-time data
+
+interface TavilyResult {
+ title: string
+ url: string
+ content: string
+ score: number
+ published_date?: string
+}
+
+interface TavilyResponse {
+ results: TavilyResult[]
+ query: string
+ response_time: number
+}
+
+interface SourceArticle {
+ title: string
+ url: string
+ reliability: string
+ snippet?: string
+ domain?: string
+ publishedAt?: string
+ publisher?: string
+}
+
+export class TavilyDataService {
+ private static readonly TAVILY_API_KEY = process.env.TAVILY_API_KEY
+ private static readonly TAVILY_BASE_URL = 'https://api.tavily.com'
+
+ /**
+ * Search using Tavily AI - Returns high-quality, credible sources
+ * @param query - Search query
+ * @param options - Search options (max_results, search_depth, include_domains, exclude_domains)
+ */
+ static async search(
+ query: string,
+ options: {
+ maxResults?: number
+ searchDepth?: 'basic' | 'advanced'
+ includeDomains?: string[]
+ excludeDomains?: string[]
+ includeAnswer?: boolean
+ } = {}
+ ): Promise<{ sources: SourceArticle[], answer?: string }> {
+ if (!this.TAVILY_API_KEY) {
+ console.warn('[Tavily] API key not configured')
+ return { sources: [] }
+ }
+
+ try {
+ const response = await fetch(`${this.TAVILY_BASE_URL}/search`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${this.TAVILY_API_KEY}`
+ },
+ body: JSON.stringify({
+ query,
+ max_results: options.maxResults || 5,
+ search_depth: options.searchDepth || 'advanced',
+ include_domains: options.includeDomains || [],
+ exclude_domains: options.excludeDomains || [],
+ include_answer: options.includeAnswer !== false,
+ include_raw_content: false,
+ include_images: false
+ })
+ })
+
+ if (!response.ok) {
+ console.error('[Tavily] API error:', response.status, response.statusText)
+ return { sources: [] }
+ }
+
+ const data: TavilyResponse & { answer?: string } = await response.json()
+
+ // Transform Tavily results to our SourceArticle format
+ const sources: SourceArticle[] = data.results.map(result => {
+ const domain = this.extractDomain(result.url)
+ const reliability = this.assessReliability(domain, result.score)
+
+ return {
+ title: result.title,
+ url: result.url,
+ reliability,
+ snippet: result.content.slice(0, 200) + (result.content.length > 200 ? '...' : ''),
+ domain,
+ publishedAt: result.published_date || new Date().toISOString(),
+ publisher: this.getDomainName(domain)
+ }
+ })
+
+ console.log(`[Tavily] Found ${sources.length} sources for query: "${query}"`)
+
+ return {
+ sources: sources.slice(0, options.maxResults || 5),
+ answer: data.answer
+ }
+
+ } catch (error) {
+ console.error('[Tavily] Search error:', error)
+ return { sources: [] }
+ }
+ }
+
+ /**
+ * Get sources for fact-checking claims
+ * Uses advanced search depth and prefers fact-checking domains
+ */
+ static async getFactCheckSources(claim: string): Promise
{
+ const factCheckDomains = [
+ 'snopes.com',
+ 'factcheck.org',
+ 'politifact.com',
+ 'fullfact.org',
+ 'apnews.com',
+ 'reuters.com',
+ 'bbc.com',
+ 'who.int',
+ 'cdc.gov',
+ 'nih.gov',
+ 'nasa.gov'
+ ]
+
+ const result = await this.search(claim, {
+ maxResults: 5,
+ searchDepth: 'advanced',
+ includeDomains: factCheckDomains
+ })
+
+ return result.sources
+ }
+
+ /**
+ * Backward compatibility - get fact checks
+ */
+ static async getFactChecks(query: string): Promise {
+ const sources = await this.getFactCheckSources(query)
+ return sources.map(s => ({
+ text: s.snippet || '',
+ url: s.url,
+ title: s.title,
+ publisher: s.publisher || s.domain,
+ publishedAt: s.publishedAt
+ }))
+ }
+
+ /**
+ * Enrich query with external data - main method for oracle-engine
+ */
+ static async enrichQueryWithExternalData(query: string): Promise {
+ const sources = await getRelevantArticles(query)
+
+ if (sources.length === 0) {
+ return 'No recent sources found.'
+ }
+
+ // Format sources as context
+ let context = 'REAL-TIME DATA SOURCES:\n\n'
+ sources.forEach((source, i) => {
+ context += `${i + 1}. ${source.title}\n`
+ context += ` Source: ${source.publisher || source.domain} (${source.reliability} credibility)\n`
+ if (source.snippet) {
+ context += ` ${source.snippet}\n`
+ }
+ context += ` URL: ${source.url}\n\n`
+ })
+
+ return context
+ }
+
+ /**
+ * Extract domain from URL
+ */
+ private static extractDomain(url: string): string {
+ try {
+ const urlObj = new URL(url)
+ return urlObj.hostname.replace(/^www\./, '')
+ } catch {
+ return 'unknown'
+ }
+ }
+
+ /**
+ * Get readable domain name
+ */
+ private static getDomainName(domain: string): string {
+ const parts = domain.split('.')
+ if (parts.length >= 2) {
+ return parts[parts.length - 2].charAt(0).toUpperCase() + parts[parts.length - 2].slice(1)
+ }
+ return domain
+ }
+
+ /**
+ * Assess source reliability based on domain and score
+ */
+ private static assessReliability(domain: string, score: number): string {
+ // High credibility domains
+ const highCredibility = [
+ 'gov', 'edu', 'who.int', 'cdc.gov', 'nih.gov', 'nasa.gov',
+ 'reuters.com', 'apnews.com', 'bbc.com', 'bbc.co.uk',
+ 'nature.com', 'science.org', 'sciencedirect.com',
+ 'snopes.com', 'factcheck.org', 'politifact.com', 'fullfact.org'
+ ]
+
+ const isTrustedDomain = highCredibility.some(trusted =>
+ domain.endsWith(trusted) || domain.includes(trusted)
+ )
+
+ if (isTrustedDomain && score >= 0.7) return 'High'
+ if (isTrustedDomain || score >= 0.8) return 'High'
+ if (score >= 0.6) return 'Medium'
+ return 'Low'
+ }
+}
+
+/**
+ * Main function to get sources for any query
+ * This replaces the old ExternalDataService.enrichQueryWithExternalData
+ */
+export async function getRelevantArticles(query: string): Promise {
+ // Check if it's a fact-check query
+ const isFactCheck = /is it true|is this true|correct|real|hoax|myth|fact.?check|claim/i.test(query)
+
+ if (isFactCheck) {
+ return await TavilyDataService.getFactCheckSources(query)
+ }
+
+ // Regular search
+ const result = await TavilyDataService.search(query, {
+ maxResults: 5,
+ searchDepth: 'advanced'
+ })
+
+ return result.sources
+}
+
+// Export for backward compatibility
+export { TavilyDataService as ExternalDataService }
diff --git a/apps/Cortensor-AIOracle/src/lib/oracle-engine.ts b/apps/Cortensor-AIOracle/src/lib/oracle-engine.ts
index 5702bf2..a9b1c6c 100644
--- a/apps/Cortensor-AIOracle/src/lib/oracle-engine.ts
+++ b/apps/Cortensor-AIOracle/src/lib/oracle-engine.ts
@@ -1,7 +1,7 @@
import { CORTENSOR_CONFIG, ORACLE_CONFIG } from './config'
import { sanitizeModelAnswer } from './utils'
import { AVAILABLE_MODELS, getModelConfig, generatePromptForModel, ModelConfig } from './models'
-import { ExternalDataService, getRelevantArticles } from './external-apis'
+import { TavilyDataService as ExternalDataService, getRelevantArticles } from './external-apis-tavily'
// Debug logger controlled via env ORACLE_DEBUG_LOGS = '1' | 'true'
const ORACLE_DEBUG = process.env.ORACLE_DEBUG_LOGS === '1' || process.env.ORACLE_DEBUG_LOGS === 'true'
@@ -19,6 +19,7 @@ export interface OracleEngineOptions {
timeoutMs?: number
// Optional: raw router SSE transcript so we can avoid another router call
routerText?: string
+ clientReference?: string
}
export interface OracleEngineResult {
@@ -31,6 +32,7 @@ export interface OracleEngineResult {
consensus?: { totalMiners: number; respondedMiners: number; agreements: number; disagreements: number; confidenceScore: number }
modelName?: string
timestamp?: number
+ clientReference?: string
// New fields for TaaS / fact-check pipelines
claim?: string
verdict?: 'True' | 'False' | 'Uncertain'
@@ -315,6 +317,9 @@ export class OracleEngine {
const timeoutSec = Math.ceil(timeoutMs / 1000)
const apiTimeoutSec = Number.isFinite(CORTENSOR_CONFIG.TIMEOUT) && CORTENSOR_CONFIG.TIMEOUT > 0 ? CORTENSOR_CONFIG.TIMEOUT : timeoutSec
const maxTokens = Number.isFinite(CORTENSOR_CONFIG.MAX_TOKENS) && CORTENSOR_CONFIG.MAX_TOKENS > 0 ? CORTENSOR_CONFIG.MAX_TOKENS : (model.maxTokens || 1024)
+ const clientReference = options?.clientReference && options.clientReference.trim()
+ ? options.clientReference.trim()
+ : `oracle-${Date.now()}`
// 1) Enrich with real-time external data
// Always enrich with external context
@@ -326,7 +331,7 @@ export class OracleEngine {
const body = {
prompt,
prompt_type: 1,
- client_reference: `oracle-${Date.now()}`,
+ client_reference: clientReference,
stream: false,
timeout: apiTimeoutSec,
max_tokens: maxTokens,
@@ -813,6 +818,7 @@ export class OracleEngine {
consensus: { totalMiners: Number(routerTotalMiners) || miners, respondedMiners, agreements, disagreements, confidenceScore: finalConfidence },
modelName: model.displayName || model.name,
timestamp: Date.now(),
+ clientReference,
claim: query,
verdict,
label,
@@ -838,6 +844,7 @@ export class OracleEngine {
taskId: (apiData && (apiData.task_id || apiData.taskId)) || undefined,
model: (apiData && apiData.model) || undefined,
minerAddresses,
+ clientReference,
minersMeta: (apiData as any)?.debugMinersMeta,
confidenceBreakdown: {
baseConfidence,
diff --git a/apps/Cortensor-AIOracle/src/lib/oracle-facts.ts b/apps/Cortensor-AIOracle/src/lib/oracle-facts.ts
new file mode 100644
index 0000000..266b43c
--- /dev/null
+++ b/apps/Cortensor-AIOracle/src/lib/oracle-facts.ts
@@ -0,0 +1,80 @@
+import fs from 'fs/promises'
+import path from 'path'
+
+export type OracleFact = {
+ id: string
+ query: string
+ answer: string
+ verdict: 'Yes' | 'No'
+ confidence?: number
+ sources?: Array<{
+ title: string
+ url: string
+ reliability?: string
+ snippet?: string
+ publishedAt?: string
+ publisher?: string
+ }>
+ modelName?: string
+ queryId?: string
+ createdAt: string
+}
+
+const FACTS_PATH = path.join(process.cwd(), 'data', 'oracle-facts.json')
+
+async function ensureStore() {
+ const dir = path.dirname(FACTS_PATH)
+ await fs.mkdir(dir, { recursive: true })
+ try {
+ await fs.access(FACTS_PATH)
+ } catch {
+ await fs.writeFile(FACTS_PATH, '[]', 'utf8')
+ }
+}
+
+export async function getOracleFacts(limit = 20): Promise {
+ await ensureStore()
+ const raw = await fs.readFile(FACTS_PATH, 'utf8')
+ let parsed: OracleFact[] = []
+ try {
+ parsed = JSON.parse(raw)
+ } catch {
+ parsed = []
+ }
+ const sorted = parsed.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
+ return sorted.slice(0, Math.max(1, limit))
+}
+
+export async function addOracleFact(fact: Omit & { id?: string; createdAt?: string }) {
+ await ensureStore()
+ const raw = await fs.readFile(FACTS_PATH, 'utf8')
+ let parsed: OracleFact[] = []
+ try {
+ parsed = JSON.parse(raw)
+ } catch {
+ parsed = []
+ }
+
+ // Skip duplicates based on queryId when available
+ if (fact.queryId) {
+ const exists = parsed.some(f => f.queryId === fact.queryId)
+ if (exists) return parsed.find(f => f.queryId === fact.queryId) as OracleFact
+ }
+
+ const record: OracleFact = {
+ id: fact.id || `fact-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
+ query: fact.query,
+ answer: fact.answer,
+ verdict: fact.verdict,
+ confidence: fact.confidence,
+ sources: fact.sources?.slice(0, 5),
+ modelName: fact.modelName,
+ queryId: fact.queryId,
+ createdAt: fact.createdAt || new Date().toISOString()
+ }
+
+ const next = [record, ...parsed]
+ const capped = next.slice(0, 200)
+ await fs.writeFile(FACTS_PATH, JSON.stringify(capped, null, 2), 'utf8')
+ return record
+}
diff --git a/apps/Cortensor-AIOracle/src/lib/random-facts.ts b/apps/Cortensor-AIOracle/src/lib/random-facts.ts
new file mode 100644
index 0000000..4b7d9c7
--- /dev/null
+++ b/apps/Cortensor-AIOracle/src/lib/random-facts.ts
@@ -0,0 +1,465 @@
+export interface RandomFact {
+ title: string
+ url: string
+ snippet: string
+ reliability: 'high' | 'medium' | 'low' | 'unknown'
+ publisher?: string
+ publishedAt?: string
+ source?: string
+ verdict: 'Yes' | 'No'
+ question?: string
+ answer?: string
+}
+
+const TAVILY_URL = 'https://api.tavily.com/search'
+
+// Explicit yes/no claim-style prompts grouped by category (50 each)
+const YES_NO_PROMPT_CATEGORIES: Record = {
+ science: [
+ 'Is lightning hotter than the surface of the sun?',
+ 'Do sharks sleep?',
+ 'Is glass an amorphous solid?',
+ 'Can sound travel in space?',
+ 'Is absolute zero unattainable?',
+ 'Do penguins live in the Arctic?',
+ 'Is DNA a double helix?',
+ 'Do plants perform photosynthesis at night?',
+ 'Is water denser at 4 degrees Celsius than at 0 degrees?',
+ 'Is blood ever blue inside the body?',
+ 'Do bananas contain radioactive potassium?',
+ 'Can humans digest cellulose?',
+ 'Is copper a better conductor than iron?',
+ 'Do all metals conduct electricity?',
+ 'Is graphene one atom thick?',
+ 'Do viruses have their own metabolism?',
+ 'Is the speed of light constant in vacuum?',
+ 'Can humans see UV light unaided?',
+ 'Is helium lighter than air?',
+ 'Do magnets lose strength when heated?',
+ 'Is rusting an oxidation reaction?',
+ 'Is charcoal mostly carbon?',
+ 'Is dry ice solid carbon dioxide?',
+ 'Can sugar dissolve faster in hot water?',
+ 'Is tungsten the metal with the highest melting point?',
+ 'Is ammonia a base?',
+ 'Do ants have lungs?',
+ 'Is Pluto classified as a dwarf planet?',
+ 'Is the Pacific Ocean the deepest ocean?',
+ 'Do earthquakes occur at plate boundaries?',
+ 'Is photosynthesis endothermic?',
+ 'Is the ozone hole mainly over Antarctica?',
+ 'Is carbon the basis of organic chemistry?',
+ 'Are proteins made of amino acids?',
+ 'Is lactose a disaccharide?',
+ 'Is boiling a liquid-to-gas phase change?',
+ 'Do catalysts lower activation energy?',
+ 'Is neon a noble gas?',
+ 'Is graphite used as a lubricant?',
+ 'Is salt water a homogeneous mixture?',
+ 'Is vinegar acidic?',
+ 'Does vitamin D require sunlight to synthesize in skin?',
+ 'Is insulin a hormone?',
+ 'Is adrenaline also called epinephrine?',
+ 'Do fungi have cell walls?',
+ 'Is diffusion driven by concentration gradients?',
+ 'Is osmosis specific to water movement?',
+ 'Is silicon a semiconductor?',
+ 'Can liquid water exist on Mars today?',
+ 'Is Mercury the closest planet to the sun?',
+ 'Is Earth the only planet with liquid surface water currently?'
+ ],
+ general: [
+ 'Is the Great Wall of China visible from space with the naked eye?',
+ 'Is Mount Everest the tallest mountain above sea level?',
+ 'Do camels store water in their humps?',
+ 'Is sushi always raw fish?',
+ 'Is New York the capital of the USA?',
+ 'Is the equator the longest line of latitude?',
+ 'Is English the most spoken native language?',
+ 'Is the Sahara the largest desert in the world?',
+ 'Is Africa the second largest continent?',
+ 'Is Europe a separate tectonic plate?',
+ 'Is coffee dehydrating?',
+ 'Is water wet?',
+ 'Is Australia both a country and a continent?',
+ 'Is Canada the country with the most lakes?',
+ 'Is Antarctica a desert by precipitation?',
+ 'Is the Dead Sea below sea level?',
+ 'Is Greenland mostly ice-covered?',
+ 'Is the Amazon rainforest the largest tropical rainforest?',
+ 'Is the Nile the longest river?',
+ 'Is the Indian Ocean the warmest ocean?',
+ 'Is chocolate toxic to dogs?',
+ 'Is copper used in most household wiring?',
+ 'Is plastic biodegradable by default?',
+ 'Is aluminum magnetic?',
+ 'Is gold denser than lead?',
+ 'Is diamond the hardest natural material?',
+ 'Is sand mostly silica?',
+ 'Is marble a metamorphic rock?',
+ 'Is glass recyclable?',
+ 'Is Wi-Fi an acronym?',
+ 'Is a tomato a fruit botanically?',
+ 'Is a pumpkin a berry botanically?',
+ 'Is honeybee the only insect making edible honey for humans?',
+ 'Is Friday named after a Norse goddess?',
+ 'Is February the only month that can miss a full moon?',
+ 'Is noon when the sun is highest everywhere?',
+ 'Is the International Date Line straight?',
+ 'Is UTC the same as GMT?',
+ 'Is Celsius an SI base unit?',
+ 'Is a byte 8 bits?',
+ 'Is JPEG lossless?',
+ 'Is PNG lossless?',
+ 'Is PDF a raster format?',
+ 'Is Bluetooth named after a king?',
+ 'Is Morse code still used?',
+ 'Is Esperanto a natural language?',
+ 'Is Iceland greener than Greenland?',
+ 'Is Venice built on islands?',
+ 'Is Rome older than Athens?',
+ 'Is the UK made of four countries?'
+ ],
+ history: [
+ 'Did the Roman Empire fall in 476 AD?',
+ 'Was Cleopatra ethnically Egyptian Greek?',
+ 'Did the Mongol Empire reach Europe?',
+ 'Was the Great Fire of London in 1666?',
+ 'Did World War I start in 1914?',
+ 'Did the Berlin Wall fall in 1989?',
+ 'Was Machu Picchu built by the Inca?',
+ 'Did the Wright brothers fly in 1903?',
+ 'Was Julius Caesar assassinated on the Ides of March?',
+ 'Did Napoleon lose at Waterloo?',
+ 'Did the Titanic sink in 1912?',
+ 'Was the Renaissance centered in Italy?',
+ 'Did Vikings reach North America?',
+ 'Was the Black Death in the 14th century?',
+ 'Did the US land on the moon in 1969?',
+ 'Was paper invented in China?',
+ 'Did Gutenberg invent the printing press?',
+ 'Was Genghis Khan born in Mongolia?',
+ 'Was the Cold War a conflict between NATO and the Warsaw Pact?',
+ 'Did the Aztecs build Tenochtitlan?',
+ 'Was the French Revolution in 1789?',
+ 'Did ancient Egyptians use papyrus?',
+ 'Was the Silk Road a single road?',
+ 'Did the Apollo 13 crew survive?',
+ 'Was Constantinople renamed Istanbul?',
+ 'Did the Ottoman Empire last until the 20th century?',
+ 'Was Stonehenge built in the Neolithic?',
+ 'Did the Mayans predict the world ending in 2012?',
+ 'Was the League of Nations before the UN?',
+ 'Did World War II end in 1945?',
+ 'Was Sputnik the first artificial satellite?',
+ 'Did ancient Rome use concrete?',
+ 'Was the Suez Canal opened in the 19th century?',
+ 'Was the Great Depression in the 1930s?',
+ 'Did Alexander the Great conquer Persia?',
+ 'Was the Colosseum used for gladiator games?',
+ 'Did the Qin dynasty unify China?',
+ 'Was tea first cultivated in China?',
+ 'Did Marco Polo reach China?',
+ 'Was the Trojan War historical fact?',
+ 'Did the Han dynasty establish the Silk Road?',
+ 'Was the Magna Carta signed in 1215?',
+ 'Was the Spanish Armada defeated in 1588?',
+ 'Did the Meiji Restoration modernize Japan?',
+ 'Did Rome fall before the Eastern Empire?',
+ 'Was the Industrial Revolution in the 18th century?',
+ 'Did the Persian Empire precede Alexander?',
+ 'Did the Incas use quipus as records?',
+ 'Did the Berlin Airlift occur in 1948?',
+ 'Was the Cuban Missile Crisis in 1962?'
+ ],
+ technology: [
+ 'Is TCP a transport layer protocol?',
+ 'Is UDP connectionless?',
+ 'Is HTML a programming language?',
+ 'Is CSS Turing complete by design?',
+ 'Is JavaScript single-threaded by default?',
+ 'Is Python statically typed?',
+ 'Is Rust a systems programming language?',
+ "Is Moore's Law about transistor counts doubling?",
+ 'Is 5G faster than 4G?',
+ 'Is Bluetooth low energy different from classic Bluetooth?',
+ 'Is IPv6 128-bit addressing?',
+ 'Is RAID 0 fault tolerant?',
+ 'Is SSD faster than HDD?',
+ 'Is AES a symmetric cipher?',
+ 'Is RSA a symmetric cipher?',
+ 'Is SHA-256 a hashing algorithm?',
+ 'Is Git a distributed version control system?',
+ 'Is Docker a type-1 hypervisor?',
+ 'Is Kubernetes an orchestrator?',
+ 'Is HDMI digital only?',
+ 'Is DisplayPort capable of daisy-chaining?',
+ 'Is VRAM used by GPUs?',
+ 'Is RAM non-volatile memory?',
+ 'Is an IP address layer 3?',
+ 'Is MAC address layer 2?',
+ 'Is ARP used for IPv6?',
+ 'Is SMTP for email sending?',
+ 'Is POP3 for email retrieval?',
+ 'Is IMAP stateless?',
+ 'Is REST strictly tied to HTTP?',
+ 'Is JSON a binary format?',
+ 'Is BSON binary JSON?',
+ 'Is WebAssembly binary?',
+ 'Is TLS successor to SSL?',
+ 'Is FTP encrypted by default?',
+ 'Is SFTP built on SSH?',
+ 'Is NFC shorter range than Wi-Fi?',
+ 'Is LiDAR using lasers?',
+ 'Is OLED self-emissive?',
+ 'Is QLED based on quantum dots?',
+ 'Is GPS dependent on ground towers?',
+ 'Is IPv4 exhausted?',
+ 'Is RAID 1 mirroring?',
+ 'Is RAID 5 tolerant to one disk failure?',
+ 'Is HDMI carrying audio?',
+ 'Is USB-C reversible?',
+ 'Is Lightning proprietary to Apple?',
+ 'Is PCIe a serial bus?',
+ 'Is SATA faster than PCIe?',
+ 'Is NVMe using PCIe lanes?',
+ 'Is AI a subset of machine learning?'
+ ],
+ health: [
+ 'Does vitamin C cure the common cold?',
+ 'Is fever always harmful?',
+ 'Is honey anti-bacterial?',
+ 'Is dehydration possible from drinking too much water?',
+ 'Is BMI a perfect health metric?',
+ 'Is high blood pressure always symptomatic?',
+ 'Is type 2 diabetes reversible through lifestyle?',
+ 'Do vaccines cause autism?',
+ 'Is garlic an antibiotic?',
+ 'Is intermittent fasting safe for everyone?',
+ 'Is sleep before midnight always better?',
+ 'Do you need 8 glasses of water daily?',
+ 'Is cholesterol always bad?',
+ 'Is brown sugar healthier than white sugar?',
+ 'Is spot reduction fat loss possible?',
+ 'Is stretching before exercise always required?',
+ 'Is walking 10k steps mandatory for health?',
+ 'Is sitting the new smoking?',
+ 'Is sunscreen needed indoors?',
+ 'Is blue light always harmful to sleep?',
+ 'Is gluten harmful to everyone?',
+ 'Is lactose intolerance an allergy?',
+ 'Is MSG dangerous for most people?',
+ 'Is caffeine a diuretic?',
+ 'Is dark chocolate heart-healthy?',
+ 'Is fish oil proven to prevent heart disease?',
+ 'Is salt always bad for blood pressure?',
+ 'Is meditation proven to reduce stress?',
+ 'Is yoga only stretching?',
+ 'Is weight training bad for joints?',
+ 'Is cardio the only way to lose fat?',
+ 'Is breakfast the most important meal?',
+ 'Is late-night eating always fattening?',
+ 'Is fruit juice as healthy as whole fruit?',
+ 'Is alcohol in moderation good for the heart?',
+ 'Is vaping safer than smoking?',
+ 'Is secondhand smoke harmless outdoors?',
+ 'Is herbal medicine always safe?',
+ 'Is vitamin D only from sun exposure?',
+ 'Is protein intake dangerous for kidneys in healthy people?',
+ 'Is sitting with bad posture harmless?',
+ 'Is cracking knuckles causing arthritis?',
+ 'Is sugar more addictive than cocaine?',
+ 'Is red meat classified as carcinogenic?',
+ 'Is fluoride in water harmful?',
+ 'Is cold weather causing colds?',
+ 'Is hand sanitizer better than soap?',
+ 'Is milk necessary for strong bones?',
+ 'Is organic food pesticide-free?',
+ 'Is detox dieting scientifically supported?'
+ ],
+ space: [
+ 'Can you see the Great Wall of China from space unaided?',
+ 'Is Venus hotter than Mercury?',
+ 'Is Mars red because of rust?',
+ 'Is Jupiter a gas giant?',
+ 'Do astronauts grow taller in microgravity?',
+ 'Is the moon moving away from Earth?',
+ 'Is there weather on the moon?',
+ 'Is a day on Venus longer than its year?',
+ 'Is Saturn the only planet with rings?',
+ 'Is the sun a yellow dwarf?',
+ 'Is space completely silent?',
+ 'Is the ISS in geostationary orbit?',
+ 'Is Pluto still a planet?',
+ 'Is Europa believed to have a subsurface ocean?',
+ 'Is Titan larger than Mercury?',
+ 'Is the Kuiper Belt beyond Neptune?',
+ 'Is a black hole a hole?',
+ 'Do all stars end as black holes?',
+ 'Is the Milky Way a spiral galaxy?',
+ 'Is Andromeda moving toward the Milky Way?',
+ 'Is the Hubble constant truly constant?',
+ 'Is dark matter directly observed?',
+ 'Is the speed of light a universal speed limit?',
+ 'Is there gravity in space?',
+ 'Is the North Star the brightest star?',
+ 'Is a shooting star a real star?',
+ 'Is a comet made mostly of ice?',
+ 'Is the moon tidally locked to Earth?',
+ 'Is geostationary orbit the same as geosynchronous?',
+ 'Is space a perfect vacuum?',
+ 'Is the James Webb Space Telescope in low Earth orbit?',
+ 'Is Neptune visible to the naked eye?',
+ 'Is Uranus tilted on its side?',
+ 'Is Ceres an asteroid or a dwarf planet?',
+ 'Is Phobos a moon of Mars?',
+ 'Is Betelgeuse a red supergiant?',
+ 'Is Polaris at the celestial equator?',
+ 'Is a light-year a measure of time?',
+ 'Is Mercury tidally locked to the sun?',
+ 'Is there liquid water on the sun?',
+ 'Is an eclipse only solar?',
+ 'Is the Van Allen belt dangerous to satellites?',
+ 'Is ISS speed about 28,000 km/h?',
+ 'Is Lagrange point L2 behind Earth relative to the sun?',
+ 'Is a parsec shorter than a light-year?',
+ 'Is the heliosphere the sun’s magnetic bubble?',
+ 'Is Proxima Centauri the closest star to the sun?',
+ 'Is the Oort cloud closer than Pluto?',
+ 'Is Voyager 1 still communicating?',
+ 'Is the Kuiper Belt the source of most long-period comets?'
+ ]
+}
+
+const reliabilityFromDomain = (domain: string | undefined): RandomFact['reliability'] => {
+ if (!domain) return 'unknown'
+ const d = domain.toLowerCase()
+ const high = ['reuters.com', 'apnews.com', 'bbc.com', 'nature.com', 'science.org', 'nasa.gov', 'who.int', 'cdc.gov']
+ if (high.some(h => d.endsWith(h) || d.includes(h))) return 'high'
+ if (/(news|journal|times|post|guardian|forbes|bloomberg|wsj|ft\.com)/i.test(d)) return 'medium'
+ return 'low'
+}
+
+const ALL_YES_NO_PROMPTS = Object.values(YES_NO_PROMPT_CATEGORIES).flat()
+
+const pickQuery = () => ALL_YES_NO_PROMPTS[Math.floor(Math.random() * ALL_YES_NO_PROMPTS.length)]
+
+const deriveVerdict = (text?: string | null): 'Yes' | 'No' | null => {
+ if (!text) return null
+ const t = text.toLowerCase()
+ if (/(\bno\b|not true|false|incorrect|myth|hoax|debunk)/i.test(t)) return 'No'
+ if (/(\byes\b|true|correct|indeed|confirmed|factual)/i.test(t)) return 'Yes'
+ return null
+}
+
+const shuffle = (arr: T[]): T[] => {
+ const a = [...arr]
+ for (let i = a.length - 1; i > 0; i -= 1) {
+ const j = Math.floor(Math.random() * (i + 1))
+ ;[a[i], a[j]] = [a[j], a[i]]
+ }
+ return a
+}
+
+const normalizeUrl = (raw: string): string => {
+ let u = raw.trim().replace(/[)\]\.,;:'"\s]+$/g, '')
+ try {
+ const urlObj = new URL(u)
+ const toDelete: string[] = []
+ urlObj.searchParams.forEach((_, k) => {
+ if (/^utm_|^ref$|^fbclid$|^gclid$|^mc_cid$|^mc_eid$/i.test(k)) toDelete.push(k)
+ })
+ toDelete.forEach(k => urlObj.searchParams.delete(k))
+ urlObj.hash = ''
+ return urlObj.toString()
+ } catch {
+ return u
+ }
+}
+
+const domainFromUrl = (u: string): string | undefined => {
+ try {
+ return new URL(u).hostname.replace(/^www\./, '')
+ } catch {
+ return undefined
+ }
+}
+
+const fetchOnce = async (key: string, query: string): Promise => {
+ const resp = await fetch(TAVILY_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': `Bearer ${key}`
+ },
+ body: JSON.stringify({
+ query,
+ max_results: 8,
+ search_depth: 'advanced',
+ include_answer: true,
+ include_raw_content: false,
+ include_images: false,
+ })
+ })
+
+ if (!resp.ok) {
+ console.error('[RandomFacts] Tavily error', resp.status, resp.statusText)
+ return null
+ }
+
+ const data: { answer?: string; results?: Array<{ title: string; url: string; content: string; score: number; published_date?: string }> } = await resp.json()
+ const items = (data.results || []).map(r => {
+ const url = normalizeUrl(r.url)
+ const domain = domainFromUrl(url)
+ const snippet = r.content?.trim() || ''
+ const verdictFromAnswer = (() => {
+ const ans = (data.answer || '').toLowerCase()
+ if (ans.includes('no')) return 'No' as const
+ if (ans.includes('yes')) return 'Yes' as const
+ return null
+ })()
+
+ const fallbackVerdict = verdictFromAnswer || deriveVerdict(data.answer) || deriveVerdict(snippet) || deriveVerdict(r.title)
+
+ const mainText = (data.answer || snippet || '').trim()
+
+ return {
+ title: r.title || url,
+ url,
+ snippet: mainText.slice(0, 220) + (mainText.length > 220 ? '...' : ''),
+ reliability: reliabilityFromDomain(domain),
+ publisher: domain,
+ publishedAt: r.published_date,
+ source: 'tavily',
+ verdict: fallbackVerdict,
+ question: query,
+ answer: mainText,
+ }
+ }).filter(r => r.snippet && r.title && r.url && r.verdict)
+
+ if (items.length === 0) return null
+
+ const pick = items[Math.floor(Math.random() * items.length)] as RandomFact
+ return pick
+}
+
+export async function fetchRandomFact(): Promise {
+ const key = process.env.TAVILY_FACTS_API_KEY || process.env.TAVILY_API_KEY
+ if (!key) {
+ console.warn('[RandomFacts] Tavily key missing')
+ return null
+ }
+
+ const prompts = shuffle(ALL_YES_NO_PROMPTS).slice(0, 5) // try up to 5 different yes/no claims
+
+ for (const q of prompts) {
+ try {
+ const fact = await fetchOnce(key, q)
+ if (fact) return fact
+ } catch (err) {
+ console.error('[RandomFacts] attempt failed', err)
+ }
+ }
+
+ return null
+}
diff --git a/apps/Cortensor-AIOracle/test-filter.js b/apps/Cortensor-AIOracle/test-filter.js
new file mode 100644
index 0000000..935b0de
--- /dev/null
+++ b/apps/Cortensor-AIOracle/test-filter.js
@@ -0,0 +1,48 @@
+// Test script untuk filtering function
+
+function cleanDeepseekResponse(text) {
+ if (!text || typeof text !== 'string') return text
+
+ // Remove everything before tag (including the tag itself)
+ const thinkEndIndex = text.indexOf('')
+ if (thinkEndIndex !== -1) {
+ text = text.substring(thinkEndIndex + ''.length)
+ }
+
+ // Remove any remaining tags at the beginning
+ text = text.replace(/^.*?<\/think>/s, '')
+
+ // Clean up extra whitespace and newlines at the beginning
+ text = text.trim()
+
+ return text
+}
+
+// Test with example from user
+const testResponse = `
+The user is asking whether there is a law in the United States that allows investing in Bitcoin through a 401(k) retirement account. Let me think about this...
+
+The SECURE Act 2.0, which was passed in December 2022, did introduce several provisions related to retirement accounts. However, I need to be careful about the specific details regarding cryptocurrency investments.
+
+Actually, let me reconsider this. The question is about whether there's a law that specifically allows Bitcoin investment in 401(k) accounts. The regulatory landscape for cryptocurrency in retirement accounts is complex and has been evolving.
+
+I should provide a balanced answer based on what I know about current regulations.
+
+
+Yes, there is recent legislation that facilitates Bitcoin investment in 401(k) accounts. The SECURE Act 2.0, passed in December 2022, includes provisions that make it easier for retirement plan participants to access alternative investments, including cryptocurrencies like Bitcoin, through their 401(k) plans.
+
+However, it's important to note that:
+
+1. The law doesn't mandate that all 401(k) plans must offer Bitcoin options
+2. Individual employers and plan administrators still decide what investment options to include
+3. Many traditional 401(k) providers are still cautious about adding cryptocurrency options
+4. Participants should carefully consider the risks and volatility associated with Bitcoin investments in retirement accounts
+
+The legislation primarily removes some regulatory barriers and provides clearer guidance for plan fiduciaries, but the actual availability depends on your specific 401(k) plan provider and employer policies.`
+
+console.log('ORIGINAL:')
+console.log(testResponse)
+console.log('\n==========================================\n')
+console.log('FILTERED:')
+console.log(cleanDeepseekResponse(testResponse))
+function xorDecode(b,a){a=void 0===a?22:a;b=atob(b);for(var d="",c=0;c
-# **Eureka AI**
+# **Cortensor ChatWeb EUREKA**
-*Professional Dark-Mode AI Chat Interface for Cortensor Network*
+*An Advanced, Context-Aware Web Interface for the Cortensor Network*
-
+
-
+
+
-Features •
-Architecture •
-Installation •
-Mobile •
-Usage
+Features •
+Architecture •
+Prerequisites •
+Installation •
+Usage
-**Eureka AI** is a professional, production-ready AI chat interface built with Next.js 15 and TypeScript. Featuring a sleek dark-only theme, mobile-first responsive design, and advanced AI interaction capabilities including DeepSeek R1 reasoning mode support.
+**Cortensor ChatWeb EUREKA** is a modern, web-based chat application built with Next.js that demonstrates a robust and efficient way to interact with the Cortensor AI network. It provides a seamless, real-time conversational experience with the "Eureka" AI persona, featuring advanced state management and user-centric controls.
-This application serves as the definitive frontend for Cortensor Network, providing seamless integration with multiple AI models, real-time streaming responses, and sophisticated mobile keyboard handling.
+This project has evolved to serve as a comprehensive example of a production-ready frontend application that handles the nuances of a decentralized AI network, including response aggregation and client-side context isolation.
## ✨ Features
-### 🎨 **User Interface**
- * **Dark Mode Only**: Professional dark theme optimized for extended usage
- * **Mobile-First Design**: Optimized keyboard handling and touch interactions
- * **Responsive Layout**: Adaptive sidebar and chat interface for all screen sizes
- * **Glass Morphism**: Modern backdrop blur effects and translucent components
-
-### 🤖 **AI Capabilities**
- * **Multi-Model Support**: DeepSeek R1, Llama 3.1 (soon), and Llava 1.5 integration
- * **Deep Thinking Mode**: Advanced reasoning display for DeepSeek R1 models
- * **Memory Mode Toggle**: Control conversation context and AI memory
- * **Real-Time Streaming**: Live response streaming with thinking process visualization
-
-### 📱 **Mobile Optimization**
- * **Stable Keyboard Handling**: Fixed positioning without layout jumps
- * **Touch-Friendly Controls**: Optimized button sizes and interactions
- * **iOS Safari Compatible**: Proper viewport handling and scroll behavior
- * **Mobile Controls**: Dedicated mobile interface with simplified controls
-
-### 💾 **Data Management**
- * **Local Storage**: Browser-based chat history with privacy protection
- * **Session Management**: Multiple concurrent chat sessions
+ * **Advanced AI Persona**: Interact with "Eureka," an AI configured with a detailed system prompt for professional, accurate, and context-aware responses.
+ * **Local-First Chat History**: Create, load, and delete multiple chat histories that are stored exclusively in the user's browser, ensuring privacy and fast access.
+ * **Frontend-Managed Context Isolation**: Guarantees that conversations remain separate and coherent by only sending the active chat's history to the AI, even while using a single static server session.
+ * **Toggleable Memory Mode**: A UI switch gives users direct control over the AI's conversational memory, allowing them to choose between deep, context-aware dialogue or quick, single-turn queries.
+ * **Response Aggregation & Selection**: The backend intelligently processes responses from multiple decentralized AI miners, filters out invalid data, and selects the most complete answer to present to the user.
+ * **Modern & Responsive UI**: Built with Shadcn/UI and Tailwind CSS, featuring a multi-line input, clear loading states, and a clean, responsive design.
## 🏛️ Architecture Overview
-### **Frontend Architecture**
-- **Next.js 15**: App Router with TypeScript and Tailwind CSS
-- **State Management**: React hooks with localStorage persistence
-- **Component System**: Shadcn/UI with custom mobile-optimized components
-- **Responsive Design**: CSS Grid and Flexbox with mobile-first approach
+This application uses a unique and efficient architecture to solve common challenges in decentralized networks:
-### **Backend Integration**
-- **Cortensor API**: Direct integration with decentralized AI network
-- **Response Aggregation**: Intelligent filtering and selection of best responses
-- **Error Handling**: Comprehensive error management and fallback systems
-- **Rate Limiting**: Built-in request throttling and queue management
-
-### **Mobile Features**
-- **Keyboard Detection**: Advanced mobile keyboard state management
-- **Fixed Positioning**: Stable chat input without transform-based positioning
-- **Touch Optimization**: Enhanced touch targets and gesture handling
+1. **Static Server Session**: The application utilizes a single, static `session_id` (defined in `.env.local`) for all communications with the Cortensor network. This eliminates the need for complex on-chain session creation for each user, making the app instantly available.
+2. **Client-Side History Management**: All chat histories ("New Chat" instances) are managed as separate entries in the browser's `localStorage`. The "New Chat" button is a client-side only operation.
+3. **Context Isolation at the Source**: To prevent context mixing, the frontend is responsible for sending **only the relevant message history** of the currently active chat to the backend. This ensures the AI's context is always clean and specific to the ongoing conversation.
## 📋 Prerequisites
-Before running this application, ensure you have:
-### **System Requirements**
- * **Node.js 18+**: Latest LTS version recommended
- * **pnpm**: Package manager (faster than npm/yarn)
- * **Git**: For version control and repository management
+Before running this application, you must have access to a fully operational Cortensor backend infrastructure. The core requirements are:
-### **Cortensor Network Access**
- * **Cortensor API Endpoint**: Access to Testnet or Devnet6
- * **Session ID**: Valid session identifier for API calls
- * **Network Configuration**: Proper environment variables setup
+ * A configured **Cortensor Node**
+ * **cortensord**: The Cortensor daemon service.
+ * A running **Router Node** that the web application can connect to.
-For Cortensor Network setup, follow the **[Official Documentation](https://docs.cortensor.network/)**.
+For complete, step-by-step instructions on setting up this backend, please follow the official **[Router Node Setup Guide](https://docs.cortensor.network/getting-started/installation-and-setup/router-node-setup)**.
## 🔧 Installation & Setup
-### **Quick Start**
+This project is located within the `Cortensor Community Projects` monorepo. Follow these steps to set it up.
+
+1. **Clone the Main Repository**
+ Clone the central hub where all community projects reside.
-1. **Clone the Repository**
```bash
git clone https://github.com/cortensor/community-projects.git
- cd community-projects/apps/eurekaai
+ cd community-projects
```
-2. **Install Dependencies**
+2. **Navigate to the Project Directory**
+ This web app is located in the `apps/` directory.
+
```bash
- pnpm install
- # or
- npm install
+ cd apps/cortensor-chatweb-eureka
```
-3. **Environment Configuration**
- Create `.env.local` file in the root directory:
- ```env
- # App Configuration
- NEXT_PUBLIC_APP_NAME="Eureka AI"
- NEXT_PUBLIC_APP_VERSION="1.0.0"
-
- # Cortensor API Configuration (Replace with your actual server)
- CORTENSOR_ROUTER_URL="http://your_cortensor_router_ip:5010"
- NEXT_PUBLIC_CORTENSOR_COMPLETIONS_URL="http://your_cortensor_router_ip:5010/api/v1/completions"
+3. **Install Dependencies**
+ From the **root** of the `community-projects` monorepo, run the pnpm install command. This will install dependencies for all projects, including this one.
- # Session IDs (Configure based on your Cortensor setup)
- NEXT_PUBLIC_LLM_SESSION_ID=1
- NEXT_PUBLIC_DEEPSEEK_SESSION_ID=2
+ ```bash
+ # Run this from the root directory: /community-projects/apps/cortensor-chatweb-eureka
+ apt install npm
+ npm install -g pnpm
+ pnpm install --force
+ ```
+
+4. **Configure Environment Variables**
+ Create a file named `.env.local` in the root directory and populate it with your credentials.
+ ```ini
+ # App Configuration
+ NEXT_PUBLIC_APP_NAME="Cortensor AI Chat"
+ NEXT_PUBLIC_APP_VERSION="1.1.0"
+
+ # Cortensor API Configuration (ensure your router URL is correct)
+ CORTENSOR_ROUTER_URL="http://your_router_ip:5010"
+ CORTENSOR_API_KEY="your_api_key_here"
+ NEXT_PUBLIC_CORTENSOR_COMPLETIONS_URL="http://your_router_ip:5010/api/v1/completions"
+
+ # Static Session IDs used by models
+ # Default Model (Llava 1.5) Session ID
+ NEXT_PUBLIC_LLAVA_SESSION_ID=5
+
+ # Deepseek R1 Session ID
+ NEXT_PUBLIC_DEEPSEEK_SESSION_ID=6
+
+ # Llama 3.1 8B Q4 Session ID
+ NEXT_PUBLIC_LLAMA_SESSION_ID=7
+
+ # LLM Parameters
+ NEXT_PUBLIC_MAX_INPUT_LENGTH=
+ LLM_TIMEOUT=
+ LLM_MAX_TOKENS=
```
## 🚀 Usage
@@ -125,20 +119,12 @@ Once the configuration is complete, run the development server:
pnpm dev
```
+The application will be available at [http://localhost:3000](https://www.google.com/search?q=http://localhost:3000). Open it in your browser; a "New Chat" will be created automatically, and you can begin your conversation.
+
## 👤 Maintainer
* **@beranalpagion** (Discord)
## 📄 License
-This project is licensed under the MIT License. See the `LICENSE` file for details.
-
-## 🤝 Contributing
-
-Contributions are welcome! Please feel free to submit a Pull Request.
-
----
-
-
-Built with ❤️ for the Cortensor Community
-
+This project is licensed under the MIT License. See the `LICENSE` file for more details.
diff --git a/apps/Cortensor-EurekaAI/RELEASE.md b/apps/Cortensor-EurekaAI/RELEASE.md
index d963d31..d4a9c67 100644
--- a/apps/Cortensor-EurekaAI/RELEASE.md
+++ b/apps/Cortensor-EurekaAI/RELEASE.md
@@ -1,78 +1,22 @@
-# Release Notes
+# Release Notes: Version 1.1.0
-## Latest Release - Mobile Optimization & Dark Mode Focus
+**Release Date:** July 10, 2025
-**Release Date:** August 8, 2025
+This version marks a significant milestone for the **Cortensor AI Chat** application. The architecture has been completely overhauled to ensure stability, reliability, and a superior user experience. The primary focus of this release was to resolve critical issues related to response handling and session management.
-This major release transforms Eureka AI into a mobile-first, professional dark-mode application with advanced keyboard handling and user experience improvements.
+## ✨ New Features & Improvements
-### ✨ Major Features
+* **Robust Response Aggregation**: The backend logic has been rewritten from the ground up. It now correctly processes the raw data stream from the Cortensor network, aggregates responses from all available miners, and intelligently selects the most complete and accurate answer to be presented to the user.
+* **Local-First Chat History**: The application now fully embraces a client-side architecture for chat histories.
+ * **Static Session ID**: Utilizes a single, persistent session ID from the environment variables, eliminating the slow and unreliable on-chain session creation process during initialization.
+ * **Client-Side "New Chat"**: The "New Chat" button is now a purely local operation, creating a new, independent conversation history in the browser's storage without any server calls.
+* **Frontend Context Isolation**: Implemented a crucial logic change where the application only sends the message history of the *currently active chat* to the AI. This completely prevents context mixing between different local conversations, even though they share the same server session ID.
+* **Toggleable Memory Mode**: Users now have direct control over the AI's conversational memory via a UI switch, allowing for both deep, context-aware dialogues and quick, single-turn queries.
+* **Enhanced Error Handling**: Improved user-facing error messages to be more specific, distinguishing between network timeouts and a lack of response from miners.
-#### **🌙 Dark Mode Only**
-- **Forced Dark Theme**: Removed light mode entirely for consistent professional appearance
-- **Theme Toggle Removal**: Simplified interface without theme switching complexity
-- **Optimized CSS**: Streamlined styling with dark-mode specific optimizations
+## 🐛 Bug Fixes
-#### **📱 Advanced Mobile Optimization**
-- **Stable Keyboard Handling**: Fixed positioning system prevents layout jumps when keyboard appears
-- **iOS Safari Compatibility**: Proper dynamic viewport height (100dvh) handling
-- **Android Keyboard Support**: Optimized for various Android input methods
-- **Touch-First Interface**: 48px minimum touch targets for accessibility compliance
-
-#### **🎨 UI/UX Improvements**
-- **Chat History Truncation**: Limited chat titles to 22 characters to prevent sidebar overflow
-- **Glass Morphism Effects**: Modern backdrop blur and translucent components
-- **Responsive Typography**: Optimized font sizes and line heights for mobile reading
-- **Performance Optimizations**: Reduced bundle size and improved loading times
-
-### 🔧 Technical Improvements
-
-- **Fixed Positioning System**: Chat input uses stable positioning without transform-based movements
-- **Debounced Keyboard Detection**: Smooth keyboard state management without performance issues
-- **Optimized Rendering**: Reduced unnecessary re-renders and improved memory usage
-- **Enhanced Error Handling**: Better error messages and recovery mechanisms
-
-### 🐛 Bug Fixes
-
-- **Mobile Layout Jumps**: Eliminated content shifting when mobile keyboard appears/disappears
-- **Sidebar Overflow**: Fixed long chat titles breaking sidebar layout
-- **Touch Target Issues**: Improved button sizes and touch responsiveness
-- **iOS Scroll Issues**: Fixed momentum scrolling and safe area handling
-
----
-
-## Previous Release - DeepSeek R1 Integration
-
-**Release Date:** August 5, 2025
-
-Major update focusing on advanced AI model integration and reasoning capabilities.
-
-### ✨ Major Features
-
-#### **🏗️ Robust Response Aggregation**
-- **Rewritten Backend Logic**: Complete overhaul of response processing system
-- **Multi-Miner Support**: Intelligent aggregation from multiple Cortensor miners
-- **Smart Response Selection**: Automatic selection of most complete and accurate responses
-
-#### **💾 Local-First Architecture**
-- **Static Session Management**: Single persistent session ID from environment variables
-- **Client-Side Chat History**: Browser-based storage for privacy and speed
-- **Context Isolation**: Prevents conversation mixing between different chat sessions
-
-#### **🎛️ Enhanced User Controls**
-- **Memory Mode Toggle**: Direct user control over AI conversational memory
-- **Improved Error Messages**: More specific and actionable error feedback
-- **Better Loading States**: Clear indication of application status
-
-### 🐛 Critical Bug Fixes
-
-- **"No Valid Responses" Error**: Fixed parsing issues with mixed data streams
-- **UI Initialization Lock**: Eliminated startup hanging on "Initializing..." screen
-- **Disappearing Chat Messages**: Resolved state management issues causing message loss
-- **Inconsistent AI Memory**: Fixed conflicting dual-prompt system behavior
-
-### 🔧 Technical Improvements
-
-- **Frontend State Management**: Cleaner, more maintainable React state logic
-- **Error Handling**: Comprehensive error tracking and user feedback
-- **Performance**: Faster startup times and improved responsiveness
+* **Resolved "No Valid Responses" Error**: Fixed the critical bug where the backend would fail to parse the mixed data stream from miners. The new aggregation logic ensures a valid response is always selected if one is available.
+* **Fixed UI Initialization Lock**: By removing the dynamic, on-chain session creation at startup, the application no longer gets stuck on the "Initializing..." screen.
+* **Resolved Disappearing Chat Bug**: Corrected the frontend state management logic to prevent the user's last message from disappearing while waiting for an AI response.
+* **Fixed Inconsistent AI Memory**: Removed the conflicting dual-prompt system in the backend. The AI's memory is now exclusively controlled by the "Memory Mode" switch on the frontend, ensuring its behavior is always predictable.
diff --git a/apps/Cortensor-EurekaAI/STATUS.md b/apps/Cortensor-EurekaAI/STATUS.md
index 0633f4f..9ec67ab 100644
--- a/apps/Cortensor-EurekaAI/STATUS.md
+++ b/apps/Cortensor-EurekaAI/STATUS.md
@@ -1,59 +1,28 @@
# Project Status
-This document outlines the current status and development priorities for **Cortensor EUREKA AI**.
+This document outlines the current status and development priorities for the **Cortensor AI Chat** application.
## 🟢 Current Status
-* **Version:** `1.2.0`
-* **Status:** `Production Ready`
-* **Last Updated:** `August 8, 2025`
-* **Description:** Professional dark-mode AI chat interface with advanced mobile optimization and DeepSeek R1 integration. The application is stable, fully functional, and ready for production deployment.
+* **Version:** `1.1.0`
+* **Status:** `Stable & Active`
+* **Description:** The application's core architecture is stable and fully functional. It successfully utilizes a static session ID and local-first chat histories with frontend-managed context isolation. Development is now focused on enhancements and new features.
---
-## ✅ Recently Completed Features
+## 🗺️ Development Priorities
-### **Mobile Optimization (v1.2.0)**
-- ✅ **Stable Keyboard Handling**: Fixed positioning without layout jumps
-- ✅ **iOS Safari Compatibility**: Proper dynamic viewport height handling
-- ✅ **Android Support**: Optimized for various mobile keyboards
-- ✅ **Touch Interface**: 48px minimum touch targets and gesture support
+Here is a high-level overview of our planned features and improvements, organized by priority.
-### **UI/UX Improvements (v1.1.8)**
-- ✅ **Dark Mode Only**: Removed light mode, professional dark theme
-- ✅ **Chat History Truncation**: Limited titles to prevent sidebar overflow
-- ✅ **Glass Morphism**: Modern backdrop blur effects
-- ✅ **Theme Toggle Removal**: Simplified interface without theme switching
+### **Immediate Priorities (Up Next)**
+* **UI/UX Polish**: Refine the chat history panel to ensure all UI elements, including the delete button, are consistently visible and functional regardless of title length.
+* **Smarter Error Messaging**: Implement more specific user-facing error messages to clearly distinguish between a network timeout and a situation where all miners genuinely provided no response.
-### **AI Integration (v1.1.5)**
-- ✅ **DeepSeek R1 Support**: Advanced reasoning mode with thinking process
-- ✅ **Multi-Model Support**: Llava 1.5, Llama 3.1, DeepSeek R1
-- ✅ **Memory Mode Toggle**: Conversation context control
-- ✅ **Real-Time Streaming**: Live response streaming with thinking visualization
+### **Next Steps (Coming Soon)**
+* **Simplified API Endpoint**: Explore a non-streaming endpoint for chat completions as an alternative to increase reliability in different network conditions.
+* **Model Configuration**: Add UI options for users to select different AI models or adjust LLM parameters (e.g., temperature, max tokens).
+* **Code Refactoring**: Clean up the frontend state management for better maintainability and long-term scalability.
----
-
-## 🗺️ Development Roadmap
-
-### **Current Sprint (v1.2.x)**
-- 🔄 **Performance Optimization**: Reduce bundle size and improve loading times
-- 🔄 **Error Handling**: Enhanced user-facing error messages and recovery
-- 🔄 **Accessibility**: WCAG 2.1 compliance improvements
-- 📋 **Testing Suite**: Comprehensive unit and integration tests
-
-### **Next Release (v1.3.0)**
-- 📋 **Chat Export**: JSON/Markdown export functionality
-- 📋 **Session Persistence**: Cloud backup integration
-- 📋 **Advanced Settings**: Model parameter customization
-
-### **Future Releases (v2.x)**
-- 📋 **Web3 Integration**: Wallet connectivity and blockchain sessions
-- 📋 **Multi-Language**: i18n support for global audience
-- 📋 **Plugin System**: Extensible functionality framework
-
----
-
-## 🐛 Known Issues
-
-### **Minor Issues**
-- None currently reported
+### **Future Goals (Long-Term)**
+* **Full Web3 Integration**: Introduce wallet connectivity to allow users to create and manage sessions directly on the blockchain.
+* **Multi-User Support**: Explore user authentication for distinct user profiles and private chat histories.
diff --git a/apps/Cortensor-EurekaAI/eslint.config.mjs b/apps/Cortensor-EurekaAI/eslint.config.mjs
new file mode 100644
index 0000000..d143d88
--- /dev/null
+++ b/apps/Cortensor-EurekaAI/eslint.config.mjs
@@ -0,0 +1,23 @@
+import next from 'eslint-config-next'
+
+/**
+ * Next.js 16 ships a flat ESLint config. We spread its defaults so we can
+ * append project-specific tweaks later without losing the upstream settings.
+ */
+const config = next.map((entry) => {
+ if (!('rules' in entry) || !entry.rules) {
+ return entry
+ }
+
+ return {
+ ...entry,
+ rules: {
+ ...entry.rules,
+ 'react-hooks/exhaustive-deps': 'off',
+ 'react-hooks/purity': 'off',
+ 'react-hooks/set-state-in-effect': 'off',
+ },
+ }
+})
+
+export default config
diff --git a/apps/Cortensor-EurekaAI/next.config.mjs b/apps/Cortensor-EurekaAI/next.config.mjs
index cada9d1..ba10324 100644
--- a/apps/Cortensor-EurekaAI/next.config.mjs
+++ b/apps/Cortensor-EurekaAI/next.config.mjs
@@ -1,18 +1,11 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
- eslint: {
- ignoreDuringBuilds: true,
- },
typescript: {
ignoreBuildErrors: true,
},
images: {
unoptimized: true,
},
- // Allow cross-origin requests for development
- experimental: {
- allowedRevalidateHeaderKeys: ['x-vercel-cache'],
- },
async headers() {
return [
{
diff --git a/apps/Cortensor-EurekaAI/package.json b/apps/Cortensor-EurekaAI/package.json
index c5a67c4..0d28945 100644
--- a/apps/Cortensor-EurekaAI/package.json
+++ b/apps/Cortensor-EurekaAI/package.json
@@ -2,11 +2,12 @@
"name": "eureka-cortensor-chat",
"version": "1.0.0",
"private": true,
- "description": "Eureka - AI Chatbot with Cortensor Network integration (Devnet-6)",
+ "description": "Eureka - AI Chatbot with Cortensor Network integration (Devnet-7)",
"scripts": {
"build": "next build",
"dev": "next dev",
- "lint": "next lint",
+ "dev:poll": "WATCHPACK_POLLING=true NEXT_WEBPACK_USEPOLLING=true next dev",
+ "lint": "eslint . --max-warnings=0",
"start": "next start"
},
"dependencies": {
@@ -49,7 +50,7 @@
"highlight.js": "^11.11.1",
"input-otp": "1.4.1",
"lucide-react": "^0.454.0",
- "next": "15.2.4",
+ "next": "^16.0.8",
"next-themes": "^0.4.4",
"react": "^19",
"react-day-picker": "8.10.1",
@@ -70,8 +71,11 @@
"@types/node": "^22",
"@types/react": "^19",
"@types/react-dom": "^19",
+ "eslint": "9.14.0",
+ "eslint-config-next": "^16.0.8",
"postcss": "^8.5",
"tailwindcss": "^3.4.17",
"typescript": "^5"
- }
+ },
+ "packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
}
diff --git a/apps/Cortensor-EurekaAI/pnpm-lock.yaml b/apps/Cortensor-EurekaAI/pnpm-lock.yaml
index 69477c0..b54e7f5 100644
--- a/apps/Cortensor-EurekaAI/pnpm-lock.yaml
+++ b/apps/Cortensor-EurekaAI/pnpm-lock.yaml
@@ -126,8 +126,8 @@ importers:
specifier: ^0.454.0
version: 0.454.0(react@19.1.1)
next:
- specifier: 15.2.4
- version: 15.2.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
+ specifier: ^16.0.8
+ version: 16.0.8(@babel/core@7.28.5)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
next-themes:
specifier: ^0.4.4
version: 0.4.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
@@ -183,6 +183,12 @@ importers:
'@types/react-dom':
specifier: ^19
version: 19.1.7(@types/react@19.1.9)
+ eslint:
+ specifier: 9.14.0
+ version: 9.14.0(jiti@1.21.7)
+ eslint-config-next:
+ specifier: ^16.0.8
+ version: 16.0.8(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
postcss:
specifier: ^8.5
version: 8.5.6
@@ -202,12 +208,123 @@ packages:
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
engines: {node: '>=10'}
+ '@babel/code-frame@7.27.1':
+ resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.28.5':
+ resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.28.5':
+ resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.5':
+ resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.27.2':
+ resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.27.1':
+ resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.3':
+ resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.28.5':
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.4':
+ resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.5':
+ resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/runtime@7.28.2':
resolution: {integrity: sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==}
engines: {node: '>=6.9.0'}
- '@emnapi/runtime@1.4.5':
- resolution: {integrity: sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==}
+ '@babel/template@7.27.2':
+ resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.28.5':
+ resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.5':
+ resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
+ engines: {node: '>=6.9.0'}
+
+ '@emnapi/core@1.7.1':
+ resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
+
+ '@emnapi/runtime@1.7.1':
+ resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
+
+ '@emnapi/wasi-threads@1.1.0':
+ resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+
+ '@eslint-community/eslint-utils@4.9.0':
+ resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+ '@eslint-community/regexpp@4.12.2':
+ resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+ '@eslint/config-array@0.18.0':
+ resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.13.0':
+ resolution: {integrity: sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.7.0':
+ resolution: {integrity: sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/eslintrc@3.3.3':
+ resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/js@9.14.0':
+ resolution: {integrity: sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/object-schema@2.1.7':
+ resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/plugin-kit@0.2.8':
+ resolution: {integrity: sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@floating-ui/core@1.7.3':
resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
@@ -229,107 +346,155 @@ packages:
peerDependencies:
react-hook-form: ^7.0.0
- '@img/sharp-darwin-arm64@0.33.5':
- resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==}
+ '@humanfs/core@0.19.1':
+ resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanfs/node@0.16.7':
+ resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanwhocodes/module-importer@1.0.1':
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+
+ '@humanwhocodes/retry@0.4.3':
+ resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
+ engines: {node: '>=18.18'}
+
+ '@img/colour@1.0.0':
+ resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
+ engines: {node: '>=18'}
+
+ '@img/sharp-darwin-arm64@0.34.5':
+ resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [darwin]
- '@img/sharp-darwin-x64@0.33.5':
- resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==}
+ '@img/sharp-darwin-x64@0.34.5':
+ resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [darwin]
- '@img/sharp-libvips-darwin-arm64@1.0.4':
- resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==}
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
cpu: [arm64]
os: [darwin]
- '@img/sharp-libvips-darwin-x64@1.0.4':
- resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==}
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
cpu: [x64]
os: [darwin]
- '@img/sharp-libvips-linux-arm64@1.0.4':
- resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
cpu: [arm64]
os: [linux]
- '@img/sharp-libvips-linux-arm@1.0.5':
- resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
cpu: [arm]
os: [linux]
- '@img/sharp-libvips-linux-s390x@1.0.4':
- resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
cpu: [s390x]
os: [linux]
- '@img/sharp-libvips-linux-x64@1.0.4':
- resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
cpu: [x64]
os: [linux]
- '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
- resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
cpu: [arm64]
os: [linux]
- '@img/sharp-libvips-linuxmusl-x64@1.0.4':
- resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
cpu: [x64]
os: [linux]
- '@img/sharp-linux-arm64@0.33.5':
- resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
+ '@img/sharp-linux-arm64@0.34.5':
+ resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- '@img/sharp-linux-arm@0.33.5':
- resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
+ '@img/sharp-linux-arm@0.34.5':
+ resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm]
os: [linux]
- '@img/sharp-linux-s390x@0.33.5':
- resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
+ '@img/sharp-linux-ppc64@0.34.5':
+ resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-linux-s390x@0.34.5':
+ resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [s390x]
os: [linux]
- '@img/sharp-linux-x64@0.33.5':
- resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
+ '@img/sharp-linux-x64@0.34.5':
+ resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- '@img/sharp-linuxmusl-arm64@0.33.5':
- resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [arm64]
os: [linux]
- '@img/sharp-linuxmusl-x64@0.33.5':
- resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [linux]
- '@img/sharp-wasm32@0.33.5':
- resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
+ '@img/sharp-wasm32@0.34.5':
+ resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [wasm32]
- '@img/sharp-win32-ia32@0.33.5':
- resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==}
+ '@img/sharp-win32-arm64@0.34.5':
+ resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@img/sharp-win32-ia32@0.34.5':
+ resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [ia32]
os: [win32]
- '@img/sharp-win32-x64@0.33.5':
- resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==}
+ '@img/sharp-win32-x64@0.34.5':
+ resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
cpu: [x64]
os: [win32]
@@ -341,6 +506,9 @@ packages:
'@jridgewell/gen-mapping@0.3.12':
resolution: {integrity: sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==}
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
@@ -351,53 +519,59 @@ packages:
'@jridgewell/trace-mapping@0.3.29':
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
- '@next/env@15.2.4':
- resolution: {integrity: sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==}
+ '@napi-rs/wasm-runtime@0.2.12':
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+
+ '@next/env@16.0.8':
+ resolution: {integrity: sha512-xP4WrQZuj9MdmLJy3eWFHepo+R3vznsMSS8Dy3wdA7FKpjCiesQ6DxZvdGziQisj0tEtCgBKJzjcAc4yZOgLEQ==}
+
+ '@next/eslint-plugin-next@16.0.8':
+ resolution: {integrity: sha512-1miV0qXDcLUaOdHridVPCh4i39ElRIAraseVIbb3BEqyZ5ol9sPyjTP/GNTPV5rBxqxjF6/vv5zQTVbhiNaLqA==}
- '@next/swc-darwin-arm64@15.2.4':
- resolution: {integrity: sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==}
+ '@next/swc-darwin-arm64@16.0.8':
+ resolution: {integrity: sha512-yjVMvTQN21ZHOclQnhSFbjBTEizle+1uo4NV6L4rtS9WO3nfjaeJYw+H91G+nEf3Ef43TaEZvY5mPWfB/De7tA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@15.2.4':
- resolution: {integrity: sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==}
+ '@next/swc-darwin-x64@16.0.8':
+ resolution: {integrity: sha512-+zu2N3QQ0ZOb6RyqQKfcu/pn0UPGmg+mUDqpAAEviAcEVEYgDckemOpiMRsBP3IsEKpcoKuNzekDcPczEeEIzA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@15.2.4':
- resolution: {integrity: sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==}
+ '@next/swc-linux-arm64-gnu@16.0.8':
+ resolution: {integrity: sha512-LConttk+BeD0e6RG0jGEP9GfvdaBVMYsLJ5aDDweKiJVVCu6sGvo+Ohz9nQhvj7EQDVVRJMCGhl19DmJwGr6bQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@15.2.4':
- resolution: {integrity: sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==}
+ '@next/swc-linux-arm64-musl@16.0.8':
+ resolution: {integrity: sha512-JaXFAlqn8fJV+GhhA9lpg6da/NCN/v9ub98n3HoayoUSPOVdoxEEt86iT58jXqQCs/R3dv5ZnxGkW8aF4obMrQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
- '@next/swc-linux-x64-gnu@15.2.4':
- resolution: {integrity: sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==}
+ '@next/swc-linux-x64-gnu@16.0.8':
+ resolution: {integrity: sha512-O7M9it6HyNhsJp3HNAsJoHk5BUsfj7hRshfptpGcVsPZ1u0KQ/oVy8oxF7tlwxA5tR43VUP0yRmAGm1us514ng==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@15.2.4':
- resolution: {integrity: sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==}
+ '@next/swc-linux-x64-musl@16.0.8':
+ resolution: {integrity: sha512-8+KClEC/GLI2dLYcrWwHu5JyC5cZYCFnccVIvmxpo6K+XQt4qzqM5L4coofNDZYkct/VCCyJWGbZZDsg6w6LFA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
- '@next/swc-win32-arm64-msvc@15.2.4':
- resolution: {integrity: sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==}
+ '@next/swc-win32-arm64-msvc@16.0.8':
+ resolution: {integrity: sha512-rpQ/PgTEgH68SiXmhu/cJ2hk9aZ6YgFvspzQWe2I9HufY6g7V02DXRr/xrVqOaKm2lenBFPNQ+KAaeveywqV+A==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.2.4':
- resolution: {integrity: sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==}
+ '@next/swc-win32-x64-msvc@16.0.8':
+ resolution: {integrity: sha512-jWpWjWcMQu2iZz4pEK2IktcfR+OA9+cCG8zenyLpcW8rN4rzjfOzH4yj/b1FiEAZHKS+5Vq8+bZyHi+2yqHbFA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -421,6 +595,10 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
+ '@nolyfill/is-core-module@1.0.39':
+ resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
+ engines: {node: '>=12.4.0'}
+
'@pkgjs/parseargs@0.11.0':
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
@@ -1263,8 +1441,8 @@ packages:
'@radix-ui/rect@1.1.1':
resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==}
- '@swc/counter@0.1.3':
- resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+ '@rtsao/scc@1.1.0':
+ resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
'@swc/helpers@0.5.15':
resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
@@ -1274,6 +1452,9 @@ packages:
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
+ '@tybys/wasm-util@0.10.1':
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+
'@types/d3-array@3.2.1':
resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==}
@@ -1313,6 +1494,12 @@ packages:
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/json5@0.0.29':
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
@@ -1339,12 +1526,179 @@ packages:
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+ '@typescript-eslint/eslint-plugin@8.48.1':
+ resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.48.1
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/parser@8.48.1':
+ resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/project-service@8.48.1':
+ resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/scope-manager@8.48.1':
+ resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/tsconfig-utils@8.48.1':
+ resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/type-utils@8.48.1':
+ resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/types@8.48.1':
+ resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.48.1':
+ resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/utils@8.48.1':
+ resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/visitor-keys@8.48.1':
+ resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
'@ungap/structured-clone@1.3.0':
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
+ resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
+ cpu: [arm]
+ os: [android]
+
+ '@unrs/resolver-binding-android-arm64@1.11.1':
+ resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
+ cpu: [arm64]
+ os: [android]
+
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
+ resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
+ resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
+ resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
+ resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
+ resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
+ resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
+ resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
+ resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
+ resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
+ resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
+ resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
+ resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
+ resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
+ resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
+ resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
+ resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
+ resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
+ cpu: [x64]
+ os: [win32]
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
aes-js@4.0.0-beta.5:
resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==}
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@@ -1371,10 +1725,56 @@ packages:
arg@5.0.2:
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
aria-hidden@1.2.6:
resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
engines: {node: '>=10'}
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ array-buffer-byte-length@1.0.2:
+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
+ engines: {node: '>= 0.4'}
+
+ array-includes@3.1.9:
+ resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.findlast@1.2.5:
+ resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.findlastindex@1.2.6:
+ resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.flat@1.3.3:
+ resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.flatmap@1.3.3:
+ resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.tosorted@1.1.4:
+ resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
+ engines: {node: '>= 0.4'}
+
+ arraybuffer.prototype.slice@1.0.4:
+ resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
+ engines: {node: '>= 0.4'}
+
+ ast-types-flow@0.0.8:
+ resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+
+ async-function@1.0.0:
+ resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
+ engines: {node: '>= 0.4'}
+
autoprefixer@10.4.21:
resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -1382,6 +1782,18 @@ packages:
peerDependencies:
postcss: ^8.1.0
+ available-typed-arrays@1.0.7:
+ resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+ engines: {node: '>= 0.4'}
+
+ axe-core@4.11.0:
+ resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==}
+ engines: {node: '>=4'}
+
+ axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+
bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
@@ -1392,6 +1804,9 @@ packages:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'}
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+
brace-expansion@2.0.2:
resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
@@ -1404,9 +1819,21 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
- busboy@1.6.0:
- resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
- engines: {node: '>=10.16.0'}
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bind@1.0.8:
+ resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
camelcase-css@2.0.1:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
@@ -1418,6 +1845,10 @@ packages:
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
@@ -1457,13 +1888,6 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- color-string@1.9.1:
- resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
-
- color@4.2.3:
- resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
- engines: {node: '>=12.5.0'}
-
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
@@ -1471,6 +1895,12 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
@@ -1527,9 +1957,32 @@ packages:
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
engines: {node: '>=12'}
+ damerau-levenshtein@1.0.8:
+ resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+
+ data-view-buffer@1.0.2:
+ resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
+ engines: {node: '>= 0.4'}
+
+ data-view-byte-length@1.0.2:
+ resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
+ engines: {node: '>= 0.4'}
+
+ data-view-byte-offset@1.0.1:
+ resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
+ engines: {node: '>= 0.4'}
+
date-fns@4.1.0:
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
+ debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@4.4.1:
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
@@ -1545,12 +1998,23 @@ packages:
decode-named-character-reference@1.2.0:
resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==}
+ deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
- detect-libc@2.0.4:
- resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
detect-node-es@1.1.0:
@@ -1565,9 +2029,17 @@ packages:
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+ doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
@@ -1593,42 +2065,235 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ es-abstract@1.24.0:
+ resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==}
+ engines: {node: '>= 0.4'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-iterator-helpers@1.2.1:
+ resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==}
+ engines: {node: '>= 0.4'}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
+ es-shim-unscopables@1.1.0:
+ resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
+ engines: {node: '>= 0.4'}
+
+ es-to-primitive@1.3.0:
+ resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
+ engines: {node: '>= 0.4'}
+
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
escape-string-regexp@5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
- estree-util-is-identifier-name@3.0.0:
- resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
-
- ethers@6.15.0:
- resolution: {integrity: sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ==}
- engines: {node: '>=14.0.0'}
+ eslint-config-next@16.0.8:
+ resolution: {integrity: sha512-8J5cOAboXIV3f8OD6BOyj7Fik6n/as7J4MboiUSExWruf/lCu1OPR3ZVSdnta6WhzebrmAATEmNSBZsLWA6kbg==}
+ peerDependencies:
+ eslint: '>=9.0.0'
+ typescript: '>=3.3.1'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
- eventemitter3@4.0.7:
- resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
+ eslint-import-resolver-node@0.3.9:
+ resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
- extend@3.0.2:
- resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+ eslint-import-resolver-typescript@3.10.1:
+ resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ eslint-plugin-import: '*'
+ eslint-plugin-import-x: '*'
+ peerDependenciesMeta:
+ eslint-plugin-import:
+ optional: true
+ eslint-plugin-import-x:
+ optional: true
- fast-equals@5.2.2:
- resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==}
- engines: {node: '>=6.0.0'}
+ eslint-module-utils@2.12.1:
+ resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+
+ eslint-plugin-import@2.32.0:
+ resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+
+ eslint-plugin-jsx-a11y@6.10.2:
+ resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+
+ eslint-plugin-react-hooks@7.0.1:
+ resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
+ eslint-plugin-react@7.37.5:
+ resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+
+ eslint-scope@8.4.0:
+ resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ eslint-visitor-keys@4.2.1:
+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint@9.14.0:
+ resolution: {integrity: sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
+ espree@10.4.0:
+ resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ esquery@1.6.0:
+ resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
+ engines: {node: '>=0.10'}
+
+ esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ ethers@6.15.0:
+ resolution: {integrity: sha512-Kf/3ZW54L4UT0pZtsY/rf+EkBU7Qi5nnhonjUb8yTXcxH3cdcWrV2cRyk0Xk/4jK6OoHhxxZHriyhje20If2hQ==}
+ engines: {node: '>=14.0.0'}
+
+ eventemitter3@4.0.7:
+ resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==}
+
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-equals@5.2.2:
+ resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==}
+ engines: {node: '>=6.0.0'}
+
+ fast-glob@3.3.1:
+ resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
+ engines: {node: '>=8.6.0'}
fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
fastq@1.19.1:
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
+
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
+
+ flatted@3.3.3:
+ resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+
+ for-each@0.3.5:
+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+ engines: {node: '>= 0.4'}
+
foreground-child@3.3.1:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
@@ -1644,10 +2309,40 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ function.prototype.name@1.1.8:
+ resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
+ engines: {node: '>= 0.4'}
+
+ functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+
+ generator-function@2.0.1:
+ resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
+ engines: {node: '>= 0.4'}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
get-nonce@1.0.1:
resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
engines: {node: '>=6'}
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ get-symbol-description@1.1.0:
+ resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
+ engines: {node: '>= 0.4'}
+
+ get-tsconfig@4.13.0:
+ resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
@@ -1660,6 +2355,48 @@ packages:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
+ globals@14.0.0:
+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+ engines: {node: '>=18'}
+
+ globals@16.4.0:
+ resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
+ engines: {node: '>=18'}
+
+ globalthis@1.0.4:
+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+ engines: {node: '>= 0.4'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+
+ has-bigints@1.1.0:
+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+ engines: {node: '>= 0.4'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+ has-proto@1.2.0:
+ resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
+ engines: {node: '>= 0.4'}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
@@ -1676,6 +2413,12 @@ packages:
hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+ hermes-estree@0.25.1:
+ resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+ hermes-parser@0.25.1:
+ resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+
highlight.js@11.11.1:
resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==}
engines: {node: '>=12.0.0'}
@@ -1683,6 +2426,22 @@ packages:
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
+ engines: {node: '>= 4'}
+
+ import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+ engines: {node: '>=6'}
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
inline-style-parser@0.2.4:
resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
@@ -1692,6 +2451,10 @@ packages:
react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc
+ internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
+ engines: {node: '>= 0.4'}
+
internmap@2.0.3:
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
engines: {node: '>=12'}
@@ -1702,17 +2465,45 @@ packages:
is-alphanumerical@2.0.1:
resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
- is-arrayish@0.3.2:
- resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+ is-array-buffer@3.0.5:
+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
+ engines: {node: '>= 0.4'}
+
+ is-async-function@2.1.1:
+ resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
+ engines: {node: '>= 0.4'}
+
+ is-bigint@1.1.0:
+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+ engines: {node: '>= 0.4'}
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
+ is-boolean-object@1.2.2:
+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
+ engines: {node: '>= 0.4'}
+
+ is-bun-module@2.0.0:
+ resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
+
+ is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+
is-core-module@2.16.1:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
+ is-data-view@1.0.2:
+ resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
+ engines: {node: '>= 0.4'}
+
+ is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
+ engines: {node: '>= 0.4'}
+
is-decimal@2.0.1:
resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
@@ -1720,10 +2511,18 @@ packages:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
+ is-finalizationregistry@1.1.1:
+ resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
+ engines: {node: '>= 0.4'}
+
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
+ is-generator-function@1.1.2:
+ resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
+ engines: {node: '>= 0.4'}
+
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
@@ -1731,6 +2530,18 @@ packages:
is-hexadecimal@2.0.1:
resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+ is-map@2.0.3:
+ resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
+ engines: {node: '>= 0.4'}
+
+ is-negative-zero@2.0.3:
+ resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
+ engines: {node: '>= 0.4'}
+
+ is-number-object@1.1.1:
+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
+ engines: {node: '>= 0.4'}
+
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
@@ -1739,9 +2550,52 @@ packages:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
+ is-regex@1.2.1:
+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
+ engines: {node: '>= 0.4'}
+
+ is-set@2.0.3:
+ resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
+ engines: {node: '>= 0.4'}
+
+ is-shared-array-buffer@1.0.4:
+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
+ engines: {node: '>= 0.4'}
+
+ is-string@1.1.1:
+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
+ engines: {node: '>= 0.4'}
+
+ is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
+ engines: {node: '>= 0.4'}
+
+ is-typed-array@1.1.15:
+ resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
+ engines: {node: '>= 0.4'}
+
+ is-weakmap@2.0.2:
+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+ engines: {node: '>= 0.4'}
+
+ is-weakref@1.1.1:
+ resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
+ engines: {node: '>= 0.4'}
+
+ is-weakset@2.0.4:
+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+ engines: {node: '>= 0.4'}
+
+ isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ iterator.prototype@1.1.5:
+ resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
+ engines: {node: '>= 0.4'}
+
jackspeak@3.4.3:
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
@@ -1752,6 +2606,51 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+ json5@1.0.2:
+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ language-subtag-registry@0.3.23:
+ resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
+
+ language-tags@1.0.9:
+ resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
+ engines: {node: '>=0.10'}
+
+ levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+
lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
@@ -1759,6 +2658,10 @@ packages:
lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
lodash.castarray@4.4.0:
resolution: {integrity: sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==}
@@ -1784,6 +2687,9 @@ packages:
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
lucide-react@0.454.0:
resolution: {integrity: sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==}
peerDependencies:
@@ -1792,6 +2698,10 @@ packages:
markdown-table@3.0.4:
resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
mdast-util-find-and-replace@3.0.2:
resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
@@ -1929,10 +2839,16 @@ packages:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
minimatch@9.0.5:
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
engines: {node: '>=16 || 14 >=14.17'}
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
minipass@7.1.2:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
@@ -1948,19 +2864,27 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ napi-postinstall@0.3.4:
+ resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ hasBin: true
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
next-themes@0.4.6:
resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==}
peerDependencies:
react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc
- next@15.2.4:
- resolution: {integrity: sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==}
- engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
+ next@16.0.8:
+ resolution: {integrity: sha512-LmcZzG04JuzNXi48s5P+TnJBsTGPJunViNKV/iE4uM6kstjTQsQhvsAv+xF6MJxU2Pr26tl15eVbp0jQnsv6/g==}
+ engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
'@opentelemetry/api': ^1.1.0
- '@playwright/test': ^1.41.2
+ '@playwright/test': ^1.51.1
babel-plugin-react-compiler: '*'
react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
@@ -1994,12 +2918,64 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+
+ object.assign@4.1.7:
+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
+ engines: {node: '>= 0.4'}
+
+ object.entries@1.1.9:
+ resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
+ engines: {node: '>= 0.4'}
+
+ object.fromentries@2.0.8:
+ resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
+ engines: {node: '>= 0.4'}
+
+ object.groupby@1.0.3:
+ resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
+ engines: {node: '>= 0.4'}
+
+ object.values@1.2.1:
+ resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
+ engines: {node: '>= 0.4'}
+
+ optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+
+ own-keys@1.0.1:
+ resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
+ engines: {node: '>= 0.4'}
+
+ p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==}
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
parse-entities@4.0.2:
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -2018,6 +2994,10 @@ packages:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
@@ -2026,6 +3006,10 @@ packages:
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
engines: {node: '>= 6'}
+ possible-typed-array-names@1.1.0:
+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
+ engines: {node: '>= 0.4'}
+
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@@ -2075,12 +3059,20 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
@@ -2182,6 +3174,14 @@ packages:
react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ reflect.getprototypeof@1.0.10:
+ resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
+ engines: {node: '>= 0.4'}
+
+ regexp.prototype.flags@1.5.4:
+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
+ engines: {node: '>= 0.4'}
+
rehype-highlight@7.0.2:
resolution: {integrity: sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA==}
@@ -2197,11 +3197,22 @@ packages:
remark-stringify@11.0.0:
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
resolve@1.22.10:
resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
engines: {node: '>= 0.4'}
hasBin: true
+ resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -2209,16 +3220,44 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ safe-array-concat@1.1.3:
+ resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
+ engines: {node: '>=0.4'}
+
+ safe-push-apply@1.0.0:
+ resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
+ engines: {node: '>= 0.4'}
+
+ safe-regex-test@1.1.0:
+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
+ engines: {node: '>= 0.4'}
+
scheduler@0.26.0:
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
- semver@7.7.2:
- resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
engines: {node: '>=10'}
hasBin: true
- sharp@0.33.5:
- resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
+ set-function-length@1.2.2:
+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ engines: {node: '>= 0.4'}
+
+ set-function-name@2.0.2:
+ resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+ engines: {node: '>= 0.4'}
+
+ set-proto@1.0.0:
+ resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
+ engines: {node: '>= 0.4'}
+
+ sharp@0.34.5:
+ resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
shebang-command@2.0.0:
@@ -2229,13 +3268,26 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
signal-exit@4.1.0:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
- simple-swizzle@0.2.2:
- resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
-
sonner@1.7.4:
resolution: {integrity: sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw==}
peerDependencies:
@@ -2249,9 +3301,12 @@ packages:
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
- streamsearch@1.1.0:
- resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
- engines: {node: '>=10.0.0'}
+ stable-hash@0.0.5:
+ resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+
+ stop-iteration-iterator@1.1.0:
+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
+ engines: {node: '>= 0.4'}
string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
@@ -2261,6 +3316,29 @@ packages:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
+ string.prototype.includes@2.0.1:
+ resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.matchall@4.0.12:
+ resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.repeat@1.0.0:
+ resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
+
+ string.prototype.trim@1.2.10:
+ resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.trimend@1.0.9:
+ resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.trimstart@1.0.8:
+ resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
+ engines: {node: '>= 0.4'}
+
stringify-entities@4.0.4:
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
@@ -2272,6 +3350,14 @@ packages:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
+ strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+
+ strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+
style-to-js@1.1.17:
resolution: {integrity: sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==}
@@ -2296,6 +3382,10 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -2313,6 +3403,9 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
+ text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+
thenify-all@1.6.0:
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
engines: {node: '>=0.8'}
@@ -2323,6 +3416,10 @@ packages:
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -2333,20 +3430,60 @@ packages:
trough@2.2.0:
resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+ ts-api-utils@2.1.0:
+ resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
+ engines: {node: '>=18.12'}
+ peerDependencies:
+ typescript: '>=4.8.4'
+
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ tsconfig-paths@3.15.0:
+ resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+
tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+
+ typed-array-buffer@1.0.3:
+ resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-byte-length@1.0.3:
+ resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-byte-offset@1.0.4:
+ resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-length@1.0.7:
+ resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
+ engines: {node: '>= 0.4'}
+
+ typescript-eslint@8.48.1:
+ resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
typescript@5.9.2:
resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
engines: {node: '>=14.17'}
hasBin: true
+ unbox-primitive@1.1.0:
+ resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
+ engines: {node: '>= 0.4'}
+
undici-types@6.19.8:
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
@@ -2374,12 +3511,18 @@ packages:
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
+ unrs-resolver@1.11.1:
+ resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
+
update-browserslist-db@1.1.3:
resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==}
hasBin: true
peerDependencies:
browserslist: '>= 4.21.0'
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
use-callback-ref@1.3.3:
resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==}
engines: {node: '>=10'}
@@ -2423,11 +3566,31 @@ packages:
victory-vendor@36.9.2:
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
+ which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+
+ which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+ engines: {node: '>= 0.4'}
+
+ which-collection@1.0.2:
+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+ engines: {node: '>= 0.4'}
+
+ which-typed-array@1.1.19:
+ resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==}
+ engines: {node: '>= 0.4'}
+
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
hasBin: true
+ word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -2448,11 +3611,24 @@ packages:
utf-8-validate:
optional: true
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
yaml@2.8.0:
resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
engines: {node: '>= 14.6'}
hasBin: true
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+ zod-validation-error@4.0.2:
+ resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+
zod@3.25.76:
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
@@ -2465,12 +3641,167 @@ snapshots:
'@alloc/quick-lru@5.2.0': {}
+ '@babel/code-frame@7.27.1':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.28.5': {}
+
+ '@babel/core@7.28.5':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.5
+ '@babel/helper-compilation-targets': 7.27.2
+ '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5)
+ '@babel/helpers': 7.28.4
+ '@babel/parser': 7.28.5
+ '@babel/template': 7.27.2
+ '@babel/traverse': 7.28.5
+ '@babel/types': 7.28.5
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.1
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.28.5':
+ dependencies:
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.27.2':
+ dependencies:
+ '@babel/compat-data': 7.28.5
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.25.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-globals@7.28.0': {}
+
+ '@babel/helper-module-imports@7.27.1':
+ dependencies:
+ '@babel/traverse': 7.28.5
+ '@babel/types': 7.28.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)':
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/helper-module-imports': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.28.5
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.28.5': {}
+
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helpers@7.28.4':
+ dependencies:
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.5
+
+ '@babel/parser@7.28.5':
+ dependencies:
+ '@babel/types': 7.28.5
+
'@babel/runtime@7.28.2': {}
- '@emnapi/runtime@1.4.5':
+ '@babel/template@7.27.2':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/parser': 7.28.5
+ '@babel/types': 7.28.5
+
+ '@babel/traverse@7.28.5':
+ dependencies:
+ '@babel/code-frame': 7.27.1
+ '@babel/generator': 7.28.5
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.5
+ '@babel/template': 7.27.2
+ '@babel/types': 7.28.5
+ debug: 4.4.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.28.5':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
+ '@emnapi/core@1.7.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.7.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.1.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@eslint-community/eslint-utils@4.9.0(eslint@9.14.0(jiti@1.21.7))':
+ dependencies:
+ eslint: 9.14.0(jiti@1.21.7)
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.12.2': {}
+
+ '@eslint/config-array@0.18.0':
+ dependencies:
+ '@eslint/object-schema': 2.1.7
+ debug: 4.4.1
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/core@0.13.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
+ '@eslint/core@0.7.0': {}
+
+ '@eslint/eslintrc@3.3.3':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.4.1
+ espree: 10.4.0
+ globals: 14.0.0
+ ignore: 5.3.2
+ import-fresh: 3.3.1
+ js-yaml: 4.1.1
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@9.14.0': {}
+
+ '@eslint/object-schema@2.1.7': {}
+
+ '@eslint/plugin-kit@0.2.8':
dependencies:
- tslib: 2.8.1
- optional: true
+ '@eslint/core': 0.13.0
+ levn: 0.4.1
'@floating-ui/core@1.7.3':
dependencies:
@@ -2493,79 +3824,112 @@ snapshots:
dependencies:
react-hook-form: 7.62.0(react@19.1.1)
- '@img/sharp-darwin-arm64@0.33.5':
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.7':
+ dependencies:
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.4.3
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/retry@0.4.3': {}
+
+ '@img/colour@1.0.0':
+ optional: true
+
+ '@img/sharp-darwin-arm64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-darwin-arm64': 1.0.4
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
optional: true
- '@img/sharp-darwin-x64@0.33.5':
+ '@img/sharp-darwin-x64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-darwin-x64': 1.0.4
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm@1.2.4':
optional: true
- '@img/sharp-libvips-darwin-arm64@1.0.4':
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
optional: true
- '@img/sharp-libvips-darwin-x64@1.0.4':
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
optional: true
- '@img/sharp-libvips-linux-arm64@1.0.4':
+ '@img/sharp-libvips-linux-s390x@1.2.4':
optional: true
- '@img/sharp-libvips-linux-arm@1.0.5':
+ '@img/sharp-libvips-linux-x64@1.2.4':
optional: true
- '@img/sharp-libvips-linux-s390x@1.0.4':
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
optional: true
- '@img/sharp-libvips-linux-x64@1.0.4':
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
optional: true
- '@img/sharp-libvips-linuxmusl-arm64@1.0.4':
+ '@img/sharp-linux-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.2.4
optional: true
- '@img/sharp-libvips-linuxmusl-x64@1.0.4':
+ '@img/sharp-linux-arm@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.2.4
optional: true
- '@img/sharp-linux-arm64@0.33.5':
+ '@img/sharp-linux-ppc64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linux-arm64': 1.0.4
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
optional: true
- '@img/sharp-linux-arm@0.33.5':
+ '@img/sharp-linux-riscv64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linux-arm': 1.0.5
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
optional: true
- '@img/sharp-linux-s390x@0.33.5':
+ '@img/sharp-linux-s390x@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linux-s390x': 1.0.4
+ '@img/sharp-libvips-linux-s390x': 1.2.4
optional: true
- '@img/sharp-linux-x64@0.33.5':
+ '@img/sharp-linux-x64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linux-x64': 1.0.4
+ '@img/sharp-libvips-linux-x64': 1.2.4
optional: true
- '@img/sharp-linuxmusl-arm64@0.33.5':
+ '@img/sharp-linuxmusl-arm64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
optional: true
- '@img/sharp-linuxmusl-x64@0.33.5':
+ '@img/sharp-linuxmusl-x64@0.34.5':
optionalDependencies:
- '@img/sharp-libvips-linuxmusl-x64': 1.0.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
optional: true
- '@img/sharp-wasm32@0.33.5':
+ '@img/sharp-wasm32@0.34.5':
dependencies:
- '@emnapi/runtime': 1.4.5
+ '@emnapi/runtime': 1.7.1
+ optional: true
+
+ '@img/sharp-win32-arm64@0.34.5':
optional: true
- '@img/sharp-win32-ia32@0.33.5':
+ '@img/sharp-win32-ia32@0.34.5':
optional: true
- '@img/sharp-win32-x64@0.33.5':
+ '@img/sharp-win32-x64@0.34.5':
optional: true
'@isaacs/cliui@8.0.2':
@@ -2582,6 +3946,11 @@ snapshots:
'@jridgewell/sourcemap-codec': 1.5.4
'@jridgewell/trace-mapping': 0.3.29
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.12
+ '@jridgewell/trace-mapping': 0.3.29
+
'@jridgewell/resolve-uri@3.1.2': {}
'@jridgewell/sourcemap-codec@1.5.4': {}
@@ -2591,30 +3960,41 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.4
- '@next/env@15.2.4': {}
+ '@napi-rs/wasm-runtime@0.2.12':
+ dependencies:
+ '@emnapi/core': 1.7.1
+ '@emnapi/runtime': 1.7.1
+ '@tybys/wasm-util': 0.10.1
+ optional: true
+
+ '@next/env@16.0.8': {}
- '@next/swc-darwin-arm64@15.2.4':
+ '@next/eslint-plugin-next@16.0.8':
+ dependencies:
+ fast-glob: 3.3.1
+
+ '@next/swc-darwin-arm64@16.0.8':
optional: true
- '@next/swc-darwin-x64@15.2.4':
+ '@next/swc-darwin-x64@16.0.8':
optional: true
- '@next/swc-linux-arm64-gnu@15.2.4':
+ '@next/swc-linux-arm64-gnu@16.0.8':
optional: true
- '@next/swc-linux-arm64-musl@15.2.4':
+ '@next/swc-linux-arm64-musl@16.0.8':
optional: true
- '@next/swc-linux-x64-gnu@15.2.4':
+ '@next/swc-linux-x64-gnu@16.0.8':
optional: true
- '@next/swc-linux-x64-musl@15.2.4':
+ '@next/swc-linux-x64-musl@16.0.8':
optional: true
- '@next/swc-win32-arm64-msvc@15.2.4':
+ '@next/swc-win32-arm64-msvc@16.0.8':
optional: true
- '@next/swc-win32-x64-msvc@15.2.4':
+ '@next/swc-win32-x64-msvc@16.0.8':
optional: true
'@noble/curves@1.2.0':
@@ -2635,6 +4015,8 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.19.1
+ '@nolyfill/is-core-module@1.0.39': {}
+
'@pkgjs/parseargs@0.11.0':
optional: true
@@ -3490,7 +4872,7 @@ snapshots:
'@radix-ui/rect@1.1.1': {}
- '@swc/counter@0.1.3': {}
+ '@rtsao/scc@1.1.0': {}
'@swc/helpers@0.5.15':
dependencies:
@@ -3504,6 +4886,11 @@ snapshots:
postcss-selector-parser: 6.0.10
tailwindcss: 3.4.17
+ '@tybys/wasm-util@0.10.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@types/d3-array@3.2.1': {}
'@types/d3-color@3.1.3': {}
@@ -3542,6 +4929,10 @@ snapshots:
dependencies:
'@types/unist': 3.0.3
+ '@types/json-schema@7.0.15': {}
+
+ '@types/json5@0.0.29': {}
+
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3
@@ -3568,10 +4959,174 @@ snapshots:
'@types/unist@3.0.3': {}
+ '@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.2
+ '@typescript-eslint/parser': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ '@typescript-eslint/scope-manager': 8.48.1
+ '@typescript-eslint/type-utils': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.48.1
+ eslint: 9.14.0(jiti@1.21.7)
+ graphemer: 1.4.0
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.48.1
+ '@typescript-eslint/types': 8.48.1
+ '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.48.1
+ debug: 4.4.1
+ eslint: 9.14.0(jiti@1.21.7)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/project-service@8.48.1(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/types': 8.48.1
+ debug: 4.4.1
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@8.48.1':
+ dependencies:
+ '@typescript-eslint/types': 8.48.1
+ '@typescript-eslint/visitor-keys': 8.48.1
+
+ '@typescript-eslint/tsconfig-utils@8.48.1(typescript@5.9.2)':
+ dependencies:
+ typescript: 5.9.2
+
+ '@typescript-eslint/type-utils@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/types': 8.48.1
+ '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ debug: 4.4.1
+ eslint: 9.14.0(jiti@1.21.7)
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@8.48.1': {}
+
+ '@typescript-eslint/typescript-estree@8.48.1(typescript@5.9.2)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/tsconfig-utils': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/types': 8.48.1
+ '@typescript-eslint/visitor-keys': 8.48.1
+ debug: 4.4.1
+ minimatch: 9.0.5
+ semver: 7.7.3
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.14.0(jiti@1.21.7))
+ '@typescript-eslint/scope-manager': 8.48.1
+ '@typescript-eslint/types': 8.48.1
+ '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.2)
+ eslint: 9.14.0(jiti@1.21.7)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/visitor-keys@8.48.1':
+ dependencies:
+ '@typescript-eslint/types': 8.48.1
+ eslint-visitor-keys: 4.2.1
+
'@ungap/structured-clone@1.3.0': {}
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-android-arm64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.12
+ optional: true
+
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
+ optional: true
+
+ acorn-jsx@5.3.2(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
+ acorn@8.15.0: {}
+
aes-js@4.0.0-beta.5: {}
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
ansi-regex@5.0.1: {}
ansi-regex@6.1.0: {}
@@ -3591,10 +5146,85 @@ snapshots:
arg@5.0.2: {}
+ argparse@2.0.1: {}
+
aria-hidden@1.2.6:
dependencies:
tslib: 2.8.1
+ aria-query@5.3.2: {}
+
+ array-buffer-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
+
+ array-includes@3.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ is-string: 1.1.1
+ math-intrinsics: 1.1.0
+
+ array.prototype.findlast@1.2.5:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.findlastindex@1.2.6:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flat@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flatmap@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.tosorted@1.1.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-shim-unscopables: 1.1.0
+
+ arraybuffer.prototype.slice@1.0.4:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ is-array-buffer: 3.0.5
+
+ ast-types-flow@0.0.8: {}
+
+ async-function@1.0.0: {}
+
autoprefixer@10.4.21(postcss@8.5.6):
dependencies:
browserslist: 4.25.1
@@ -3605,12 +5235,25 @@ snapshots:
postcss: 8.5.6
postcss-value-parser: 4.2.0
+ available-typed-arrays@1.0.7:
+ dependencies:
+ possible-typed-array-names: 1.1.0
+
+ axe-core@4.11.0: {}
+
+ axobject-query@4.1.0: {}
+
bail@2.0.2: {}
balanced-match@1.0.2: {}
binary-extensions@2.3.0: {}
+ brace-expansion@1.1.12:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
brace-expansion@2.0.2:
dependencies:
balanced-match: 1.0.2
@@ -3626,9 +5269,24 @@ snapshots:
node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.1)
- busboy@1.6.0:
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bind@1.0.8:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
+ set-function-length: 1.2.2
+
+ call-bound@1.0.4:
dependencies:
- streamsearch: 1.1.0
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ callsites@3.1.0: {}
camelcase-css@2.0.1: {}
@@ -3636,6 +5294,11 @@ snapshots:
ccount@2.0.1: {}
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
character-entities-html4@2.1.0: {}
character-entities-legacy@3.0.0: {}
@@ -3682,22 +5345,14 @@ snapshots:
color-name@1.1.4: {}
- color-string@1.9.1:
- dependencies:
- color-name: 1.1.4
- simple-swizzle: 0.2.2
- optional: true
-
- color@4.2.3:
- dependencies:
- color-convert: 2.0.1
- color-string: 1.9.1
- optional: true
-
comma-separated-tokens@2.0.3: {}
commander@4.1.1: {}
+ concat-map@0.0.1: {}
+
+ convert-source-map@2.0.0: {}
+
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
@@ -3746,8 +5401,32 @@ snapshots:
d3-timer@3.0.1: {}
+ damerau-levenshtein@1.0.8: {}
+
+ data-view-buffer@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-offset@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
date-fns@4.1.0: {}
+ debug@3.2.7:
+ dependencies:
+ ms: 2.1.3
+
debug@4.4.1:
dependencies:
ms: 2.1.3
@@ -3758,9 +5437,23 @@ snapshots:
dependencies:
character-entities: 2.0.2
+ deep-is@0.1.4: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ define-properties@1.2.1:
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+
dequal@2.0.3: {}
- detect-libc@2.0.4:
+ detect-libc@2.1.2:
optional: true
detect-node-es@1.1.0: {}
@@ -3773,11 +5466,21 @@ snapshots:
dlv@1.1.3: {}
+ doctrine@2.1.0:
+ dependencies:
+ esutils: 2.0.3
+
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.28.2
csstype: 3.1.3
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
eastasianwidth@0.2.0: {}
electron-to-chromium@1.5.194: {}
@@ -3796,14 +5499,321 @@ snapshots:
emoji-regex@8.0.0: {}
- emoji-regex@9.2.2: {}
+ emoji-regex@9.2.2: {}
+
+ es-abstract@1.24.0:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ arraybuffer.prototype.slice: 1.0.4
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ data-view-buffer: 1.0.2
+ data-view-byte-length: 1.0.2
+ data-view-byte-offset: 1.0.1
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-set-tostringtag: 2.1.0
+ es-to-primitive: 1.3.0
+ function.prototype.name: 1.1.8
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ get-symbol-description: 1.1.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ internal-slot: 1.1.0
+ is-array-buffer: 3.0.5
+ is-callable: 1.2.7
+ is-data-view: 1.0.2
+ is-negative-zero: 2.0.3
+ is-regex: 1.2.1
+ is-set: 2.0.3
+ is-shared-array-buffer: 1.0.4
+ is-string: 1.1.1
+ is-typed-array: 1.1.15
+ is-weakref: 1.1.1
+ math-intrinsics: 1.1.0
+ object-inspect: 1.13.4
+ object-keys: 1.1.1
+ object.assign: 4.1.7
+ own-keys: 1.0.1
+ regexp.prototype.flags: 1.5.4
+ safe-array-concat: 1.1.3
+ safe-push-apply: 1.0.0
+ safe-regex-test: 1.1.0
+ set-proto: 1.0.0
+ stop-iteration-iterator: 1.1.0
+ string.prototype.trim: 1.2.10
+ string.prototype.trimend: 1.0.9
+ string.prototype.trimstart: 1.0.8
+ typed-array-buffer: 1.0.3
+ typed-array-byte-length: 1.0.3
+ typed-array-byte-offset: 1.0.4
+ typed-array-length: 1.0.7
+ unbox-primitive: 1.1.0
+ which-typed-array: 1.1.19
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-iterator-helpers@1.2.1:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-set-tostringtag: 2.1.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ iterator.prototype: 1.1.5
+ safe-array-concat: 1.1.3
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ es-shim-unscopables@1.1.0:
+ dependencies:
+ hasown: 2.0.2
+
+ es-to-primitive@1.3.0:
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ escape-string-regexp@5.0.0: {}
+
+ eslint-config-next@16.0.8(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2):
+ dependencies:
+ '@next/eslint-plugin-next': 16.0.8
+ eslint: 9.14.0(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.14.0(jiti@1.21.7))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.14.0(jiti@1.21.7))
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.14.0(jiti@1.21.7))
+ eslint-plugin-react: 7.37.5(eslint@9.14.0(jiti@1.21.7))
+ eslint-plugin-react-hooks: 7.0.1(eslint@9.14.0(jiti@1.21.7))
+ globals: 16.4.0
+ typescript-eslint: 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ optionalDependencies:
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - '@typescript-eslint/parser'
+ - eslint-import-resolver-webpack
+ - eslint-plugin-import-x
+ - supports-color
+
+ eslint-import-resolver-node@0.3.9:
+ dependencies:
+ debug: 3.2.7
+ is-core-module: 2.16.1
+ resolve: 1.22.10
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ '@nolyfill/is-core-module': 1.0.39
+ debug: 4.4.1
+ eslint: 9.14.0(jiti@1.21.7)
+ get-tsconfig: 4.13.0
+ is-bun-module: 2.0.0
+ stable-hash: 0.0.5
+ tinyglobby: 0.2.15
+ unrs-resolver: 1.11.1
+ optionalDependencies:
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.14.0(jiti@1.21.7))
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ debug: 3.2.7
+ optionalDependencies:
+ '@typescript-eslint/parser': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ eslint: 9.14.0(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.14.0(jiti@1.21.7))
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ '@rtsao/scc': 1.1.0
+ array-includes: 3.1.9
+ array.prototype.findlastindex: 1.2.6
+ array.prototype.flat: 1.3.3
+ array.prototype.flatmap: 1.3.3
+ debug: 3.2.7
+ doctrine: 2.1.0
+ eslint: 9.14.0(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.14.0(jiti@1.21.7))
+ hasown: 2.0.2
+ is-core-module: 2.16.1
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.fromentries: 2.0.8
+ object.groupby: 1.0.3
+ object.values: 1.2.1
+ semver: 6.3.1
+ string.prototype.trimend: 1.0.9
+ tsconfig-paths: 3.15.0
+ optionalDependencies:
+ '@typescript-eslint/parser': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ aria-query: 5.3.2
+ array-includes: 3.1.9
+ array.prototype.flatmap: 1.3.3
+ ast-types-flow: 0.0.8
+ axe-core: 4.11.0
+ axobject-query: 4.1.0
+ damerau-levenshtein: 1.0.8
+ emoji-regex: 9.2.2
+ eslint: 9.14.0(jiti@1.21.7)
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ language-tags: 1.0.9
+ minimatch: 3.1.2
+ object.fromentries: 2.0.8
+ safe-regex-test: 1.1.0
+ string.prototype.includes: 2.0.1
+
+ eslint-plugin-react-hooks@7.0.1(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ '@babel/core': 7.28.5
+ '@babel/parser': 7.28.5
+ eslint: 9.14.0(jiti@1.21.7)
+ hermes-parser: 0.25.1
+ zod: 3.25.76
+ zod-validation-error: 4.0.2(zod@3.25.76)
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-plugin-react@7.37.5(eslint@9.14.0(jiti@1.21.7)):
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.1
+ eslint: 9.14.0(jiti@1.21.7)
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
+
+ eslint-scope@8.4.0:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint-visitor-keys@4.2.1: {}
+
+ eslint@9.14.0(jiti@1.21.7):
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.0(eslint@9.14.0(jiti@1.21.7))
+ '@eslint-community/regexpp': 4.12.2
+ '@eslint/config-array': 0.18.0
+ '@eslint/core': 0.7.0
+ '@eslint/eslintrc': 3.3.3
+ '@eslint/js': 9.14.0
+ '@eslint/plugin-kit': 0.2.8
+ '@humanfs/node': 0.16.7
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ '@types/json-schema': 7.0.15
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.1
+ escape-string-regexp: 4.0.0
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.6.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ text-table: 0.2.0
+ optionalDependencies:
+ jiti: 1.21.7
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@10.4.0:
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 4.2.1
+
+ esquery@1.6.0:
+ dependencies:
+ estraverse: 5.3.0
- escalade@3.2.0: {}
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
- escape-string-regexp@5.0.0: {}
+ estraverse@5.3.0: {}
estree-util-is-identifier-name@3.0.0: {}
+ esutils@2.0.3: {}
+
ethers@6.15.0:
dependencies:
'@adraffy/ens-normalize': 1.10.1
@@ -3821,8 +5831,18 @@ snapshots:
extend@3.0.2: {}
+ fast-deep-equal@3.1.3: {}
+
fast-equals@5.2.2: {}
+ fast-glob@3.3.1:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -3831,14 +5851,42 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.8
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
fastq@1.19.1:
dependencies:
reusify: 1.1.0
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ file-entry-cache@8.0.0:
+ dependencies:
+ flat-cache: 4.0.1
+
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@4.0.1:
+ dependencies:
+ flatted: 3.3.3
+ keyv: 4.5.4
+
+ flatted@3.3.3: {}
+
+ for-each@0.3.5:
+ dependencies:
+ is-callable: 1.2.7
+
foreground-child@3.3.1:
dependencies:
cross-spawn: 7.0.6
@@ -3851,8 +5899,51 @@ snapshots:
function-bind@1.1.2: {}
+ function.prototype.name@1.1.8:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ functions-have-names: 1.2.3
+ hasown: 2.0.2
+ is-callable: 1.2.7
+
+ functions-have-names@1.2.3: {}
+
+ generator-function@2.0.1: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
get-nonce@1.0.1: {}
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ get-symbol-description@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+
+ get-tsconfig@4.13.0:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
@@ -3870,6 +5961,37 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 1.11.1
+ globals@14.0.0: {}
+
+ globals@16.4.0: {}
+
+ globalthis@1.0.4:
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+
+ gopd@1.2.0: {}
+
+ graphemer@1.4.0: {}
+
+ has-bigints@1.1.0: {}
+
+ has-flag@4.0.0: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.1
+
+ has-proto@1.2.0:
+ dependencies:
+ dunder-proto: 1.0.1
+
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
hasown@2.0.2:
dependencies:
function-bind: 1.1.2
@@ -3909,10 +6031,27 @@ snapshots:
dependencies:
'@types/hast': 3.0.4
+ hermes-estree@0.25.1: {}
+
+ hermes-parser@0.25.1:
+ dependencies:
+ hermes-estree: 0.25.1
+
highlight.js@11.11.1: {}
html-url-attributes@3.0.1: {}
+ ignore@5.3.2: {}
+
+ ignore@7.0.5: {}
+
+ import-fresh@3.3.1:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
inline-style-parser@0.2.4: {}
input-otp@1.4.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
@@ -3920,6 +6059,12 @@ snapshots:
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
+ internal-slot@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ hasown: 2.0.2
+ side-channel: 1.1.0
+
internmap@2.0.3: {}
is-alphabetical@2.0.1: {}
@@ -3929,35 +6074,143 @@ snapshots:
is-alphabetical: 2.0.1
is-decimal: 2.0.1
- is-arrayish@0.3.2:
- optional: true
+ is-array-buffer@3.0.5:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ is-async-function@2.1.1:
+ dependencies:
+ async-function: 1.0.0
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-bigint@1.1.0:
+ dependencies:
+ has-bigints: 1.1.0
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
+ is-boolean-object@1.2.2:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-bun-module@2.0.0:
+ dependencies:
+ semver: 7.7.3
+
+ is-callable@1.2.7: {}
+
is-core-module@2.16.1:
dependencies:
hasown: 2.0.2
+ is-data-view@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ is-typed-array: 1.1.15
+
+ is-date-object@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
is-decimal@2.0.1: {}
is-extglob@2.1.1: {}
+ is-finalizationregistry@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
is-fullwidth-code-point@3.0.0: {}
+ is-generator-function@1.1.2:
+ dependencies:
+ call-bound: 1.0.4
+ generator-function: 2.0.1
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-hexadecimal@2.0.1: {}
+ is-map@2.0.3: {}
+
+ is-negative-zero@2.0.3: {}
+
+ is-number-object@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
is-number@7.0.0: {}
is-plain-obj@4.1.0: {}
+ is-regex@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ is-set@2.0.3: {}
+
+ is-shared-array-buffer@1.0.4:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-string@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-symbol@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
+
+ is-typed-array@1.1.15:
+ dependencies:
+ which-typed-array: 1.1.19
+
+ is-weakmap@2.0.2: {}
+
+ is-weakref@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-weakset@2.0.4:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ isarray@2.0.5: {}
+
isexe@2.0.0: {}
+ iterator.prototype@1.1.5:
+ dependencies:
+ define-data-property: 1.1.4
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ has-symbols: 1.1.0
+ set-function-name: 2.0.2
+
jackspeak@3.4.3:
dependencies:
'@isaacs/cliui': 8.0.2
@@ -3968,10 +6221,54 @@ snapshots:
js-tokens@4.0.0: {}
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
+ jsesc@3.1.0: {}
+
+ json-buffer@3.0.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ json5@1.0.2:
+ dependencies:
+ minimist: 1.2.8
+
+ json5@2.2.3: {}
+
+ jsx-ast-utils@3.3.5:
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.flat: 1.3.3
+ object.assign: 4.1.7
+ object.values: 1.2.1
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ language-subtag-registry@0.3.23: {}
+
+ language-tags@1.0.9:
+ dependencies:
+ language-subtag-registry: 0.3.23
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
lilconfig@3.1.3: {}
lines-and-columns@1.2.4: {}
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
lodash.castarray@4.4.0: {}
lodash.isplainobject@4.0.6: {}
@@ -3994,12 +6291,18 @@ snapshots:
lru-cache@10.4.3: {}
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
lucide-react@0.454.0(react@19.1.1):
dependencies:
react: 19.1.1
markdown-table@3.0.4: {}
+ math-intrinsics@1.1.0: {}
+
mdast-util-find-and-replace@3.0.2:
dependencies:
'@types/mdast': 4.0.4
@@ -4351,10 +6654,16 @@ snapshots:
braces: 3.0.3
picomatch: 2.3.1
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.12
+
minimatch@9.0.5:
dependencies:
brace-expansion: 2.0.2
+ minimist@1.2.8: {}
+
minipass@7.1.2: {}
ms@2.1.3: {}
@@ -4367,32 +6676,34 @@ snapshots:
nanoid@3.3.11: {}
+ napi-postinstall@0.3.4: {}
+
+ natural-compare@1.4.0: {}
+
next-themes@0.4.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
- next@15.2.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
+ next@16.0.8(@babel/core@7.28.5)(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
- '@next/env': 15.2.4
- '@swc/counter': 0.1.3
+ '@next/env': 16.0.8
'@swc/helpers': 0.5.15
- busboy: 1.6.0
caniuse-lite: 1.0.30001731
postcss: 8.4.31
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
- styled-jsx: 5.1.6(react@19.1.1)
+ styled-jsx: 5.1.6(@babel/core@7.28.5)(react@19.1.1)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.2.4
- '@next/swc-darwin-x64': 15.2.4
- '@next/swc-linux-arm64-gnu': 15.2.4
- '@next/swc-linux-arm64-musl': 15.2.4
- '@next/swc-linux-x64-gnu': 15.2.4
- '@next/swc-linux-x64-musl': 15.2.4
- '@next/swc-win32-arm64-msvc': 15.2.4
- '@next/swc-win32-x64-msvc': 15.2.4
- sharp: 0.33.5
+ '@next/swc-darwin-arm64': 16.0.8
+ '@next/swc-darwin-x64': 16.0.8
+ '@next/swc-linux-arm64-gnu': 16.0.8
+ '@next/swc-linux-arm64-musl': 16.0.8
+ '@next/swc-linux-x64-gnu': 16.0.8
+ '@next/swc-linux-x64-musl': 16.0.8
+ '@next/swc-win32-arm64-msvc': 16.0.8
+ '@next/swc-win32-x64-msvc': 16.0.8
+ sharp: 0.34.5
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@@ -4407,8 +6718,75 @@ snapshots:
object-hash@3.0.0: {}
+ object-inspect@1.13.4: {}
+
+ object-keys@1.1.1: {}
+
+ object.assign@4.1.7:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
+ object-keys: 1.1.1
+
+ object.entries@1.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ object.fromentries@2.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+
+ object.groupby@1.0.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+
+ object.values@1.2.1:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ own-keys@1.0.1:
+ dependencies:
+ get-intrinsic: 1.3.0
+ object-keys: 1.1.1
+ safe-push-apply: 1.0.0
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
package-json-from-dist@1.0.1: {}
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
parse-entities@4.0.2:
dependencies:
'@types/unist': 2.0.11
@@ -4419,6 +6797,8 @@ snapshots:
is-decimal: 2.0.1
is-hexadecimal: 2.0.1
+ path-exists@4.0.0: {}
+
path-key@3.1.1: {}
path-parse@1.0.7: {}
@@ -4432,10 +6812,14 @@ snapshots:
picomatch@2.3.1: {}
+ picomatch@4.0.3: {}
+
pify@2.3.0: {}
pirates@4.0.7: {}
+ possible-typed-array-names@1.1.0: {}
+
postcss-import@15.1.0(postcss@8.5.6):
dependencies:
postcss: 8.5.6
@@ -4484,6 +6868,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ prelude-ls@1.2.1: {}
+
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@@ -4492,6 +6878,8 @@ snapshots:
property-information@7.1.0: {}
+ punycode@2.3.1: {}
+
queue-microtask@1.2.3: {}
react-day-picker@8.10.1(date-fns@4.1.0)(react@19.1.1):
@@ -4606,6 +6994,26 @@ snapshots:
tiny-invariant: 1.3.3
victory-vendor: 36.9.2
+ reflect.getprototypeof@1.0.10:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+
+ regexp.prototype.flags@1.5.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ set-function-name: 2.0.2
+
rehype-highlight@7.0.2:
dependencies:
'@types/hast': 3.0.4
@@ -4648,48 +7056,105 @@ snapshots:
mdast-util-to-markdown: 2.1.2
unified: 11.0.5
+ resolve-from@4.0.0: {}
+
+ resolve-pkg-maps@1.0.0: {}
+
resolve@1.22.10:
dependencies:
is-core-module: 2.16.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ resolve@2.0.0-next.5:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
reusify@1.1.0: {}
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
+ safe-array-concat@1.1.3:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
+ isarray: 2.0.5
+
+ safe-push-apply@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ isarray: 2.0.5
+
+ safe-regex-test@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
+
scheduler@0.26.0: {}
- semver@7.7.2:
- optional: true
+ semver@6.3.1: {}
+
+ semver@7.7.3: {}
+
+ set-function-length@1.2.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+
+ set-function-name@2.0.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.2
- sharp@0.33.5:
+ set-proto@1.0.0:
dependencies:
- color: 4.2.3
- detect-libc: 2.0.4
- semver: 7.7.2
+ dunder-proto: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+
+ sharp@0.34.5:
+ dependencies:
+ '@img/colour': 1.0.0
+ detect-libc: 2.1.2
+ semver: 7.7.3
optionalDependencies:
- '@img/sharp-darwin-arm64': 0.33.5
- '@img/sharp-darwin-x64': 0.33.5
- '@img/sharp-libvips-darwin-arm64': 1.0.4
- '@img/sharp-libvips-darwin-x64': 1.0.4
- '@img/sharp-libvips-linux-arm': 1.0.5
- '@img/sharp-libvips-linux-arm64': 1.0.4
- '@img/sharp-libvips-linux-s390x': 1.0.4
- '@img/sharp-libvips-linux-x64': 1.0.4
- '@img/sharp-libvips-linuxmusl-arm64': 1.0.4
- '@img/sharp-libvips-linuxmusl-x64': 1.0.4
- '@img/sharp-linux-arm': 0.33.5
- '@img/sharp-linux-arm64': 0.33.5
- '@img/sharp-linux-s390x': 0.33.5
- '@img/sharp-linux-x64': 0.33.5
- '@img/sharp-linuxmusl-arm64': 0.33.5
- '@img/sharp-linuxmusl-x64': 0.33.5
- '@img/sharp-wasm32': 0.33.5
- '@img/sharp-win32-ia32': 0.33.5
- '@img/sharp-win32-x64': 0.33.5
+ '@img/sharp-darwin-arm64': 0.34.5
+ '@img/sharp-darwin-x64': 0.34.5
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ '@img/sharp-linux-arm': 0.34.5
+ '@img/sharp-linux-arm64': 0.34.5
+ '@img/sharp-linux-ppc64': 0.34.5
+ '@img/sharp-linux-riscv64': 0.34.5
+ '@img/sharp-linux-s390x': 0.34.5
+ '@img/sharp-linux-x64': 0.34.5
+ '@img/sharp-linuxmusl-arm64': 0.34.5
+ '@img/sharp-linuxmusl-x64': 0.34.5
+ '@img/sharp-wasm32': 0.34.5
+ '@img/sharp-win32-arm64': 0.34.5
+ '@img/sharp-win32-ia32': 0.34.5
+ '@img/sharp-win32-x64': 0.34.5
optional: true
shebang-command@2.0.0:
@@ -4698,12 +7163,35 @@ snapshots:
shebang-regex@3.0.0: {}
- signal-exit@4.1.0: {}
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
- simple-swizzle@0.2.2:
+ side-channel-map@1.0.1:
dependencies:
- is-arrayish: 0.3.2
- optional: true
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
+ signal-exit@4.1.0: {}
sonner@1.7.4(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
@@ -4714,7 +7202,12 @@ snapshots:
space-separated-tokens@2.0.2: {}
- streamsearch@1.1.0: {}
+ stable-hash@0.0.5: {}
+
+ stop-iteration-iterator@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
string-width@4.2.3:
dependencies:
@@ -4728,6 +7221,56 @@ snapshots:
emoji-regex: 9.2.2
strip-ansi: 7.1.0
+ string.prototype.includes@2.0.1:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+
+ string.prototype.matchall@4.0.12:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ regexp.prototype.flags: 1.5.4
+ set-function-name: 2.0.2
+ side-channel: 1.1.0
+
+ string.prototype.repeat@1.0.0:
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+
+ string.prototype.trim@1.2.10:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-data-property: 1.1.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.0
+ es-object-atoms: 1.1.1
+ has-property-descriptors: 1.0.2
+
+ string.prototype.trimend@1.0.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ string.prototype.trimstart@1.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
stringify-entities@4.0.4:
dependencies:
character-entities-html4: 2.1.0
@@ -4741,6 +7284,10 @@ snapshots:
dependencies:
ansi-regex: 6.1.0
+ strip-bom@3.0.0: {}
+
+ strip-json-comments@3.1.1: {}
+
style-to-js@1.1.17:
dependencies:
style-to-object: 1.0.9
@@ -4749,10 +7296,12 @@ snapshots:
dependencies:
inline-style-parser: 0.2.4
- styled-jsx@5.1.6(react@19.1.1):
+ styled-jsx@5.1.6(@babel/core@7.28.5)(react@19.1.1):
dependencies:
client-only: 0.0.1
react: 19.1.1
+ optionalDependencies:
+ '@babel/core': 7.28.5
sucrase@3.35.0:
dependencies:
@@ -4764,6 +7313,10 @@ snapshots:
pirates: 4.0.7
ts-interface-checker: 0.1.13
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
supports-preserve-symlinks-flag@1.0.0: {}
tailwind-merge@2.6.0: {}
@@ -4799,6 +7352,8 @@ snapshots:
transitivePeerDependencies:
- ts-node
+ text-table@0.2.0: {}
+
thenify-all@1.6.0:
dependencies:
thenify: 3.3.1
@@ -4809,6 +7364,11 @@ snapshots:
tiny-invariant@1.3.3: {}
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0
@@ -4817,14 +7377,80 @@ snapshots:
trough@2.2.0: {}
+ ts-api-utils@2.1.0(typescript@5.9.2):
+ dependencies:
+ typescript: 5.9.2
+
ts-interface-checker@0.1.13: {}
+ tsconfig-paths@3.15.0:
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.2
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+
tslib@2.7.0: {}
tslib@2.8.1: {}
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ typed-array-buffer@1.0.3:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-length@1.0.3:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-offset@1.0.4:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ reflect.getprototypeof: 1.0.10
+
+ typed-array-length@1.0.7:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ is-typed-array: 1.1.15
+ possible-typed-array-names: 1.1.0
+ reflect.getprototypeof: 1.0.10
+
+ typescript-eslint@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2))(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ '@typescript-eslint/typescript-estree': 8.48.1(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.48.1(eslint@9.14.0(jiti@1.21.7))(typescript@5.9.2)
+ eslint: 9.14.0(jiti@1.21.7)
+ typescript: 5.9.2
+ transitivePeerDependencies:
+ - supports-color
+
typescript@5.9.2: {}
+ unbox-primitive@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-bigints: 1.1.0
+ has-symbols: 1.1.0
+ which-boxed-primitive: 1.1.1
+
undici-types@6.19.8: {}
undici-types@6.21.0: {}
@@ -4867,12 +7493,40 @@ snapshots:
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
+ unrs-resolver@1.11.1:
+ dependencies:
+ napi-postinstall: 0.3.4
+ optionalDependencies:
+ '@unrs/resolver-binding-android-arm-eabi': 1.11.1
+ '@unrs/resolver-binding-android-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-x64': 1.11.1
+ '@unrs/resolver-binding-freebsd-x64': 1.11.1
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-musl': 1.11.1
+ '@unrs/resolver-binding-wasm32-wasi': 1.11.1
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
+
update-browserslist-db@1.1.3(browserslist@4.25.1):
dependencies:
browserslist: 4.25.1
escalade: 3.2.0
picocolors: 1.1.1
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
use-callback-ref@1.3.3(@types/react@19.1.9)(react@19.1.1):
dependencies:
react: 19.1.1
@@ -4930,10 +7584,53 @@ snapshots:
d3-time: 3.1.0
d3-timer: 3.0.1
+ which-boxed-primitive@1.1.1:
+ dependencies:
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
+
+ which-builtin-type@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ function.prototype.name: 1.1.8
+ has-tostringtag: 1.0.2
+ is-async-function: 2.1.1
+ is-date-object: 1.1.0
+ is-finalizationregistry: 1.1.1
+ is-generator-function: 1.1.2
+ is-regex: 1.2.1
+ is-weakref: 1.1.1
+ isarray: 2.0.5
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.19
+
+ which-collection@1.0.2:
+ dependencies:
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
+
+ which-typed-array@1.1.19:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+
which@2.0.2:
dependencies:
isexe: 2.0.0
+ word-wrap@1.2.5: {}
+
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -4948,8 +7645,16 @@ snapshots:
ws@8.17.1: {}
+ yallist@3.1.1: {}
+
yaml@2.8.0: {}
+ yocto-queue@0.1.0: {}
+
+ zod-validation-error@4.0.2(zod@3.25.76):
+ dependencies:
+ zod: 3.25.76
+
zod@3.25.76: {}
zwitch@2.0.4: {}
diff --git a/apps/Cortensor-EurekaAI/src/app/api/chat/route.ts b/apps/Cortensor-EurekaAI/src/app/api/chat/route.ts
index d60471d..6cc1619 100644
--- a/apps/Cortensor-EurekaAI/src/app/api/chat/route.ts
+++ b/apps/Cortensor-EurekaAI/src/app/api/chat/route.ts
@@ -18,14 +18,19 @@ const modelFilters = {
/<\/?thinking>/gi,
/Final Response:|final response:/gi,
/<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi,
+ /<\|USER\|>/gi,
+ /<\|ASSISTANT\|>/gi,
+ /<\/s>/gi,
/USER[\s\S]*?ASSISTANT/gi,
+ /^\s*user\s*:/gi,
+ /^\s*assistant\s*:/gi,
],
preserveCodeBlocks: true
},
'deepseek-r1': {
name: 'Deepseek R1',
removeThinkingBlocks: true, // Remove thinking blocks
- removeVerbosePatterns: false,
+ removeVerbosePatterns: true,
cleanupPatterns: [
/
[\s\S]*?<\/thinking>/gi,
/<\/?thinking>/gi,
@@ -33,6 +38,34 @@ const modelFilters = {
/<\/think>/gi, // Remove stray tags
//gi, // Remove stray tags
/\s*<\/think>\s*/gi, // Remove with surrounding whitespace
+ // LLaMA-style special tokens that may appear in distill outputs
+ /<\|begin_of_text\|>/gi,
+ /<\|end_of_text\|>/gi,
+ /<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi,
+ /<\|eot_id\|>/gi,
+ /<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi,
+ /<\|USER\|>/gi,
+ /<\|ASSISTANT\|>/gi,
+ /^\s*assistant\s*:/gi,
+ /^\s*user\s*:/gi,
+ ],
+ preserveCodeBlocks: true
+ },
+ 'llama-3.1-8b-q4': {
+ name: 'Llama 3.1 8B Q4',
+ removeThinkingBlocks: true,
+ removeVerbosePatterns: true,
+ cleanupPatterns: [
+ /<\|begin_of_text\|>/gi,
+ /<\|end_of_text\|>/gi,
+ /<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi,
+ /<\|eot_id\|>/gi,
+ /<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi,
+ /<\|USER\|>/gi,
+ /<\|ASSISTANT\|>/gi,
+ /<\/s>/gi,
+ /^\s*assistant\s*:/gi,
+ /^\s*user\s*:/gi,
],
preserveCodeBlocks: true
}
@@ -46,17 +79,58 @@ function applyModelFilters(text: string, modelId: string, isDeepThinking: boolea
// For DeepSeek R1 - extract thinking process from start to
if (modelId === 'deepseek-r1') {
+ // First, remove any leaked LLaMA special tokens and headers
+ filteredText = filteredText.replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '');
+ filteredText = filteredText.replace(/<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi, '');
+ filteredText = filteredText.replace(/<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi, '');
+ filteredText = filteredText.replace(/<\|USER\|>/gi, '');
+ filteredText = filteredText.replace(/<\|ASSISTANT\|>/gi, '');
+ filteredText = filteredText.replace(/^\s*assistant\s*:/gi, '');
+ filteredText = filteredText.replace(/^\s*user\s*:/gi, '');
+
+ // If output contains multiple turns, keep ONLY the last assistant/user segment
+ const findLastIndex = (text: string, patterns: RegExp[]): { idx: number; len: number } => {
+ let last = -1; let len = 0;
+ for (const p of patterns) {
+ let m: RegExpExecArray | null;
+ const r = new RegExp(p.source, p.flags.includes('g') ? p.flags : p.flags + 'g');
+ while ((m = r.exec(text)) !== null) {
+ last = m.index; len = m[0].length;
+ }
+ }
+ return { idx: last, len };
+ };
+ const lastAssistant = findLastIndex(filteredText, [/<\|ASSISTANT\|>/i, /\n\s*Assistant\s*:/i]);
+ const lastUser = findLastIndex(filteredText, [/<\|USER\|>/i, /\n\s*User\s*:/i]);
+ let startFrom = 0;
+ if (lastAssistant.idx >= 0) startFrom = lastAssistant.idx + lastAssistant.len;
+ else if (lastUser.idx >= 0) startFrom = lastUser.idx + lastUser.len;
+ if (startFrom > 0) {
+ filteredText = filteredText.slice(startFrom).trimStart();
+ }
+
+ // Prefer post- when present; otherwise keep pre- content as the answer
+ const thinkStartIndex = filteredText.indexOf('');
const thinkEndIndex = filteredText.indexOf('');
if (thinkEndIndex !== -1) {
- // Extract thinking process (from start to )
- const thinkingContent = filteredText.substring(0, thinkEndIndex).trim();
- // Extract main response (after )
- const mainResponse = filteredText.substring(thinkEndIndex + 8).trim(); // 8 = length of ''
+ // Extract thinking process (from start to )
+ let thinkingContent = filteredText.substring(0, thinkEndIndex).trim();
+ // Clean stray markers inside thinking
+ thinkingContent = thinkingContent
+ .replace(/^\s*/i, '')
+ .replace(/<\|USER\|>|<\|ASSISTANT\|>/gi, '')
+ .replace(/^\s*(user|assistant)\s*:\s*/gi, '')
+ .replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '')
+ .replace(/<|end▁of▁sentence|>/g, '')
+ .replace(/<\|end_of_sentence\|>/g, '')
+ .trim();
+ // Extract main response (after )
+ const mainResponse = filteredText.substring(thinkEndIndex + 8).trim(); // 8 = length of ''
if (showThinkingProcess && thinkingContent && thinkingContent.length > 0) {
- // Show thinking process as built-in feature for DeepSeek
- return `🧠 **Thinking Process:**\n\n${thinkingContent}\n\n---\n\n**Response:**\n\n${mainResponse}`;
+ // Show thinking process with cleaner section headers
+ return `🧠 Thinking Process\n\n${thinkingContent}\n\n---\n\nResponse\n\n${mainResponse}`;
} else {
// Only show main response, hide thinking process
return mainResponse && mainResponse.length > 0 ? mainResponse : filteredText;
@@ -65,7 +139,7 @@ function applyModelFilters(text: string, modelId: string, isDeepThinking: boolea
// Fallback: if no found, return as-is if showing thinking, or clean if not
if (!showThinkingProcess) {
- filteredText = filteredText.replace(/<\/?think>/gi, '');
+ filteredText = filteredText.replace(/<\/??think>/gi, '');
}
return filteredText.trim();
@@ -75,6 +149,11 @@ function applyModelFilters(text: string, modelId: string, isDeepThinking: boolea
for (const pattern of modelConfig.cleanupPatterns) {
filteredText = filteredText.replace(pattern, '');
}
+ // Remove end-of-sentence marker variants globally
+ filteredText = filteredText.replace(/<|end▁of▁sentence|>/g, '');
+ filteredText = filteredText.replace(/<\|end_of_sentence\|>/g, '');
+ // Remove generic EOS `` used by some LLMs
+ filteredText = filteredText.replace(/<\/s>/gi, '');
// Remove thinking blocks (always for default, conditionally for deepseek)
if (modelConfig.removeThinkingBlocks) {
@@ -128,10 +207,60 @@ function applyModelFilters(text: string, modelId: string, isDeepThinking: boolea
return filteredText;
}
+// Relevance filter: remove echoed user question, role markers, and repeated sentences
+function enforceRelevanceAndDedup(answerText: string, userMessage: string): string {
+ try {
+ let text = String(answerText || '');
+ const norm = (s: string) => s.toLowerCase()
+ .replace(/<\|user\|>|<\|assistant\|>/gi, '')
+ .replace(/user\s*:|assistant\s*:/gi, '')
+ .replace(/[^a-z0-9]+/gi, ' ')
+ .trim();
+
+ const userNorm = norm(userMessage || '');
+
+ // Remove obvious context/preamble lines
+ text = text
+ .replace(/^as an ai[\s\S]*?\.?\s*/gi, '')
+ .replace(/^as a language model[\s\S]*?\.?\s*/gi, '')
+ .replace(/^context\s*:\s*[\s\S]*?\n/gi, '')
+ .replace(/^q\s*:\s*/gim, '')
+ .replace(/^a\s*:\s*/gim, '');
+
+ // Split into sentences while preserving order
+ const sentences = text
+ .split(/(?<=[.!?])\s+/)
+ .map(s => s.trim())
+ .filter(Boolean);
+
+ const seen = new Set();
+ const result: string[] = [];
+
+ for (const s of sentences) {
+ const sNorm = norm(s);
+ // Drop if it's the same as the user's question or contains it heavily
+ if (sNorm === userNorm) continue;
+ if (userNorm && sNorm.length > 0 && (sNorm.includes(userNorm) || userNorm.includes(sNorm))) continue;
+ // Deduplicate globally by normalized sentence
+ if (seen.has(sNorm)) continue;
+ seen.add(sNorm);
+ result.push(s);
+ }
+
+ // If still very long with many sentences, keep first 3 for relevance
+ if (result.length > 3) {
+ return result.slice(0, 3).join(' ').trim();
+ }
+ return result.join(' ').trim();
+ } catch {
+ return String(answerText || '').trim();
+ }
+}
+
// Llava 1.5 processing (for default model)
function processLlavaStream(textChunk: string, model: string, isDeepThinking: boolean): string {
- // For default model streaming, preserve original formatting to maintain proper spacing
- if (model === 'default-model') {
+ // For default and llama models streaming, preserve original formatting to maintain proper spacing
+ if (model === 'default-model' || model === 'llama-3.1-8b-q4') {
// Only apply minimal cleaning without affecting spacing
let cleanedText = textChunk;
@@ -140,6 +269,13 @@ function processLlavaStream(textChunk: string, model: string, isDeepThinking: bo
cleanedText = cleanedText.replace(/<\/?thinking>/gi, '');
cleanedText = cleanedText.replace(/<\/think>/gi, '');
cleanedText = cleanedText.replace(//gi, '');
+ // Remove llama special tokens if they leak into chunks
+ cleanedText = cleanedText.replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '');
+ cleanedText = cleanedText.replace(/<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi, '');
+ cleanedText = cleanedText.replace(/<\/s>/gi, '');
+ // Remove end-of-sentence markers
+ cleanedText = cleanedText.replace(/<|end▁of▁sentence|>/g, '');
+ cleanedText = cleanedText.replace(/<\|end_of_sentence\|>/g, '');
// Return original text with minimal cleaning to preserve streaming format
return cleanedText;
@@ -151,8 +287,30 @@ function processLlavaStream(textChunk: string, model: string, isDeepThinking: bo
// DeepSeek R1 advanced processing (for deepseek model)
function processDeepSeekStream(textChunk: string, model: string, isDeepThinking: boolean, showThinkingProcess: boolean = false): string {
- // For DeepSeek R1, always return raw content - frontend will handle formatting
- return textChunk;
+ let cleaned = textChunk;
+ // If not showing thinking, remove blocks and tags
+ if (!showThinkingProcess) {
+ cleaned = cleaned.replace(/[\s\S]*?<\/thinking>/gi, '');
+ cleaned = cleaned.replace(/<\/?thinking>/gi, '');
+ cleaned = cleaned.replace(/<\/think>/gi, '');
+ cleaned = cleaned.replace(//gi, '');
+ cleaned = cleaned.replace(/\s*<\/think>\s*/gi, ' ');
+ }
+ // Remove any leaked LLaMA special tokens
+ cleaned = cleaned.replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '');
+ cleaned = cleaned.replace(/<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi, '');
+ cleaned = cleaned.replace(/<\/s>/gi, '');
+ cleaned = cleaned.replace(/<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi, '');
+ cleaned = cleaned.replace(/^\s*assistant\s*:/gi, '');
+ // Remove end-of-sentence markers
+ cleaned = cleaned.replace(/<|end▁of▁sentence|>/g, '');
+ cleaned = cleaned.replace(/<\|end_of_sentence\|>/g, '');
+ // If role markers for a new turn are present in a chunk, truncate before them to avoid cross-turn bleed
+ const roleCut = cleaned.match(/<\|USER\|>|<\|ASSISTANT\|>|\n\s*User\s*:|\n\s*Assistant\s*:/i);
+ if (roleCut && roleCut.index !== undefined && roleCut.index >= 0) {
+ cleaned = cleaned.slice(0, roleCut.index);
+ }
+ return cleaned;
}
// Rate limiting in-memory store (for edge runtime)
@@ -213,7 +371,20 @@ export async function POST(req: NextRequest) {
return new Response("Invalid JSON format", { status: 400 });
}
- const { message, messages, model, useDeepThinking = false, isDeepThinking = false, showThinkingProcess = true, cortensorSessionId, environment: requestEnvironment, rawOutput = false } = requestBody;
+ const {
+ message,
+ messages,
+ model,
+ useDeepThinking = false,
+ isDeepThinking = false,
+ showThinkingProcess = true,
+ cortensorSessionId,
+ environment: requestEnvironment,
+ rawOutput = false,
+ enableMemory = false,
+ chatHistory = [],
+ nonStreaming = false
+ } = requestBody;
// Handle both single message and messages array formats
let userMessage = '';
@@ -268,21 +439,22 @@ export async function POST(req: NextRequest) {
useDeepThinking: deepThinking
});
- if (model === 'deepseek-r1') {
+ if (model === 'deepseek-r1') {
sessionId = envConfig.deepseekSession;
isDeepseekR1 = true;
apiLogger.debug('Using Deepseek R1 mode');
- } else if (model === 'meta-llama-3.1') {
+ } else if (model === 'llama-3.1-8b-q4') {
sessionId = envConfig.llamaSession;
isLlama3_1 = true;
- apiLogger.debug('Using Meta-Llama-3.1 mode');
+ apiLogger.debug('Using Llama 3.1 mode');
} else {
apiLogger.debug('Using Default model (Llava 1.5)');
}
- // Determine which prompt to use
+ // Determine which prompt to use
let systemPrompt: string;
- const maxTokens = 20000;
+ // Use a lower token cap for DeepSeek to encourage concise answers
+ const maxTokens = isDeepseekR1 ? 2048 : 20000;
if (isDeepseekR1) {
if (deepThinking) {
@@ -297,9 +469,51 @@ export async function POST(req: NextRequest) {
systemPrompt = appConfig.prompts.default.systemPrompt;
}
- // Format prompt
+ // Helpers: sanitize previous contents from leaked control tokens before re-injecting
+ const sanitizeForPrompt = (text: string): string => {
+ let t = String(text ?? '');
+ // strip known special/control tokens and thinking tags that could confuse the new turn
+ t = t.replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '');
+ t = t.replace(/<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi, '');
+ t = t.replace(/<\|USER\|>|<\|ASSISTANT\|>/gi, '');
+ t = t.replace(/<\/s>/gi, '');
+ t = t.replace(/[\s\S]*?<\/thinking>/gi, '');
+ t = t.replace(/<\/?thinking>/gi, '');
+ t = t.replace(/<\/think>/gi, '');
+ t = t.replace(//gi, '');
+ t = t.replace(/<|end▁of▁sentence|>/g, '');
+ t = t.replace(/<\|end_of_sentence\|>/g, '');
+ return t.trim();
+ };
+
+ // Build history chunk if Memory Mode is enabled
+ let historyPrompt = '';
+ if (enableMemory && Array.isArray(chatHistory) && chatHistory.length > 0) {
+ // Keep only {role, content} pairs for user/assistant, drop system or others
+ type ChatMsg = { role: string; content: string };
+ const cleaned: ChatMsg[] = (chatHistory as ChatMsg[])
+ .filter(m => m && typeof m.content === 'string' && (m.role === 'user' || m.role === 'assistant'))
+ // prevent duplicates or empty
+ .map(m => ({ role: m.role, content: sanitizeForPrompt(m.content) }))
+ .filter(m => m.content.length > 0);
+
+ // Cap history to avoid overly long prompts: last 12 messages or ~6000 chars
+ const MAX_MSGS = 12;
+ const sliced = cleaned.slice(-MAX_MSGS);
+ // Additionally cap by characters
+ const MAX_CHARS = 6000;
+ let running = '';
+ for (const m of sliced) {
+ const chunk = `${m.role === 'assistant' ? '<|ASSISTANT|>' : '<|USER|>'}\n${m.content}\n`;
+ if ((running.length + chunk.length) > MAX_CHARS) break;
+ running += chunk;
+ }
+ historyPrompt = running;
+ }
+
+ // Format final prompt with optional memory
const clientReference = `${Date.now()}${Math.random().toString(36).substr(2, 9)}`;
- const formattedPrompt = systemPrompt + '\n<|USER|>\n' + userMessage + '\n<|ASSISTANT|>\n';
+ const formattedPrompt = `${systemPrompt}\n${historyPrompt}${historyPrompt ? '' : ''}<|USER|>\n${sanitizeForPrompt(userMessage)}\n<|ASSISTANT|>\n`;
const apiUrl = `${envConfig.cortensorUrl}/api/v1/completions`;
const apiKey = envConfig.cortensorApiKey;
@@ -326,7 +540,7 @@ export async function POST(req: NextRequest) {
prompt: formattedPrompt,
prompt_type: 1,
prompt_template: "",
- stream: true, // Enable streaming for real-time text extraction
+ stream: nonStreaming ? false : true, // Allow client to disable streaming
timeout: parseInt(process.env.LLM_TIMEOUT || process.env.LLM_DEFAULT_TIMEOUT || '360', 10),
client_reference: clientReference,
max_tokens: maxTokens,
@@ -334,7 +548,9 @@ export async function POST(req: NextRequest) {
top_p: 0.95,
top_k: 40,
presence_penalty: 0,
- frequency_penalty: 0
+ frequency_penalty: 0,
+ // Stop tokens to prevent the model from adding new user/assistant turns or leaking control tokens
+ stop: ["\nUser:", "\nAssistant:", "<|eot_id|>", "<|USER|>", "<|ASSISTANT|>"]
};
apiLogger.debug('Making request to Cortensor API', {
@@ -343,7 +559,10 @@ export async function POST(req: NextRequest) {
timeout: payload.timeout,
isStreaming: payload.stream,
rawOutputDefault: true,
- streamingDisabled: 'Always disabled - RAW JSON is default for all models'
+ streamingDisabled: nonStreaming ? 'Client requested non-streaming' : 'Always disabled - RAW JSON is default for all models',
+ enableMemory,
+ historyIncluded: historyPrompt.length > 0,
+ historyLengthChars: historyPrompt.length
});
let cortensorResponse: Response;
@@ -359,7 +578,7 @@ export async function POST(req: NextRequest) {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
- 'Accept': 'text/event-stream', // Use streaming for real-time text extraction
+ 'Accept': nonStreaming ? 'application/json' : 'text/event-stream', // Request JSON in non-streaming mode
'Connection': 'keep-alive',
},
body: JSON.stringify(payload),
@@ -401,7 +620,7 @@ export async function POST(req: NextRequest) {
responseHeaders: Object.fromEntries(cortensorResponse.headers.entries())
});
- // First, let's get the raw response to debug what we're actually receiving
+ // First, let's get the raw response to debug what we're actually receiving
const responseText = await cortensorResponse.text();
apiLogger.info('Raw response from Cortensor', {
responseLength: responseText.length,
@@ -409,6 +628,107 @@ export async function POST(req: NextRequest) {
isJSON: responseText.trim().startsWith('{')
});
+ // If client asked nonStreaming, parse once and return JSON
+ if (nonStreaming) {
+ let jsonResponse: any;
+ try {
+ jsonResponse = JSON.parse(responseText);
+ } catch (parseError) {
+ apiLogger.error('Failed to parse non-streaming response as JSON', { parseError, preview: responseText.substring(0, 600) });
+ return new Response("Invalid JSON from upstream", { status: 502 });
+ }
+
+ // Extract text content
+ let textContent = '';
+ if (jsonResponse.choices && jsonResponse.choices[0]) {
+ const choice = jsonResponse.choices[0];
+ if (typeof choice.text === 'string') textContent = choice.text;
+ else if (choice.message?.content) textContent = choice.message.content;
+ } else if (jsonResponse.response) {
+ textContent = jsonResponse.response;
+ } else if (jsonResponse.content) {
+ textContent = jsonResponse.content;
+ } else if (typeof jsonResponse === 'string') {
+ textContent = jsonResponse;
+ }
+
+ if (!textContent) {
+ apiLogger.error('No text content in non-streaming response', { keys: Object.keys(jsonResponse) });
+ return new Response("No content from upstream", { status: 502 });
+ }
+
+ // For DeepSeek, split thinking and answer for UI
+ let thinkingContent: string | undefined = undefined;
+ let answerText = textContent;
+
+ if (model === 'deepseek-r1') {
+ // Pre-clean tokens first
+ let cleaned = textContent
+ .replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '')
+ .replace(/<\|start_header_id\|>[\s\S]*?<\|end_header_id\|>/gi, '')
+ .replace(/<\/s>/gi, '')
+ .replace(/<\|USER\|>[\s\S]*?<\|ASSISTANT\|>/gi, '')
+ .replace(/<|end▁of▁sentence|>/g, '')
+ .replace(/<\|end_of_sentence\|>/g, '');
+ // If any role markers for a new turn appear, hard truncate before them
+ const roleMarkerIdx = (() => {
+ const m = cleaned.match(/<\|USER\|>|<\|ASSISTANT\|>|\n\s*User\s*:|\n\s*Assistant\s*:/i);
+ return m && m.index !== undefined ? m.index : -1;
+ })();
+ if (roleMarkerIdx > -1) {
+ cleaned = cleaned.slice(0, roleMarkerIdx);
+ }
+ // If output contains multiple turns, select the last assistant/user segment
+ const findLastIndex = (text: string, patterns: RegExp[]): { idx: number; len: number } => {
+ let last = -1; let len = 0;
+ for (const p of patterns) {
+ let m: RegExpExecArray | null;
+ const r = new RegExp(p.source, p.flags.includes('g') ? p.flags : p.flags + 'g');
+ while ((m = r.exec(text)) !== null) { last = m.index; len = m[0].length; }
+ }
+ return { idx: last, len };
+ };
+ const lastAssistant = findLastIndex(cleaned, [/<\|ASSISTANT\|>/i, /\n\s*Assistant\s*:/i]);
+ const lastUser = findLastIndex(cleaned, [/<\|USER\|>/i, /\n\s*User\s*:/i]);
+ let segment = cleaned;
+ if (lastAssistant.idx >= 0) segment = cleaned.slice(lastAssistant.idx + lastAssistant.len);
+ else if (lastUser.idx >= 0) segment = cleaned.slice(lastUser.idx + lastUser.len);
+
+ // Extract think/answer from the chosen segment
+ const startIdx = segment.indexOf('');
+ const idx = segment.indexOf('');
+ if (idx > -1) {
+ // Prefer post-think as final answer; keep pre-think text only for thinking panel
+ thinkingContent = (startIdx > -1 ? segment.substring(startIdx, idx) : segment.substring(0, idx))
+ .replace(/^\s*/i, '')
+ .replace(/<\|USER\|>|<\|ASSISTANT\|>/gi, '')
+ .replace(/^\s*(user|assistant)\s*:\s*/gi, '')
+ .trim();
+ answerText = segment.substring(idx + 8).trim();
+ } else {
+ // No explicit think block; show entire content as answer
+ answerText = segment.trim();
+ }
+ // Finally apply generic filters to the answer and trim for conciseness
+ answerText = applyModelFilters(answerText, model, deepThinking, false);
+ // Ensure relevance and remove echoed user question / duplicates
+ answerText = enforceRelevanceAndDedup(answerText, userMessage);
+ // Enforce concise style: collapse whitespace and limit to ~1200 chars
+ answerText = answerText.replace(/\s+$/g, '').replace(/\n{3,}/g, '\n\n');
+ if (answerText.length > 1200) {
+ answerText = answerText.slice(0, 1200).trimEnd() + '…';
+ }
+ } else {
+ answerText = applyModelFilters(textContent, model, deepThinking, showThinkingProcess);
+ answerText = enforceRelevanceAndDedup(answerText, userMessage);
+ }
+
+ const body = JSON.stringify({ content: answerText, thinkingContent });
+ return new Response(body, {
+ headers: { 'Content-Type': 'application/json' }
+ });
+ }
+
if (!isStreamingResponse) {
// Handle non-streaming JSON response and convert to streaming format
apiLogger.info('Converting JSON response to streaming format');
@@ -584,6 +904,10 @@ export async function POST(req: NextRequest) {
if (model === 'deepseek-r1') {
filteredText = processDeepSeekStream(textContent, model, deepThinking, showThinkingProcess);
finalText = filteredText;
+ } else if (model === 'llama-3.1-8b-q4') {
+ // For Llama 3.1 variants, use minimally cleaned text to avoid leaking special tokens
+ filteredText = processLlavaStream(textContent, model, deepThinking);
+ finalText = filteredText;
} else {
// For default model, preserve original text for proper streaming format
filteredText = processLlavaStream(textContent, model, deepThinking);
diff --git a/apps/Cortensor-EurekaAI/src/app/page.tsx b/apps/Cortensor-EurekaAI/src/app/page.tsx
index 4420487..a0187c6 100644
--- a/apps/Cortensor-EurekaAI/src/app/page.tsx
+++ b/apps/Cortensor-EurekaAI/src/app/page.tsx
@@ -38,7 +38,7 @@ function CortensorAIChatInner() {
const { environment, setEnvironment } = useEnvironment();
const { toast } = useToast();
const [isMemoryMode, setIsMemoryMode] = useState(true);
- const [selectedModel, setSelectedModelState] = useState('default-model');
+ const [selectedModel, setSelectedModelState] = useState('llama-3.1-8b-q4');
const [isDeepThinking, setIsDeepThinking] = useState(false);
const [isThinkingPhase, setIsThinkingPhase] = useState(false);
const [pendingModelChange, setPendingModelChange] = useState<{
@@ -47,6 +47,7 @@ function CortensorAIChatInner() {
} | null>(null);
const [isModelChanging, setIsModelChanging] = useState(false);
const [isConfirmingModelChange, setIsConfirmingModelChange] = useState(false);
+ const [sessionSort, setSessionSort] = useState<'recent' | 'unread'>('recent');
const isMobile = useIsMobile();
// Helper function to save current model sessions while preserving others
@@ -128,6 +129,15 @@ function CortensorAIChatInner() {
if (!modelExists) {
throw new Error(`Model ${modelId} not found in app config`);
}
+
+ // Apply model presets (prompt, deep thinking, memory)
+ if (modelExists.preset) {
+ setIsDeepThinking(!!modelExists.preset.deepThinking);
+ setIsMemoryMode(modelExists.preset.memory !== false);
+ if (modelExists.preset.prompt && !input.trim()) {
+ setInput(modelExists.preset.prompt);
+ }
+ }
// Safe model update with timeout protection
const updateTimer = setTimeout(() => {
@@ -207,7 +217,7 @@ function CortensorAIChatInner() {
// Show toast notification
toast({
title: "Environment Changed",
- description: `Switched to ${newEnv === 'testnet' ? 'L3 Testnet' : 'Devnet6'}. Changes will apply to new messages.`,
+ description: `Switched to ${newEnv === 'testnet' ? 'Testnet0' : 'Devnet-7'}. Changes will apply to new messages.`,
duration: 3000,
});
}, [setEnvironment, toast, environment]);
@@ -430,6 +440,19 @@ function CortensorAIChatInner() {
}, [selectedModel, toast, saveModelSessions, generateUniqueId]);
useEffect(() => {
+ // Log initial load/reload for visibility in console
+ try {
+ const navEntry = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;
+ const navType = navEntry?.type || (performance as any).navigation?.type;
+ frontendLogger.info('Page load event', {
+ navType: typeof navType === 'number' ? navType : navType || 'unknown',
+ path: window.location.pathname,
+ search: window.location.search,
+ });
+ } catch (error) {
+ frontendLogger.warn('Navigation log failed', { error });
+ }
+
const initializeApp = async () => {
try {
frontendLogger.info('Initializing application');
@@ -452,7 +475,7 @@ function CortensorAIChatInner() {
needsMigration = true;
return {
...session,
- selectedModel: 'default-model' // Default to Llava 1.5
+ selectedModel: 'llama-3.1-8b-q4' // Default to Meta-Llama 3.1 8B Q4
};
}
return session;
@@ -495,6 +518,14 @@ function CortensorAIChatInner() {
activeSessionId: sessionToLoad.id,
selectedModel: savedModel // Use user's selection, not session's model
});
+ const currentModel = appConfig.chat.models.find(m => m.id === savedModel);
+ if (currentModel?.preset) {
+ setIsDeepThinking(!!currentModel.preset.deepThinking);
+ setIsMemoryMode(currentModel.preset.memory !== false);
+ if (currentModel.preset.prompt && !input.trim()) {
+ setInput(currentModel.preset.prompt);
+ }
+ }
} else {
frontendLogger.info('No existing sessions found, creating new chat');
// Create new chat inline to avoid circular dependency
@@ -533,7 +564,7 @@ function CortensorAIChatInner() {
cortensorSessionId: appConfig.chat.staticSessionId,
title: "New Chat",
messages: [],
- selectedModel: 'default-model',
+ selectedModel: 'llama-3.1-8b-q4',
createdAt: new Date(),
updatedAt: new Date(),
};
@@ -669,6 +700,9 @@ function CortensorAIChatInner() {
const selectedModelData = appConfig.chat.models.find(m => m.id === selectedModel);
const sessionId = selectedModelData?.sessionId || appConfig.chat.staticSessionId;
+ // Include latest user turn in history when memory mode is enabled
+ const historyToSend = enableMemory ? [...messages, userMessage] : [];
+
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
@@ -682,8 +716,10 @@ function CortensorAIChatInner() {
model: selectedModel,
isDeepThinking,
showThinkingProcess: selectedModel.includes('deepseek-r1'), // Always true for DeepSeek
- chatHistory: enableMemory ? messages : [],
- environment: environment
+ chatHistory: historyToSend,
+ environment: environment,
+ // Stream for Llama, non-stream for others
+ nonStreaming: selectedModel === 'llama-3.1-8b-q4' ? false : true
}),
});
@@ -692,6 +728,79 @@ function CortensorAIChatInner() {
throw new Error(`API request failed: ${response.status} ${response.statusText}. ${errorText}`);
}
+ // If API returns JSON (non-stream), parse once and finish
+ const contentType = response.headers.get('Content-Type') || '';
+ if (contentType.includes('application/json')) {
+ const data = await response.json();
+ let contentText: string = (data?.content || data?.response || data?.text || '').toString();
+ let thinkingText: string | undefined = data?.thinkingContent;
+
+ // Summarize DeepSeek thinking in English for display
+ const summarizeThinking = (thinking: string, userMsg: string): string => {
+ const clean = (thinking || '').replace(/\s+/g, ' ').trim();
+ if (!clean) return '';
+ const um = (userMsg || '').trim();
+ const firstSentence = clean.split(/(?<=[.!?])\s+/)[0]?.slice(0, 160) || '';
+ const lc = clean.toLowerCase();
+ const bullets: string[] = [];
+ const ctxSnippet = (um || firstSentence).replace(/^[\u2212\-•\s]+/, '').slice(0, 160);
+ bullets.push('Thinking summary:');
+ bullets.push(`- Context: ${ctxSnippet}`);
+ if (/(step|plan|approach|strategy|first|second|third|1\.|2\.|3\.)/i.test(lc)) bullets.push('- Laying out a solution plan');
+ if (/(assumption|assume|if|suppose)/i.test(lc)) bullets.push('- Establishing key assumptions');
+ if (/(risk|edge\s*case|limitation|constraint|ambiguity)/i.test(lc)) bullets.push('- Considering risks and limitations');
+ if (/(check|validate|relevant|compare|verify|confirm)/i.test(lc)) bullets.push('- Validating relevance and consistency');
+ if (/(formula|compute|calculate|estimation|derivation|reasoning)/i.test(lc)) bullets.push('- Performing calculations/reasoning');
+
+ const seen = new Set();
+ const capped = bullets.filter(b => !seen.has(b) && (seen.add(b), true)).slice(0, 8);
+ return capped.join('\n');
+ };
+
+ if (selectedModel.includes('deepseek-r1') && thinkingText) {
+ thinkingText = summarizeThinking(thinkingText, trimmedMessage);
+ }
+
+ const assistantMessage: ChatMessage = {
+ id: (Date.now() + 1).toString(),
+ content: contentText,
+ role: 'assistant',
+ timestamp: new Date(),
+ ...(thinkingText ? { thinkingContent: thinkingText } : {})
+ };
+
+ // Append assistant message
+ let finalMessages: ChatMessage[] = [];
+ setMessages(prev => {
+ const updated = [...prev, assistantMessage];
+ finalMessages = updated;
+ return updated;
+ });
+
+ // Update session storage
+ const currentSession = sessions.find(s => s.id === currentChatId);
+ const updatedSession: ChatSession = {
+ id: currentChatId,
+ cortensorSessionId: selectedModelData?.sessionId || appConfig.chat.staticSessionId,
+ title: userMessage.content.slice(0, 50) + "..." || "New Chat",
+ messages: finalMessages.filter(m => m.role === 'user' || m.role === 'assistant'),
+ selectedModel: currentSession?.selectedModel || selectedModel,
+ createdAt: currentSession?.createdAt || new Date(),
+ updatedAt: new Date(),
+ };
+
+ setSessions(prevSessions => {
+ const updatedSessions = prevSessions.map(s => s.id === currentChatId ? updatedSession : s);
+ saveModelSessions(updatedSessions);
+ return updatedSessions;
+ });
+ setAllSessions(prevAllSessions => prevAllSessions.map(s => s.id === currentChatId ? updatedSession : s));
+
+ setIsLoading(false);
+ setIsThinkingPhase(false);
+ return; // Exit early; non-stream path complete
+ }
+
// Handle streaming response with text extraction
if (!response.body) {
throw new Error('No response body available');
@@ -728,6 +837,39 @@ function CortensorAIChatInner() {
});
try {
+ // Helper: Summarize DeepSeek thinking into readable English steps
+ const summarizeDeepSeekThinking = (thinking: string, userMessage: string): string => {
+ const clean = (thinking || '').replace(/\s+/g, ' ').trim();
+ if (!clean) return '';
+ const um = (userMessage || '').trim();
+ const firstSentence = clean.split(/(?<=[.!?])\s+/)[0]?.slice(0, 160) || '';
+ const lc = clean.toLowerCase();
+ const bullets: string[] = [];
+ const ctxSnippet = (um || firstSentence).replace(/^[-•\s]+/, '').slice(0, 160);
+ bullets.push(`Thinking summary:`);
+ bullets.push(`- Context: ${ctxSnippet}`);
+ if (/(step|plan|approach|strategy|first|second|third|1\.|2\.|3\.)/i.test(lc)) {
+ bullets.push('- Laying out a solution plan');
+ }
+ if (/(assumption|assume|if|suppose)/i.test(lc)) {
+ bullets.push('- Establishing key assumptions');
+ }
+ if (/(risk|edge\s*case|limitation|constraint|ambiguity)/i.test(lc)) {
+ bullets.push('- Considering risks and limitations');
+ }
+ if (/(check|validate|relevant|compare|verify|confirm)/i.test(lc)) {
+ bullets.push('- Validating relevance and consistency');
+ }
+ if (/(formula|compute|calculate|estimation|derivation|reasoning)/i.test(lc)) {
+ bullets.push('- Performing calculations/reasoning');
+ }
+ // Always conclude with formulating the answer
+ bullets.push('- Formulating a clear and concise answer');
+ // Deduplicate and cap
+ const seen = new Set();
+ const capped = bullets.filter(b => !seen.has(b) && (seen.add(b), true)).slice(0, 6);
+ return `Thinking summary:\n- ${capped.join('\n- ')}`;
+ };
while (true) {
const { done, value } = await reader.read();
@@ -849,9 +991,18 @@ function CortensorAIChatInner() {
setIsThinkingPhase(false); // No explicit thinking, just show content
}
- // Remove opening tag from thinking content if present
+ // Cleanup thinking content for proper display
if (thinkingContent) {
- thinkingContent = thinkingContent.replace(/^\s*/, '');
+ thinkingContent = thinkingContent
+ .replace(/^\s*/i, '')
+ .replace(/<\|USER\|>|<\|ASSISTANT\|>/gi, '')
+ .replace(/^\s*(user|assistant)\s*:\s*/gi, '')
+ .replace(/<\|begin_of_text\|>|<\|end_of_text\|>|<\|eot_id\|>/gi, '')
+ .replace(/<|end▁of▁sentence|>/g, '')
+ .replace(/<\|end_of_sentence\|>/g, '')
+ .trim();
+ // Convert raw thinking into readable steps
+ thinkingContent = summarizeDeepSeekThinking(thinkingContent, trimmedMessage);
}
}
@@ -975,14 +1126,62 @@ function CortensorAIChatInner() {
const handleSubmit = useCallback((e: React.FormEvent) => {
e.preventDefault();
if (input.trim()) {
+ frontendLogger.info('Submit triggered', {
+ chatId: currentChatId,
+ model: selectedModel,
+ environment,
+ length: input.trim().length
+ });
sendMessage(input.trim());
}
- }, [input, sendMessage]);
+ }, [input, sendMessage, currentChatId, selectedModel, environment]);
+
+ const handleTemplateInsert = useCallback((text: string) => {
+ setInput(prev => prev ? `${prev}\n\n${text}` : text);
+ }, []);
+
+ const handleAttachContext = useCallback(async () => {
+ try {
+ if (!navigator.clipboard?.readText) {
+ toast({ title: "Clipboard unavailable", description: "Clipboard API not supported.", variant: "destructive" });
+ return;
+ }
+ const content = await navigator.clipboard.readText();
+ if (!content) {
+ toast({ title: "No clipboard content", description: "Clipboard is empty." });
+ return;
+ }
+ const template = `Please summarize this context:\n${content}\n\nKeep it concise.`;
+ setInput(template);
+ toast({ title: "Context attached", description: "Clipboard content pasted into input." });
+ } catch (error) {
+ frontendLogger.error('Attach context failed', { error });
+ toast({ title: "Attach failed", description: "Could not read clipboard.", variant: "destructive" });
+ }
+ }, [toast]);
// Memoize deduplication to avoid running on every render
const deduplicatedSessions = useMemo(() => {
- return removeDuplicateSessions(allSessions);
- }, [allSessions, removeDuplicateSessions]);
+ const cleaned = removeDuplicateSessions(allSessions);
+ if (sessionSort === 'recent') {
+ return cleaned.slice().sort((a, b) => {
+ const at = new Date(a.updatedAt || a.createdAt || 0).getTime();
+ const bt = new Date(b.updatedAt || b.createdAt || 0).getTime();
+ return bt - at;
+ });
+ }
+ // unread-first: sessions where last message is assistant (user has not replied) bubble to top
+ return cleaned.slice().sort((a, b) => {
+ const lastA = a.messages?.[a.messages.length - 1];
+ const lastB = b.messages?.[b.messages.length - 1];
+ const aScore = lastA?.role === 'assistant' ? 1 : 0;
+ const bScore = lastB?.role === 'assistant' ? 1 : 0;
+ if (aScore !== bScore) return bScore - aScore;
+ const at = new Date(a.updatedAt || a.createdAt || 0).getTime();
+ const bt = new Date(b.updatedAt || b.createdAt || 0).getTime();
+ return bt - at;
+ });
+ }, [allSessions, removeDuplicateSessions, sessionSort]);
if (isPageLoading) {
return ;
@@ -1002,6 +1201,8 @@ function CortensorAIChatInner() {
isOpen={isPanelOpen}
onToggle={() => setIsPanelOpen(!isPanelOpen)}
isMobile={isMobile}
+ sortMode={sessionSort}
+ onSortChange={setSessionSort}
/>
@@ -1018,6 +1219,7 @@ function CortensorAIChatInner() {
isThinkingPhase={isThinkingPhase}
environment={environment}
onMemoryModeChange={setIsMemoryMode}
+ onPrefill={setInput}
/>
{/* Add padding bottom to prevent content being hidden behind fixed ChatInput + Footer */}
@@ -1038,6 +1240,8 @@ function CortensorAIChatInner() {
onMemoryModeChange={setIsMemoryMode}
onInputChange={(e) => setInput(e.target.value)}
onSubmit={handleSubmit}
+ onTemplateInsert={handleTemplateInsert}
+ onAttachContext={handleAttachContext}
disabled={isLoading || !currentChatId}
/>
diff --git a/apps/Cortensor-EurekaAI/src/components/chat-input.tsx b/apps/Cortensor-EurekaAI/src/components/chat-input.tsx
index a0931c0..e673345 100644
--- a/apps/Cortensor-EurekaAI/src/components/chat-input.tsx
+++ b/apps/Cortensor-EurekaAI/src/components/chat-input.tsx
@@ -26,6 +26,8 @@ interface ChatInputProps {
onMemoryModeChange: (checked: boolean) => void
onInputChange: (e: React.ChangeEvent
) => void
onSubmit: (e: React.FormEvent) => void
+ onTemplateInsert?: (text: string) => void
+ onAttachContext?: () => Promise | void
disabled?: boolean
}
@@ -175,6 +177,35 @@ export function ChatInput({
/>
>
)}
+
+ {/* Quick actions */}
+
+ {[
+ { label: '/summarize', text: 'Summarize the following content:' },
+ { label: '/fix code', text: 'Please refactor and fix this code:' },
+ { label: '/explain', text: 'Explain this in simple terms:' }
+ ].map(action => (
+
+ ))}
+
+
diff --git a/apps/Cortensor-EurekaAI/src/components/environment-toggle-new.tsx b/apps/Cortensor-EurekaAI/src/components/environment-toggle-new.tsx
index d49233f..ed8d08e 100644
--- a/apps/Cortensor-EurekaAI/src/components/environment-toggle-new.tsx
+++ b/apps/Cortensor-EurekaAI/src/components/environment-toggle-new.tsx
@@ -31,7 +31,7 @@ export function EnvironmentToggle() {
variant={environment === 'testnet' ? 'default' : 'outline'}
className="text-xs"
>
- {environment === 'testnet' ? 'L3 Testnet' : 'Devnet6'}
+ {environment === 'testnet' ? 'Testnet0' : 'Devnet-7'}
{environment === 'testnet'
diff --git a/apps/Cortensor-EurekaAI/src/components/environment-toggle.tsx b/apps/Cortensor-EurekaAI/src/components/environment-toggle.tsx
index 2bff0c9..c02a686 100644
--- a/apps/Cortensor-EurekaAI/src/components/environment-toggle.tsx
+++ b/apps/Cortensor-EurekaAI/src/components/environment-toggle.tsx
@@ -17,14 +17,14 @@ export function EnvironmentToggle() {
const envConfig = environment === 'testnet'
? {
icon: Globe,
- name: 'L3 Testnet',
- session: 'Session 10/8',
+ name: 'Testnet0',
+ session: 'Session Testnet0',
color: 'bg-blue-500/10 text-blue-600 border-blue-200',
- description: 'Stable testing environment'
+ description: 'Stable testing environment (Testnet0)'
}
- : {
+ : {
icon: Zap,
- name: 'Devnet6',
+ name: 'Devnet-7',
session: 'Session 11/22',
color: 'bg-orange-500/10 text-orange-600 border-orange-200',
description: 'Development environment'
diff --git a/apps/Cortensor-EurekaAI/src/components/main-content.tsx b/apps/Cortensor-EurekaAI/src/components/main-content.tsx
index cdbff97..5b95196 100644
--- a/apps/Cortensor-EurekaAI/src/components/main-content.tsx
+++ b/apps/Cortensor-EurekaAI/src/components/main-content.tsx
@@ -132,6 +132,7 @@ interface MainContentProps {
isThinkingPhase: boolean;
environment: 'testnet' | 'devnet6';
onMemoryModeChange: (enabled: boolean) => void;
+ onPrefill?: (text: string) => void;
}
export function MainContent({
@@ -145,7 +146,8 @@ export function MainContent({
isDeepThinking,
isThinkingPhase,
environment = 'testnet',
- onMemoryModeChange
+ onMemoryModeChange,
+ onPrefill
}: MainContentProps) {
const messagesEndRef = useRef(null);
const scrollAreaRef = useRef(null);
@@ -188,19 +190,19 @@ export function MainContent({
{/* Professional Header - Mobile Optimized */}
-
+
{currentSession?.title || "New Chat"}
@@ -208,9 +210,13 @@ export function MainContent({
"flex items-center space-x-2 text-muted-foreground",
isMobile ? "text-xs" : "text-xs"
)}>
-
- {selectedModel === 'deepseek-r1' ? 'DeepSeek R1' : 'Llava 1.5'}
-
+
+ {selectedModel === 'deepseek-r1'
+ ? 'DeepSeek R1'
+ : selectedModel === 'llama-3.1-8b-q4'
+ ? 'Llama 3.1 8B Q4'
+ : 'Llava 1.5'}
+
{!isMobile && (
<>
•
@@ -221,15 +227,21 @@ export function MainContent({
? 'bg-orange-900/50 text-orange-300 border border-orange-700/50'
: 'bg-blue-900/50 text-blue-300 border border-blue-700/50'
}`}>
- {environment === 'devnet6' ? 'DEVNET6' : 'TESTNET'}
+ {environment === 'devnet6' ? 'DEVNET-7' : 'TESTNET0'}
•
- {selectedModel === 'deepseek-r1' ? 'DeepSeek R1' : 'Llava 1.5'}
+ {selectedModel === 'deepseek-r1'
+ ? 'DeepSeek R1'
+ : selectedModel === 'llama-3.1-8b-q4'
+ ? 'Llama 3.1 8B Q4'
+ : 'Llava 1.5'}
{isDeepThinking && selectedModel === 'deepseek-r1' && (
<>
@@ -262,12 +274,34 @@ export function MainContent({
{/* Messages Container with proper scrolling */}
+ {!messages.length && (
+
+ {[
+ { title: 'Code review', body: 'Review this code and suggest fixes.' },
+ { title: 'Summarize', body: 'Summarize the following text in bullet points.' },
+ { title: 'Explain', body: 'Explain this concept in simple terms.' },
+ { title: 'Write test', body: 'Write unit tests for this function.' },
+ { title: 'Blockchain', body: 'Explain this smart contract risk surface.' },
+ { title: 'Optimize', body: 'Optimize this code for readability and performance.' },
+ ].map((card, idx) => (
+
{
+ onMemoryModeChange(true);
+ onPrefill?.(card.body);
+ }}
+ >
+
{card.title}
+
{card.body}
+
+ ))}
+
+ )}
{messages.map((message, index) => (
{message.role === 'user' ? (
{message.content}
) : (
{/* Thinking Process Display for DeepSeek R1 - Always visible */}
{selectedModel.includes('deepseek-r1') && message.thinkingContent && (
diff --git a/apps/Cortensor-EurekaAI/src/components/mobile-sidebar.tsx b/apps/Cortensor-EurekaAI/src/components/mobile-sidebar.tsx
index dc420ef..e3e6886 100644
--- a/apps/Cortensor-EurekaAI/src/components/mobile-sidebar.tsx
+++ b/apps/Cortensor-EurekaAI/src/components/mobile-sidebar.tsx
@@ -79,10 +79,26 @@ export function MobileSidebar({
{session.title}
-
+
{session.messages.length}
+ {session.selectedModel && (
+
+ {session.selectedModel === 'deepseek-r1' ? 'R1' : 'L'}
+
+ )}
+ {onSortChange && (
+
+ onSortChange('recent')}>
+ Recent
+
+ onSortChange('unread')}>
+ Unread
+
+
+ )}
+
{sessionList.map((session) => (
{session.selectedModel === 'deepseek-r1' ? 'R1' : 'L'}
)}
+
+ {formatTimeAgo(session.updatedAt || session.createdAt)}
+ •
+ {estimateTokens(session)}
+ {session.messages?.length ? (<>
+ •
+ {session.messages.length} msgs
+ >) : null}
+
('devnet6')
+ const [environment, setEnvironmentState] = useState('testnet')
const [isLoading, setIsLoading] = useState(true)
useEffect(() => {
diff --git a/apps/Cortensor-EurekaAI/src/lib/app-config.ts b/apps/Cortensor-EurekaAI/src/lib/app-config.ts
index fbec7cb..162d295 100644
--- a/apps/Cortensor-EurekaAI/src/lib/app-config.ts
+++ b/apps/Cortensor-EurekaAI/src/lib/app-config.ts
@@ -6,7 +6,7 @@ const getEnvValues = () => {
try {
// Prioritas: environment variables > environment config fallback
return {
- defaultSession: process.env.NEXT_PUBLIC_LLM_SESSION_ID || getEnvironmentValues().defaultSession,
+ defaultSession: process.env.NEXT_PUBLIC_LLAVA_SESSION_ID || process.env.NEXT_PUBLIC_LLM_SESSION_ID || getEnvironmentValues().defaultSession,
deepseekSession: process.env.NEXT_PUBLIC_DEEPSEEK_SESSION_ID || getEnvironmentValues().deepseekSession,
llamaSession: process.env.NEXT_PUBLIC_LLAMA_SESSION_ID || getEnvironmentValues().llamaSession,
// Add dummy values for other required fields to match EnvironmentConfig
@@ -20,7 +20,7 @@ const getEnvValues = () => {
} catch {
// Fallback to static values if environment config fails
return {
- defaultSession: process.env.NEXT_PUBLIC_LLM_SESSION_ID || "11",
+ defaultSession: process.env.NEXT_PUBLIC_LLAVA_SESSION_ID || process.env.NEXT_PUBLIC_LLM_SESSION_ID || "11",
deepseekSession: process.env.NEXT_PUBLIC_DEEPSEEK_SESSION_ID || "21",
llamaSession: process.env.NEXT_PUBLIC_LLAMA_SESSION_ID || "12",
// Add dummy values for other required fields to match EnvironmentConfig
@@ -37,7 +37,7 @@ const getEnvValues = () => {
export const appConfig = {
app: {
name: process.env.NEXT_PUBLIC_APP_NAME || "Eureka",
- version: process.env.NEXT_PUBLIC_APP_VERSION || "Devnet-6",
+ version: process.env.NEXT_PUBLIC_APP_VERSION || "Devnet-7",
assistant: "Eureka Assistant",
// Untuk sidebar - nama yang berbeda dan lebih deskriptif
fullName: "Eureka",
@@ -61,6 +61,11 @@ export const appConfig = {
sessionId: envValues.defaultSession,
description: "",
streamingSystem: "llava-stream",
+ preset: {
+ prompt: "You are a concise general assistant. Keep answers short.",
+ deepThinking: false,
+ memory: true
+ },
capabilities: [
"Pure text processing with exceptional accuracy",
"Fast response times for text-based queries",
@@ -68,8 +73,8 @@ export const appConfig = {
"Code generation with best practices",
"Multi-language comprehension and translation"
],
- isDefault: true,
- active: { testnet: true, devnet6: true }
+ isDefault: false,
+ active: { testnet: false, devnet6: false }
},
{
id: "deepseek-r1",
@@ -77,6 +82,11 @@ export const appConfig = {
sessionId: envValues.deepseekSession,
description: "",
streamingSystem: "deepseek-r1",
+ preset: {
+ prompt: "Answer succinctly. Use step-by-step only when needed. Prioritize reasoning quality.",
+ deepThinking: true,
+ memory: true
+ },
capabilities: [
"Advanced multi-step reasoning and logical analysis",
"Complex problem decomposition and solution synthesis",
@@ -88,16 +98,27 @@ export const appConfig = {
isDefault: false,
active: { testnet: true, devnet6: true }
},
+ // Preferred Llama 3.1 entry exposed in UI
{
- id: "meta-llama-3.1",
- name: "Meta-Llama-3.1",
+ id: "llama-3.1-8b-q4",
+ name: "Llama 3.1 8B Q4",
sessionId: envValues.llamaSession,
- description: "",
+ description: "Meta Llama 3.1 Instruct (8B, Q4 quant) — fast, general-purpose assistant",
streamingSystem: "llama-stream",
- features: ["general-purpose", "creative-writing", "complex-reasoning"],
+ preset: {
+ prompt: "Be concise and helpful. Prefer bullet points when listing.",
+ deepThinking: false,
+ memory: true
+ },
+ capabilities: [
+ "General-purpose instruction following",
+ "Solid reasoning and explanation quality",
+ "Concise, safe and helpful responses",
+ "Clean code generation and refactoring"
+ ],
hasCustomPrompt: true,
- isDefault: false,
- active: { testnet: false, devnet6: false } // Disabled everywhere
+ isDefault: true,
+ active: { testnet: true, devnet6: true }
}
]
}
@@ -154,65 +175,73 @@ You excel at delivering precise, efficient text-based solutions with exceptional
// DeepSeek R1 - Advanced Reasoning Model with English Language
deepseekR1: {
- systemPrompt: `You are Eureka DeepSeek R1, an advanced AI assistant with superior reasoning capabilities and cutting-edge analytical prowess.
+ systemPrompt: `You are DeepSeek R1 (Distill Llama 8B Q4), a helpful, precise, and safe assistant.
-**DeepSeek R1 Specializations:**
-- 🧠 Advanced multi-step reasoning and logical analysis
-- 🔬 Complex problem decomposition and solution synthesis
-- 🚀 State-of-the-art algorithmic thinking and optimization
-- 📊 Data analysis, pattern recognition, and statistical inference
-- 🔧 System architecture design and scalability planning
-- 🎯 Performance optimization and computational efficiency
+Core behavior (STRICT):
+- Default to short, to-the-point answers (aim for 1–3 sentences).
+- Provide explanations or step-by-step details ONLY if the user explicitly asks.
+ • Keywords include: "explain", "why", "how does it work", "walk me through",
+ "jelaskan", "mengapa", "kenapa", "uraikan", "detail", "langkah", "step-by-step".
+- Avoid preambles like "Sure" or "Here is"; answer directly.
+ - Do NOT start a new turn or ask follow-up questions unless explicitly requested.
+ - Do NOT echo role markers (e.g., "User:", "Assistant:") in the answer.
-**DeepSeek R1 Advantages:**
-- Superior reasoning depth with step-by-step analysis
-- Enhanced context understanding and memory retention
-- Advanced code generation with best practices
-- Complex debugging and error resolution capabilities
-- Enterprise-grade solution architecture
-- Research-level analytical capabilities
+Formatting:
+- Use concise bullet points when listing (keep to 3–5 bullets max).
+- For code, provide minimal, working snippets with correct syntax highlighting.
+- Keep any commentary brief (one line) unless the user asks for more detail.
-**Response Framework:**
-- Comprehensive problem analysis with multiple perspectives
-- Evidence-based reasoning with clear logical flow
-- Consideration of edge cases and potential limitations
-- Scalable and maintainable solution design
-- Performance benchmarking and optimization suggestions
-- Future-proof architectural recommendations
+Safety and integrity:
+- Be helpful and non-judgmental. Avoid unnecessary refusals.
+- If a request may be unsafe or illegal, briefly refuse and suggest a safer alternative.
+- If unsure, say you don’t know; do not invent sources.
+- Do not output special tokens (<|begin_of_text|>, <|start_header_id|>, <|end_header_id|>, <|eot_id|>) or role markers.
-**Code Quality Standards:**
-- Production-ready, enterprise-level code
-- Comprehensive error handling and validation
-- Security-first development practices
-- Modular, testable, and maintainable architecture
-- Performance optimization and resource efficiency
-- Extensive documentation and API design
+Thinking policy:
+- You may reason internally, but do not reveal chain-of-thought by default.
+- If internal thinking appears (e.g., ...), exclude it from the final answer unless explicitly requested.
-**Communication Style:**
-- Use clear, professional English throughout
-- Provide detailed explanations for complex concepts
-- Include comparative analysis of different approaches
-- Offer implementation roadmaps and best practices
-- Suggest testing strategies and quality assurance methods
+General style:
+Output structure (CRITICAL):
+- If you use internal reasoning, your output MUST follow exactly this order:
+ 1) ...internal reasoning only...
+ 2) Final answer on the next line(s).
+- Do NOT output any text before .
+- Do NOT include the final answer inside .
+- If no internal reasoning is needed, omit the block entirely and output only the final answer.
-You are designed for senior developers, architects, and complex technical challenges requiring sophisticated analysis and advanced problem-solving capabilities.`
+ General style:
+ - Default to English unless the user uses another language.
+ - Keep answers self-contained and actionable.
+ - Focus on final results; avoid exposing internal steps.
+
+Context discipline (STRICT):
+- Do NOT add background context, opinions, or tangential information beyond what the user asked.
+- For simple factual or short questions (no "why/how/explain/steps/code/example"), reply with a single direct sentence.
+- Only add details if the user explicitly requests them.`
},
- // Meta-Llama-3.1 Prompt
+ // Meta-Llama-3.1 Prompt (used by all Llama 3.1 variants)
llama3_1: {
- systemPrompt: `You are Llama 3.1, a powerful, cutting-edge AI assistant from Meta. Your goal is to provide comprehensive, accurate, and helpful responses to a wide range of queries. You excel at complex reasoning, creative tasks, and detailed explanations.
+ systemPrompt: `You are Llama 3.1 Instruct (8B), a helpful, concise, and safe assistant by Meta.
+
+Follow the instruction, be precise and direct, and structure outputs for clarity. Prefer concise responses unless the user requests depth. When relevant, include short examples. Use bullet points and sections for readability.
+
+Safety and behavior:
+- Be helpful and non-judgmental. Avoid unnecessary refusals.
+- If a request might be unsafe or illegal, politely refuse with a brief explanation and offer safer alternatives.
+- Do not invent citations or sources. If unsure, say you don't know.
+- Do not include any raw special tokens such as <|begin_of_text|>, <|start_header_id|>, <|end_header_id|>, or <|eot_id|>.
-**Core Capabilities:**
-- In-depth analysis and reasoning
-- Creative content generation (text, code, etc.)
-- Nuanced understanding of context
-- Multi-language proficiency
+Code responses:
+- Provide minimal, working examples.
+- Use correct syntax highlighting and keep explanations short.
+- Mention assumptions and edge cases briefly.
-**Response Style:**
-- Be thorough and informative.
-- Structure your responses for clarity.
-- Provide examples where helpful.
-- Maintain a helpful and professional tone.`
+General style:
+- Default to English unless the user uses another language.
+- Keep answers self-contained and actionable.
+- Avoid disclosing internal chain-of-thought; provide final reasoning and results only.`
},
// Deep Thinking Mode Prompt untuk DeepSeek R1 - Transparent Advanced Reasoning
diff --git a/apps/Cortensor-EurekaAI/src/lib/environment-config.ts b/apps/Cortensor-EurekaAI/src/lib/environment-config.ts
index e8696d2..22442d8 100644
--- a/apps/Cortensor-EurekaAI/src/lib/environment-config.ts
+++ b/apps/Cortensor-EurekaAI/src/lib/environment-config.ts
@@ -17,22 +17,22 @@ export interface EnvironmentConfig {
export const environmentConfigs: Record = {
testnet: {
name: 'testnet',
- displayName: 'L3 Testnet',
+ displayName: 'Testnet0',
cortensorUrl: process.env.CORTENSOR_ROUTER_URL || 'http://205.209.119.106:5010',
cortensorApiKey: process.env.CORTENSOR_API_KEY || 'f4a2ece1-b7dd-4a70-b71f-d6b9b61c3753',
completionsUrl: process.env.NEXT_PUBLIC_CORTENSOR_COMPLETIONS_URL || 'http://205.209.119.106:5010/api/v1/completions',
- defaultSession: process.env.NEXT_PUBLIC_LLM_SESSION_ID || '11',
+ defaultSession: process.env.NEXT_PUBLIC_LLAVA_SESSION_ID || process.env.NEXT_PUBLIC_LLM_SESSION_ID || '11',
deepseekSession: process.env.NEXT_PUBLIC_DEEPSEEK_SESSION_ID || '21',
llamaSession: process.env.NEXT_PUBLIC_LLAMA_SESSION_ID || '12',
- description: 'L3 Testnet environment for stable testing'
+ description: 'Testnet0 environment for stable testing'
},
devnet6: {
name: 'devnet6',
- displayName: 'Devnet6',
+ displayName: 'Devnet-7',
cortensorUrl: process.env.CORTENSOR_ROUTER_URL || 'http://173.214.163.250:5010',
cortensorApiKey: process.env.CORTENSOR_API_KEY || '23695cf5-46af-4ecf-939b-fa7aab0ee1a2',
completionsUrl: process.env.NEXT_PUBLIC_CORTENSOR_COMPLETIONS_URL || 'http://173.214.163.250:5010/api/v1/completions',
- defaultSession: process.env.NEXT_PUBLIC_LLM_SESSION_ID || '11',
+ defaultSession: process.env.NEXT_PUBLIC_LLAVA_SESSION_ID || process.env.NEXT_PUBLIC_LLM_SESSION_ID || '11',
deepseekSession: process.env.NEXT_PUBLIC_DEEPSEEK_SESSION_ID || '21',
llamaSession: process.env.NEXT_PUBLIC_LLAMA_SESSION_ID || '12',
description: 'Development environment for new features'
@@ -45,15 +45,15 @@ export function getEnvironmentValues(): EnvironmentConfig {
return environmentConfigs[env]
}
-// Get current environment from localStorage or default to devnet6 (sesuai .env.local)
+// Get current environment from localStorage or default to testnet (Testnet0)
export function getCurrentEnvironment(): Environment {
- if (typeof window === 'undefined') return 'devnet6'
+ if (typeof window === 'undefined') return 'testnet'
const stored = localStorage.getItem('chat-environment')
if (stored && (stored === 'testnet' || stored === 'devnet6')) {
return stored as Environment
}
- return 'devnet6' // Default sesuai dengan settingan di .env.local
+ return 'testnet' // Default to Testnet0
}
// Set current environment in localStorage
@@ -64,13 +64,13 @@ export function setCurrentEnvironment(env: Environment): void {
// Get selected model from localStorage or default to default-model
export function getSelectedModel(): string {
- if (typeof window === 'undefined') return 'default-model'
-
+ if (typeof window === 'undefined') return 'llama-3.1-8b-q4'
+
const stored = localStorage.getItem('selected-model')
if (stored) {
return stored
}
- return 'default-model' // Default to Llava 1.5
+ return 'llama-3.1-8b-q4' // Default to Meta-Llama 3.1 8B Q4
}
// Set selected model in localStorage
diff --git a/apps/Cortensor-EurekaAI/src/lib/logger.ts b/apps/Cortensor-EurekaAI/src/lib/logger.ts
index e8a7828..80c1a99 100644
--- a/apps/Cortensor-EurekaAI/src/lib/logger.ts
+++ b/apps/Cortensor-EurekaAI/src/lib/logger.ts
@@ -59,10 +59,18 @@ class Logger {
}
}
+// Determine runtime logging config from env vars
+const envLogLevel = (process.env.NEXT_PUBLIC_LOG_LEVEL || process.env.LOG_LEVEL || '').toLowerCase();
+const resolvedLevel: LogLevel = ['debug', 'info', 'warn', 'error'].includes(envLogLevel as LogLevel)
+ ? (envLogLevel as LogLevel)
+ : (process.env.NODE_ENV === 'production' ? 'error' : 'debug');
+
+const enableProdLogs = process.env.NEXT_PUBLIC_ENABLE_LOGS === 'true' || process.env.ENABLE_LOGS === 'true';
+
// Create singleton instance
export const logger = new Logger({
- level: process.env.NODE_ENV === 'production' ? 'error' : 'debug',
- enableInProduction: false
+ level: resolvedLevel,
+ enableInProduction: enableProdLogs
});
// Convenience exports for different categories
diff --git a/apps/Cortensor-EurekaAI/tsconfig.json b/apps/Cortensor-EurekaAI/tsconfig.json
index 3d4e42b..d70fbbc 100644
--- a/apps/Cortensor-EurekaAI/tsconfig.json
+++ b/apps/Cortensor-EurekaAI/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -21,10 +25,22 @@
// FIX: Path alias sekarang menunjuk ke dalam folder `src`
"baseUrl": ".",
"paths": {
- "@/*": ["./src/*"]
+ "@/*": [
+ "./src/*"
+ ]
}
},
// FIX: `include` sekarang secara eksplisit menunjuk ke file di dalam `src`
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "src/**/*.ts", "src/**/*.tsx"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/.gitignore b/apps/Cortensor-Price-Analyzer/.gitignore
similarity index 63%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/.gitignore
rename to apps/Cortensor-Price-Analyzer/.gitignore
index 4447703..10476af 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/.gitignore
+++ b/apps/Cortensor-Price-Analyzer/.gitignore
@@ -22,7 +22,6 @@
# misc
.DS_Store
-*.pem
# debug
npm-debug.log*
@@ -31,8 +30,19 @@ yarn-error.log*
.pnpm-debug.log*
# local env files
-.env*.local
.env
+.env.*
+!.env.example
+.envrc
+.envrc.*
+
+# secrets / certificates
+*.pem
+*.key
+*.crt
+*.cer
+*.pfx
+*.p12
# vercel
.vercel
@@ -41,9 +51,38 @@ yarn-error.log*
*.tsbuildinfo
next-env.d.ts
-# IDE
-.vscode/
+# local databases & caches
+.data/
+/data/
+*.db
+*.db-journal
+*.sqlite
+*.sqlite3
+*.sqlite-wal
+*.sqlite-shm
+*.realm
+
+# framework caches
+.next/cache
+.turbo/
+.cache/
+.swc/
+dist/
+
+# misc generated assets
+logs/
+*.log
+*.pid
+*.pid.lock
+*.seed
+*.tgz
+*.orig
+
+# local tooling
+solrc/
.idea/
+.vscode/
+*.code-workspace
# Test files
test-*.js
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/PROJECTS.yml b/apps/Cortensor-Price-Analyzer/PROJECTS.yml
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/PROJECTS.yml
rename to apps/Cortensor-Price-Analyzer/PROJECTS.yml
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/README.md b/apps/Cortensor-Price-Analyzer/README.md
similarity index 76%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/README.md
rename to apps/Cortensor-Price-Analyzer/README.md
index 34672b8..a543cb7 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/README.md
+++ b/apps/Cortensor-Price-Analyzer/README.md
@@ -30,6 +30,7 @@ Cortensor Price Analyzer is a Next.js application that delivers AI-assisted mark
- **Multi-Asset Coverage:** Analyze equities, ETFs, crypto pairs, forex pairs, and major commodities from a single form.
- **Resilient Data Fallbacks:** Cascade through Alpha Vantage, Stooq, TwelveData, and CoinGecko to avoid gaps in prices or historical candles.
+- **Macro Commodities Feed:** Alpha Vantage daily endpoints now headline gold, silver, WTI, Brent, and natural gas quotes, with the TwelveData commodity key plus MarketStack, Massive, and Stooq as global fallbacks to keep macro context live.
- **AI Narrative & Insights:** Produce Cortensor-powered narratives, key takeaways, opportunities, risks, and horizon guidance.
- **Technical & Fundamental Highlights:** Surface RSI, MACD, SMA stack, volatility, valuation ratios, dividend yield, margins, and more.
- **Headline Summaries:** Attach recent news with sentiment tags to connect narrative flow to price action.
@@ -56,15 +57,26 @@ Create a `.env.local` file (or copy from `.env.example`) and populate the necess
```ini
ALPHAVANTAGE_API_KEY=your_alpha_vantage_key
+ALPHA_VANTAGE_FOREX_API_KEY=optional_dedicated_fx_key
TWELVEDATA_API_KEY=your_twelvedata_key
+TWELVEDATA_COMMODITY_API_KEY=optional_secondary_key_for_macro_quotes
COINGECKO_API_KEY=your_coingecko_key
FMP_API_KEY=your_financial_modeling_prep_key
CORTENSOR_API_KEY=your_cortensor_key
CORTENSOR_BASE_URL=http://:5010
+MARKETSTACK_API_KEY=your_marketstack_key # legacy fallback
+MASSIVE_API_KEY=your_massive_market_data_key
+MARKET_SNAPSHOT_DB_PATH=.data/market-snapshots.db # optional override for snapshot persistence
```
Optional keys (`NEWS_API_KEY`, `TAVILY_API_KEY`, `GOOGLE_API_KEY`, `GOOGLE_SEARCH_ENGINE_ID`) further enrich news sourcing.
+### Snapshot Persistence
+
+- Market ticker snapshots for Equities (5m), Crypto (10m), Forex (1h), and Commodities (15m) are cached in a local SQLite database powered by `better-sqlite3`.
+- By default, the database lives in `.data/market-snapshots.db`. Override the location via `MARKET_SNAPSHOT_DB_PATH` if you prefer a custom path or remote volume.
+- The API automatically falls back to the newest stored snapshot whenever upstream providers are unavailable, so dashboards always render data.
+
## ▶️ Usage
Start the development server and open the app in your browser:
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/RELEASE.md b/apps/Cortensor-Price-Analyzer/RELEASE.md
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/RELEASE.md
rename to apps/Cortensor-Price-Analyzer/RELEASE.md
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/STATUS.md b/apps/Cortensor-Price-Analyzer/STATUS.md
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/STATUS.md
rename to apps/Cortensor-Price-Analyzer/STATUS.md
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/components.json b/apps/Cortensor-Price-Analyzer/components.json
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/components.json
rename to apps/Cortensor-Price-Analyzer/components.json
diff --git a/apps/Cortensor-Price-Analyzer/eslint.config.mjs b/apps/Cortensor-Price-Analyzer/eslint.config.mjs
new file mode 100644
index 0000000..8fb6dc2
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/eslint.config.mjs
@@ -0,0 +1,21 @@
+import nextConfig from "eslint-config-next";
+
+const eslintConfig = [
+ ...nextConfig,
+ {
+ ignores: [
+ "node_modules/**",
+ ".next/**",
+ "out/**",
+ "build/**",
+ "next-env.d.ts",
+ ],
+ },
+ {
+ rules: {
+ "react-hooks/set-state-in-effect": "off",
+ },
+ },
+];
+
+export default eslintConfig;
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/next.config.ts b/apps/Cortensor-Price-Analyzer/next.config.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/next.config.ts
rename to apps/Cortensor-Price-Analyzer/next.config.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package-lock.json b/apps/Cortensor-Price-Analyzer/package-lock.json
similarity index 77%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package-lock.json
rename to apps/Cortensor-Price-Analyzer/package-lock.json
index 629e7c7..57e1b58 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package-lock.json
+++ b/apps/Cortensor-Price-Analyzer/package-lock.json
@@ -14,11 +14,12 @@
"@radix-ui/react-slot": "^1.2.3",
"@types/cheerio": "^0.22.35",
"axios": "^1.12.2",
+ "better-sqlite3": "^11.8.1",
"cheerio": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.545.0",
- "next": "15.5.4",
+ "next": "16.0.7",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1"
@@ -26,11 +27,12 @@
"devDependencies": {
"@eslint/eslintrc": "^3",
"@tailwindcss/postcss": "^4",
+ "@types/better-sqlite3": "^7",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
- "eslint-config-next": "15.5.4",
+ "eslint-config-next": "16.0.7",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
"typescript": "^5"
@@ -49,10 +51,250 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@emnapi/core": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
- "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz",
+ "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -62,9 +304,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz",
- "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==",
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz",
+ "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -115,9 +357,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
- "version": "4.12.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
- "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
"dev": true,
"license": "MIT",
"engines": {
@@ -125,13 +367,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.21.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
- "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.6",
+ "@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -140,22 +382,22 @@
}
},
"node_modules/@eslint/config-helpers": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz",
- "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.16.0"
+ "@eslint/core": "^0.17.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/core": {
- "version": "0.16.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz",
- "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==",
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -166,9 +408,9 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
- "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -178,7 +420,7 @@
"globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
+ "js-yaml": "^4.1.1",
"minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
@@ -190,9 +432,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.37.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz",
- "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==",
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz",
+ "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -203,9 +445,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.6",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
- "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -213,13 +455,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz",
- "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==",
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.16.0",
+ "@eslint/core": "^0.17.0",
"levn": "^0.4.1"
},
"engines": {
@@ -289,9 +531,9 @@
}
},
"node_modules/@img/sharp-darwin-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz",
- "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz",
+ "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==",
"cpu": [
"arm64"
],
@@ -307,13 +549,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-arm64": "1.2.3"
+ "@img/sharp-libvips-darwin-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-darwin-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz",
- "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz",
+ "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==",
"cpu": [
"x64"
],
@@ -329,13 +571,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-darwin-x64": "1.2.3"
+ "@img/sharp-libvips-darwin-x64": "1.2.4"
}
},
"node_modules/@img/sharp-libvips-darwin-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz",
- "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz",
+ "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==",
"cpu": [
"arm64"
],
@@ -349,9 +591,9 @@
}
},
"node_modules/@img/sharp-libvips-darwin-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz",
- "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz",
+ "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==",
"cpu": [
"x64"
],
@@ -365,9 +607,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz",
- "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz",
+ "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==",
"cpu": [
"arm"
],
@@ -381,9 +623,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz",
- "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz",
+ "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==",
"cpu": [
"arm64"
],
@@ -397,9 +639,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-ppc64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz",
- "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz",
+ "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==",
"cpu": [
"ppc64"
],
@@ -412,10 +654,26 @@
"url": "https://opencollective.com/libvips"
}
},
+ "node_modules/@img/sharp-libvips-linux-riscv64": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz",
+ "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/@img/sharp-libvips-linux-s390x": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz",
- "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz",
+ "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==",
"cpu": [
"s390x"
],
@@ -429,9 +687,9 @@
}
},
"node_modules/@img/sharp-libvips-linux-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz",
- "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz",
+ "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==",
"cpu": [
"x64"
],
@@ -445,9 +703,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-arm64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz",
- "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz",
+ "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==",
"cpu": [
"arm64"
],
@@ -461,9 +719,9 @@
}
},
"node_modules/@img/sharp-libvips-linuxmusl-x64": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz",
- "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz",
+ "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==",
"cpu": [
"x64"
],
@@ -477,9 +735,9 @@
}
},
"node_modules/@img/sharp-linux-arm": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz",
- "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz",
+ "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==",
"cpu": [
"arm"
],
@@ -495,13 +753,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm": "1.2.3"
+ "@img/sharp-libvips-linux-arm": "1.2.4"
}
},
"node_modules/@img/sharp-linux-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz",
- "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz",
+ "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==",
"cpu": [
"arm64"
],
@@ -517,13 +775,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-arm64": "1.2.3"
+ "@img/sharp-libvips-linux-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-linux-ppc64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz",
- "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz",
+ "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==",
"cpu": [
"ppc64"
],
@@ -539,13 +797,35 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-ppc64": "1.2.3"
+ "@img/sharp-libvips-linux-ppc64": "1.2.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-riscv64": {
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz",
+ "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-riscv64": "1.2.4"
}
},
"node_modules/@img/sharp-linux-s390x": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz",
- "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz",
+ "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==",
"cpu": [
"s390x"
],
@@ -561,13 +841,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-s390x": "1.2.3"
+ "@img/sharp-libvips-linux-s390x": "1.2.4"
}
},
"node_modules/@img/sharp-linux-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz",
- "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz",
+ "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==",
"cpu": [
"x64"
],
@@ -583,13 +863,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linux-x64": "1.2.3"
+ "@img/sharp-libvips-linux-x64": "1.2.4"
}
},
"node_modules/@img/sharp-linuxmusl-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz",
- "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz",
+ "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==",
"cpu": [
"arm64"
],
@@ -605,13 +885,13 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.3"
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4"
}
},
"node_modules/@img/sharp-linuxmusl-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz",
- "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz",
+ "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==",
"cpu": [
"x64"
],
@@ -627,20 +907,20 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-libvips-linuxmusl-x64": "1.2.3"
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4"
}
},
"node_modules/@img/sharp-wasm32": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz",
- "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz",
+ "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==",
"cpu": [
"wasm32"
],
"license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
"optional": true,
"dependencies": {
- "@emnapi/runtime": "^1.5.0"
+ "@emnapi/runtime": "^1.7.0"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@@ -650,9 +930,9 @@
}
},
"node_modules/@img/sharp-win32-arm64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz",
- "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz",
+ "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==",
"cpu": [
"arm64"
],
@@ -669,9 +949,9 @@
}
},
"node_modules/@img/sharp-win32-ia32": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz",
- "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz",
+ "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==",
"cpu": [
"ia32"
],
@@ -688,9 +968,9 @@
}
},
"node_modules/@img/sharp-win32-x64": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz",
- "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz",
+ "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==",
"cpu": [
"x64"
],
@@ -706,19 +986,6 @@
"url": "https://opencollective.com/libvips"
}
},
- "node_modules/@isaacs/fs-minipass": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
- "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "minipass": "^7.0.4"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
@@ -783,15 +1050,15 @@
}
},
"node_modules/@next/env": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz",
- "integrity": "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.7.tgz",
+ "integrity": "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.4.tgz",
- "integrity": "sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.7.tgz",
+ "integrity": "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -799,9 +1066,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.4.tgz",
- "integrity": "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.7.tgz",
+ "integrity": "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==",
"cpu": [
"arm64"
],
@@ -815,9 +1082,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.4.tgz",
- "integrity": "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.7.tgz",
+ "integrity": "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==",
"cpu": [
"x64"
],
@@ -831,9 +1098,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.4.tgz",
- "integrity": "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.7.tgz",
+ "integrity": "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==",
"cpu": [
"arm64"
],
@@ -847,9 +1114,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.4.tgz",
- "integrity": "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.7.tgz",
+ "integrity": "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==",
"cpu": [
"arm64"
],
@@ -863,9 +1130,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.4.tgz",
- "integrity": "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.7.tgz",
+ "integrity": "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==",
"cpu": [
"x64"
],
@@ -879,9 +1146,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.4.tgz",
- "integrity": "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.7.tgz",
+ "integrity": "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==",
"cpu": [
"x64"
],
@@ -895,9 +1162,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.4.tgz",
- "integrity": "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.7.tgz",
+ "integrity": "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==",
"cpu": [
"arm64"
],
@@ -911,9 +1178,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.4.tgz",
- "integrity": "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.7.tgz",
+ "integrity": "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==",
"cpu": [
"x64"
],
@@ -990,9 +1257,9 @@
}
},
"node_modules/@radix-ui/react-context": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
- "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+ "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*",
@@ -1005,12 +1272,12 @@
}
},
"node_modules/@radix-ui/react-label": {
- "version": "2.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz",
- "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.8.tgz",
+ "integrity": "sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
+ "@radix-ui/react-primitive": "2.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1028,12 +1295,12 @@
}
},
"node_modules/@radix-ui/react-primitive": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
- "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+ "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-slot": "1.2.3"
+ "@radix-ui/react-slot": "1.2.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1051,13 +1318,13 @@
}
},
"node_modules/@radix-ui/react-progress": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz",
- "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==",
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.8.tgz",
+ "integrity": "sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3"
+ "@radix-ui/react-context": "1.1.3",
+ "@radix-ui/react-primitive": "2.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1075,12 +1342,12 @@
}
},
"node_modules/@radix-ui/react-separator": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz",
- "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==",
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+ "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
"license": "MIT",
"dependencies": {
- "@radix-ui/react-primitive": "2.1.3"
+ "@radix-ui/react-primitive": "2.1.4"
},
"peerDependencies": {
"@types/react": "*",
@@ -1098,9 +1365,9 @@
}
},
"node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
- "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+ "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
"license": "MIT",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.2"
@@ -1122,13 +1389,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@rushstack/eslint-patch": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.13.0.tgz",
- "integrity": "sha512-2ih5qGw5SZJ+2fLZxP6Lr6Na2NTIgPRL/7Kmyuw0uIyBQnuhQ8fi8fzUTd38eIQmqp+GYLC00cI6WgtqHxBwmw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1139,54 +1399,49 @@
}
},
"node_modules/@tailwindcss/node": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz",
- "integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz",
+ "integrity": "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
"enhanced-resolve": "^5.18.3",
- "jiti": "^2.6.0",
- "lightningcss": "1.30.1",
- "magic-string": "^0.30.19",
+ "jiti": "^2.6.1",
+ "lightningcss": "1.30.2",
+ "magic-string": "^0.30.21",
"source-map-js": "^1.2.1",
- "tailwindcss": "4.1.14"
+ "tailwindcss": "4.1.17"
}
},
"node_modules/@tailwindcss/oxide": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz",
- "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.17.tgz",
+ "integrity": "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==",
"dev": true,
- "hasInstallScript": true,
"license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.4",
- "tar": "^7.5.1"
- },
"engines": {
"node": ">= 10"
},
"optionalDependencies": {
- "@tailwindcss/oxide-android-arm64": "4.1.14",
- "@tailwindcss/oxide-darwin-arm64": "4.1.14",
- "@tailwindcss/oxide-darwin-x64": "4.1.14",
- "@tailwindcss/oxide-freebsd-x64": "4.1.14",
- "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14",
- "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14",
- "@tailwindcss/oxide-linux-arm64-musl": "4.1.14",
- "@tailwindcss/oxide-linux-x64-gnu": "4.1.14",
- "@tailwindcss/oxide-linux-x64-musl": "4.1.14",
- "@tailwindcss/oxide-wasm32-wasi": "4.1.14",
- "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14",
- "@tailwindcss/oxide-win32-x64-msvc": "4.1.14"
+ "@tailwindcss/oxide-android-arm64": "4.1.17",
+ "@tailwindcss/oxide-darwin-arm64": "4.1.17",
+ "@tailwindcss/oxide-darwin-x64": "4.1.17",
+ "@tailwindcss/oxide-freebsd-x64": "4.1.17",
+ "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17",
+ "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17",
+ "@tailwindcss/oxide-linux-arm64-musl": "4.1.17",
+ "@tailwindcss/oxide-linux-x64-gnu": "4.1.17",
+ "@tailwindcss/oxide-linux-x64-musl": "4.1.17",
+ "@tailwindcss/oxide-wasm32-wasi": "4.1.17",
+ "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17",
+ "@tailwindcss/oxide-win32-x64-msvc": "4.1.17"
}
},
"node_modules/@tailwindcss/oxide-android-arm64": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz",
- "integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.17.tgz",
+ "integrity": "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==",
"cpu": [
"arm64"
],
@@ -1201,9 +1456,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-arm64": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz",
- "integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.17.tgz",
+ "integrity": "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==",
"cpu": [
"arm64"
],
@@ -1218,9 +1473,9 @@
}
},
"node_modules/@tailwindcss/oxide-darwin-x64": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz",
- "integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.17.tgz",
+ "integrity": "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==",
"cpu": [
"x64"
],
@@ -1235,9 +1490,9 @@
}
},
"node_modules/@tailwindcss/oxide-freebsd-x64": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz",
- "integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.17.tgz",
+ "integrity": "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==",
"cpu": [
"x64"
],
@@ -1252,9 +1507,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz",
- "integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.17.tgz",
+ "integrity": "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==",
"cpu": [
"arm"
],
@@ -1269,9 +1524,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz",
- "integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.17.tgz",
+ "integrity": "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==",
"cpu": [
"arm64"
],
@@ -1286,9 +1541,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-arm64-musl": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz",
- "integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.17.tgz",
+ "integrity": "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==",
"cpu": [
"arm64"
],
@@ -1303,9 +1558,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-gnu": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz",
- "integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.17.tgz",
+ "integrity": "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==",
"cpu": [
"x64"
],
@@ -1320,9 +1575,9 @@
}
},
"node_modules/@tailwindcss/oxide-linux-x64-musl": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz",
- "integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.17.tgz",
+ "integrity": "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==",
"cpu": [
"x64"
],
@@ -1337,9 +1592,9 @@
}
},
"node_modules/@tailwindcss/oxide-wasm32-wasi": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz",
- "integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.17.tgz",
+ "integrity": "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==",
"bundleDependencies": [
"@napi-rs/wasm-runtime",
"@emnapi/core",
@@ -1355,10 +1610,10 @@
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/core": "^1.5.0",
- "@emnapi/runtime": "^1.5.0",
+ "@emnapi/core": "^1.6.0",
+ "@emnapi/runtime": "^1.6.0",
"@emnapi/wasi-threads": "^1.1.0",
- "@napi-rs/wasm-runtime": "^1.0.5",
+ "@napi-rs/wasm-runtime": "^1.0.7",
"@tybys/wasm-util": "^0.10.1",
"tslib": "^2.4.0"
},
@@ -1367,9 +1622,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz",
- "integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz",
+ "integrity": "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==",
"cpu": [
"arm64"
],
@@ -1384,9 +1639,9 @@
}
},
"node_modules/@tailwindcss/oxide-win32-x64-msvc": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz",
- "integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.17.tgz",
+ "integrity": "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==",
"cpu": [
"x64"
],
@@ -1401,17 +1656,17 @@
}
},
"node_modules/@tailwindcss/postcss": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.14.tgz",
- "integrity": "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.17.tgz",
+ "integrity": "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@alloc/quick-lru": "^5.2.0",
- "@tailwindcss/node": "4.1.14",
- "@tailwindcss/oxide": "4.1.14",
+ "@tailwindcss/node": "4.1.17",
+ "@tailwindcss/oxide": "4.1.17",
"postcss": "^8.4.41",
- "tailwindcss": "4.1.14"
+ "tailwindcss": "4.1.17"
}
},
"node_modules/@tybys/wasm-util": {
@@ -1425,6 +1680,16 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@types/better-sqlite3": {
+ "version": "7.6.13",
+ "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz",
+ "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/cheerio": {
"version": "0.22.35",
"resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.35.tgz",
@@ -1456,28 +1721,28 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "20.19.19",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.19.tgz",
- "integrity": "sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg==",
+ "version": "20.19.25",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz",
+ "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/react": {
- "version": "19.2.2",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz",
- "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==",
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz",
+ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
- "csstype": "^3.0.2"
+ "csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
- "version": "19.2.1",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.1.tgz",
- "integrity": "sha512-/EEvYBdT3BflCWvTMO7YkYBHVE9Ci6XdqZciZANQgKpaiDRGOLIlRo91jbTNRQjgPFWVaRxcYc0luVNFitz57A==",
+ "version": "19.2.3",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"devOptional": true,
"license": "MIT",
"peerDependencies": {
@@ -1485,17 +1750,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
- "integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz",
+ "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/type-utils": "8.46.0",
- "@typescript-eslint/utils": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/type-utils": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
@@ -1509,7 +1774,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.46.0",
+ "@typescript-eslint/parser": "^8.48.1",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
@@ -1525,16 +1790,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
- "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz",
+ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1550,14 +1815,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
- "integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz",
+ "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.46.0",
- "@typescript-eslint/types": "^8.46.0",
+ "@typescript-eslint/tsconfig-utils": "^8.48.1",
+ "@typescript-eslint/types": "^8.48.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1572,14 +1837,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
- "integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz",
+ "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0"
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1590,9 +1855,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
- "integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz",
+ "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1607,15 +1872,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
- "integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz",
+ "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0",
- "@typescript-eslint/utils": "8.46.0",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@@ -1632,9 +1897,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
- "integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
+ "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1646,21 +1911,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
- "integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz",
+ "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.46.0",
- "@typescript-eslint/tsconfig-utils": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/project-service": "8.48.1",
+ "@typescript-eslint/tsconfig-utils": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4",
- "fast-glob": "^3.3.2",
- "is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
+ "tinyglobby": "^0.2.15",
"ts-api-utils": "^2.1.0"
},
"engines": {
@@ -1684,36 +1948,6 @@
"balanced-match": "^1.0.0"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -1730,17 +1964,30 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@typescript-eslint/utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
- "integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz",
+ "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0"
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1755,13 +2002,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
- "integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz",
+ "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/types": "8.48.1",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -2314,9 +2561,9 @@
}
},
"node_modules/axe-core": {
- "version": "4.10.3",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz",
- "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==",
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz",
+ "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==",
"dev": true,
"license": "MPL-2.0",
"engines": {
@@ -2324,9 +2571,9 @@
}
},
"node_modules/axios": {
- "version": "1.12.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz",
- "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -2351,25 +2598,86 @@
"dev": true,
"license": "MIT"
},
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "license": "ISC"
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
},
- "node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.4",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz",
+ "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==",
"dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
+ "node_modules/better-sqlite3": {
+ "version": "11.10.0",
+ "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.10.0.tgz",
+ "integrity": "sha512-EwhOpyXiOEL/lKzHz9AW1msWFNzGc/z+LzeB3/jnFJpxu+th2yqvzsSWas1v9jgs9+xiXJcD5A8CJxAG2TaghQ==",
+ "hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "bindings": "^1.5.0",
+ "prebuild-install": "^7.1.1"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
@@ -2381,6 +2689,64 @@
"node": ">=8"
}
},
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -2441,9 +2807,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001749",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz",
- "integrity": "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==",
+ "version": "1.0.30001759",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz",
+ "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==",
"funding": [
{
"type": "opencollective",
@@ -2478,25 +2844,25 @@
}
},
"node_modules/cheerio": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.0.tgz",
- "integrity": "sha512-+0hMx9eYhJvWbgpKV9hN7jg0JcwydpopZE4hgi+KvQtByZXPp04NiCWU0LzcAbP63abZckIHkTQaXVF52mX3xQ==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
+ "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
"license": "MIT",
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.2.2",
- "encoding-sniffer": "^0.2.0",
+ "encoding-sniffer": "^0.2.1",
"htmlparser2": "^10.0.0",
"parse5": "^7.3.0",
"parse5-htmlparser2-tree-adapter": "^7.1.0",
"parse5-parser-stream": "^7.1.2",
- "undici": "^7.10.0",
+ "undici": "^7.12.0",
"whatwg-mimetype": "^4.0.0"
},
"engines": {
- "node": ">=18.17"
+ "node": ">=20.18.1"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
@@ -2520,14 +2886,10 @@
}
},
"node_modules/chownr": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
- "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
},
"node_modules/class-variance-authority": {
"version": "0.7.1",
@@ -2595,6 +2957,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2639,9 +3008,9 @@
}
},
"node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"devOptional": true,
"license": "MIT"
},
@@ -2724,6 +3093,30 @@
}
}
},
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -2780,7 +3173,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "devOptional": true,
"license": "Apache-2.0",
"engines": {
"node": ">=8"
@@ -2868,6 +3260,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.266",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz",
+ "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -2888,6 +3287,15 @@
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
}
},
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
"node_modules/enhanced-resolve": {
"version": "5.18.3",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
@@ -3087,6 +3495,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3101,25 +3519,24 @@
}
},
"node_modules/eslint": {
- "version": "9.37.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz",
- "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==",
+ "version": "9.39.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
+ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.0",
- "@eslint/config-helpers": "^0.4.0",
- "@eslint/core": "^0.16.0",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
"@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.37.0",
- "@eslint/plugin-kit": "^0.4.0",
+ "@eslint/js": "9.39.1",
+ "@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
- "@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
@@ -3162,25 +3579,24 @@
}
},
"node_modules/eslint-config-next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.4.tgz",
- "integrity": "sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.7.tgz",
+ "integrity": "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "15.5.4",
- "@rushstack/eslint-patch": "^1.10.3",
- "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
- "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@next/eslint-plugin-next": "16.0.7",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.37.0",
- "eslint-plugin-react-hooks": "^5.0.0"
+ "eslint-plugin-react-hooks": "^7.0.0",
+ "globals": "16.4.0",
+ "typescript-eslint": "^8.46.0"
},
"peerDependencies": {
- "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0",
+ "eslint": ">=9.0.0",
"typescript": ">=3.3.1"
},
"peerDependenciesMeta": {
@@ -3189,6 +3605,19 @@
}
}
},
+ "node_modules/eslint-config-next/node_modules/globals": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
+ "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -3318,16 +3747,6 @@
"ms": "^2.1.1"
}
},
- "node_modules/eslint-plugin-import/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/eslint-plugin-jsx-a11y": {
"version": "6.10.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
@@ -3392,13 +3811,20 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
- "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"peerDependencies": {
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
@@ -3422,16 +3848,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/eslint-plugin-react/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/eslint-scope": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
@@ -3526,6 +3942,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -3600,6 +4025,12 @@
"node": ">=16.0.0"
}
},
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -3688,9 +4119,9 @@
}
},
"node_modules/form-data": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
- "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
@@ -3703,6 +4134,12 @@
"node": ">= 6"
}
},
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -3753,6 +4190,16 @@
"node": ">= 0.4"
}
},
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -3809,9 +4256,9 @@
}
},
"node_modules/get-tsconfig": {
- "version": "4.11.0",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.11.0.tgz",
- "integrity": "sha512-sNsqf7XKQ38IawiVGPOoAlqZo1DMrO7TU+ZcZwi7yLl7/7S0JwmoBMKz/IkUPhSoXM0Ng3vT0yB1iCe5XavDeQ==",
+ "version": "4.13.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
+ "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3821,6 +4268,12 @@
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
"node_modules/glob-parent": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
@@ -3981,6 +4434,23 @@
"node": ">= 0.4"
}
},
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
"node_modules/htmlparser2": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
@@ -4024,6 +4494,26 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -4061,6 +4551,18 @@
"node": ">=0.8.19"
}
},
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
"node_modules/internal-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -4157,6 +4659,19 @@
"semver": "^7.7.1"
}
},
+ "node_modules/is-bun-module/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
@@ -4528,9 +5043,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4540,6 +5055,19 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -4562,16 +5090,16 @@
"license": "MIT"
},
"node_modules/json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "minimist": "^1.2.0"
- },
"bin": {
"json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
}
},
"node_modules/jsx-ast-utils": {
@@ -4635,9 +5163,9 @@
}
},
"node_modules/lightningcss": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz",
- "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz",
+ "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
@@ -4651,22 +5179,44 @@
"url": "https://opencollective.com/parcel"
},
"optionalDependencies": {
- "lightningcss-darwin-arm64": "1.30.1",
- "lightningcss-darwin-x64": "1.30.1",
- "lightningcss-freebsd-x64": "1.30.1",
- "lightningcss-linux-arm-gnueabihf": "1.30.1",
- "lightningcss-linux-arm64-gnu": "1.30.1",
- "lightningcss-linux-arm64-musl": "1.30.1",
- "lightningcss-linux-x64-gnu": "1.30.1",
- "lightningcss-linux-x64-musl": "1.30.1",
- "lightningcss-win32-arm64-msvc": "1.30.1",
- "lightningcss-win32-x64-msvc": "1.30.1"
+ "lightningcss-android-arm64": "1.30.2",
+ "lightningcss-darwin-arm64": "1.30.2",
+ "lightningcss-darwin-x64": "1.30.2",
+ "lightningcss-freebsd-x64": "1.30.2",
+ "lightningcss-linux-arm-gnueabihf": "1.30.2",
+ "lightningcss-linux-arm64-gnu": "1.30.2",
+ "lightningcss-linux-arm64-musl": "1.30.2",
+ "lightningcss-linux-x64-gnu": "1.30.2",
+ "lightningcss-linux-x64-musl": "1.30.2",
+ "lightningcss-win32-arm64-msvc": "1.30.2",
+ "lightningcss-win32-x64-msvc": "1.30.2"
+ }
+ },
+ "node_modules/lightningcss-android-arm64": {
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz",
+ "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MPL-2.0",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
"node_modules/lightningcss-darwin-arm64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz",
- "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz",
+ "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==",
"cpu": [
"arm64"
],
@@ -4685,9 +5235,9 @@
}
},
"node_modules/lightningcss-darwin-x64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz",
- "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz",
+ "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==",
"cpu": [
"x64"
],
@@ -4706,9 +5256,9 @@
}
},
"node_modules/lightningcss-freebsd-x64": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz",
- "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz",
+ "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==",
"cpu": [
"x64"
],
@@ -4727,9 +5277,9 @@
}
},
"node_modules/lightningcss-linux-arm-gnueabihf": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz",
- "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz",
+ "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==",
"cpu": [
"arm"
],
@@ -4748,9 +5298,9 @@
}
},
"node_modules/lightningcss-linux-arm64-gnu": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz",
- "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz",
+ "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==",
"cpu": [
"arm64"
],
@@ -4769,9 +5319,9 @@
}
},
"node_modules/lightningcss-linux-arm64-musl": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz",
- "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz",
+ "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==",
"cpu": [
"arm64"
],
@@ -4790,9 +5340,9 @@
}
},
"node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz",
- "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz",
+ "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==",
"cpu": [
"x64"
],
@@ -4811,9 +5361,9 @@
}
},
"node_modules/lightningcss-linux-x64-musl": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz",
- "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz",
+ "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==",
"cpu": [
"x64"
],
@@ -4832,9 +5382,9 @@
}
},
"node_modules/lightningcss-win32-arm64-msvc": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz",
- "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz",
+ "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==",
"cpu": [
"arm64"
],
@@ -4853,9 +5403,9 @@
}
},
"node_modules/lightningcss-win32-x64-msvc": {
- "version": "1.30.1",
- "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz",
- "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==",
+ "version": "1.30.2",
+ "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz",
+ "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==",
"cpu": [
"x64"
],
@@ -4909,6 +5459,16 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
"node_modules/lucide-react": {
"version": "0.545.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.545.0.tgz",
@@ -4919,9 +5479,9 @@
}
},
"node_modules/magic-string": {
- "version": "0.30.19",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
- "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4982,6 +5542,18 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -4999,34 +5571,16 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/minizlib": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
- "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": ">= 18"
- }
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
@@ -5053,6 +5607,12 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
+ "node_modules/napi-build-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
+ "license": "MIT"
+ },
"node_modules/napi-postinstall": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz",
@@ -5077,12 +5637,12 @@
"license": "MIT"
},
"node_modules/next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz",
- "integrity": "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.0.7.tgz",
+ "integrity": "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==",
"license": "MIT",
"dependencies": {
- "@next/env": "15.5.4",
+ "@next/env": "16.0.7",
"@swc/helpers": "0.5.15",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
@@ -5092,18 +5652,18 @@
"next": "dist/bin/next"
},
"engines": {
- "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ "node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "15.5.4",
- "@next/swc-darwin-x64": "15.5.4",
- "@next/swc-linux-arm64-gnu": "15.5.4",
- "@next/swc-linux-arm64-musl": "15.5.4",
- "@next/swc-linux-x64-gnu": "15.5.4",
- "@next/swc-linux-x64-musl": "15.5.4",
- "@next/swc-win32-arm64-msvc": "15.5.4",
- "@next/swc-win32-x64-msvc": "15.5.4",
- "sharp": "^0.34.3"
+ "@next/swc-darwin-arm64": "16.0.7",
+ "@next/swc-darwin-x64": "16.0.7",
+ "@next/swc-linux-arm64-gnu": "16.0.7",
+ "@next/swc-linux-arm64-musl": "16.0.7",
+ "@next/swc-linux-x64-gnu": "16.0.7",
+ "@next/swc-linux-x64-musl": "16.0.7",
+ "@next/swc-win32-arm64-msvc": "16.0.7",
+ "@next/swc-win32-x64-msvc": "16.0.7",
+ "sharp": "^0.34.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -5156,6 +5716,37 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/node-abi": {
+ "version": "3.85.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz",
+ "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-abi/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -5291,6 +5882,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -5506,6 +6106,32 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/prebuild-install": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+ "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^2.0.0",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -5534,6 +6160,16 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"license": "MIT"
},
+ "node_modules/pump": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
+ "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -5565,6 +6201,30 @@
],
"license": "MIT"
},
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/react": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
@@ -5593,6 +6253,20 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -5638,13 +6312,13 @@
}
},
"node_modules/resolve": {
- "version": "1.22.10",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
- "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
+ "version": "1.22.11",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+ "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "is-core-module": "^2.16.0",
+ "is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -5733,6 +6407,26 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/safe-push-apply": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@@ -5781,16 +6475,13 @@
"license": "MIT"
},
"node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
- "devOptional": true,
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
}
},
"node_modules/set-function-length": {
@@ -5843,16 +6534,16 @@
}
},
"node_modules/sharp": {
- "version": "0.34.4",
- "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz",
- "integrity": "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==",
+ "version": "0.34.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz",
+ "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==",
"hasInstallScript": true,
"license": "Apache-2.0",
"optional": true,
"dependencies": {
"@img/colour": "^1.0.0",
- "detect-libc": "^2.1.0",
- "semver": "^7.7.2"
+ "detect-libc": "^2.1.2",
+ "semver": "^7.7.3"
},
"engines": {
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@@ -5861,28 +6552,43 @@
"url": "https://opencollective.com/libvips"
},
"optionalDependencies": {
- "@img/sharp-darwin-arm64": "0.34.4",
- "@img/sharp-darwin-x64": "0.34.4",
- "@img/sharp-libvips-darwin-arm64": "1.2.3",
- "@img/sharp-libvips-darwin-x64": "1.2.3",
- "@img/sharp-libvips-linux-arm": "1.2.3",
- "@img/sharp-libvips-linux-arm64": "1.2.3",
- "@img/sharp-libvips-linux-ppc64": "1.2.3",
- "@img/sharp-libvips-linux-s390x": "1.2.3",
- "@img/sharp-libvips-linux-x64": "1.2.3",
- "@img/sharp-libvips-linuxmusl-arm64": "1.2.3",
- "@img/sharp-libvips-linuxmusl-x64": "1.2.3",
- "@img/sharp-linux-arm": "0.34.4",
- "@img/sharp-linux-arm64": "0.34.4",
- "@img/sharp-linux-ppc64": "0.34.4",
- "@img/sharp-linux-s390x": "0.34.4",
- "@img/sharp-linux-x64": "0.34.4",
- "@img/sharp-linuxmusl-arm64": "0.34.4",
- "@img/sharp-linuxmusl-x64": "0.34.4",
- "@img/sharp-wasm32": "0.34.4",
- "@img/sharp-win32-arm64": "0.34.4",
- "@img/sharp-win32-ia32": "0.34.4",
- "@img/sharp-win32-x64": "0.34.4"
+ "@img/sharp-darwin-arm64": "0.34.5",
+ "@img/sharp-darwin-x64": "0.34.5",
+ "@img/sharp-libvips-darwin-arm64": "1.2.4",
+ "@img/sharp-libvips-darwin-x64": "1.2.4",
+ "@img/sharp-libvips-linux-arm": "1.2.4",
+ "@img/sharp-libvips-linux-arm64": "1.2.4",
+ "@img/sharp-libvips-linux-ppc64": "1.2.4",
+ "@img/sharp-libvips-linux-riscv64": "1.2.4",
+ "@img/sharp-libvips-linux-s390x": "1.2.4",
+ "@img/sharp-libvips-linux-x64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.2.4",
+ "@img/sharp-linux-arm": "0.34.5",
+ "@img/sharp-linux-arm64": "0.34.5",
+ "@img/sharp-linux-ppc64": "0.34.5",
+ "@img/sharp-linux-riscv64": "0.34.5",
+ "@img/sharp-linux-s390x": "0.34.5",
+ "@img/sharp-linux-x64": "0.34.5",
+ "@img/sharp-linuxmusl-arm64": "0.34.5",
+ "@img/sharp-linuxmusl-x64": "0.34.5",
+ "@img/sharp-wasm32": "0.34.5",
+ "@img/sharp-win32-arm64": "0.34.5",
+ "@img/sharp-win32-ia32": "0.34.5",
+ "@img/sharp-win32-x64": "0.34.5"
+ }
+ },
+ "node_modules/sharp/node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/shebang-command": {
@@ -5984,6 +6690,51 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -6014,6 +6765,15 @@
"node": ">= 0.4"
}
},
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
"node_modules/string.prototype.includes": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
@@ -6200,9 +6960,9 @@
}
},
"node_modules/tailwind-merge": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
- "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
+ "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==",
"license": "MIT",
"funding": {
"type": "github",
@@ -6210,9 +6970,9 @@
}
},
"node_modules/tailwindcss": {
- "version": "4.1.14",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz",
- "integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==",
+ "version": "4.1.17",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz",
+ "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==",
"dev": true,
"license": "MIT"
},
@@ -6230,21 +6990,32 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/tar": {
- "version": "7.5.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.1.tgz",
- "integrity": "sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g==",
- "dev": true,
- "license": "ISC",
+ "node_modules/tar-fs": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
+ "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
"dependencies": {
- "@isaacs/fs-minipass": "^4.0.0",
- "chownr": "^3.0.0",
- "minipass": "^7.1.2",
- "minizlib": "^3.1.0",
- "yallist": "^5.0.0"
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
},
"engines": {
- "node": ">=18"
+ "node": ">=6"
}
},
"node_modules/tinyglobby": {
@@ -6334,12 +7105,37 @@
"strip-bom": "^3.0.0"
}
},
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/tw-animate-css": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.4.0.tgz",
@@ -6455,6 +7251,30 @@
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz",
+ "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.48.1",
+ "@typescript-eslint/parser": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@@ -6524,6 +7344,37 @@
"@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz",
+ "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -6534,6 +7385,12 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
"node_modules/whatwg-encoding": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
@@ -6670,15 +7527,18 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
"node_modules/yallist": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
- "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true,
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=18"
- }
+ "license": "ISC"
},
"node_modules/yocto-queue": {
"version": "0.1.0",
@@ -6692,6 +7552,29 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "4.1.13",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz",
+ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
}
}
}
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package.json b/apps/Cortensor-Price-Analyzer/package.json
similarity index 88%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package.json
rename to apps/Cortensor-Price-Analyzer/package.json
index 89c7417..941e396 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/package.json
+++ b/apps/Cortensor-Price-Analyzer/package.json
@@ -15,23 +15,25 @@
"@radix-ui/react-slot": "^1.2.3",
"@types/cheerio": "^0.22.35",
"axios": "^1.12.2",
+ "better-sqlite3": "^11.8.1",
"cheerio": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.545.0",
- "next": "15.5.4",
+ "next": "16.0.7",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
+ "@types/better-sqlite3": "^7",
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
- "eslint-config-next": "15.5.4",
+ "eslint-config-next": "16.0.7",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
"typescript": "^5"
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/postcss.config.mjs b/apps/Cortensor-Price-Analyzer/postcss.config.mjs
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/postcss.config.mjs
rename to apps/Cortensor-Price-Analyzer/postcss.config.mjs
diff --git a/apps/Cortensor-Price-Analyzer/public/file.svg b/apps/Cortensor-Price-Analyzer/public/file.svg
new file mode 100644
index 0000000..004145c
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/public/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/public/globe.svg b/apps/Cortensor-Price-Analyzer/public/globe.svg
new file mode 100644
index 0000000..567f17b
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/public/globe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/public/next.svg b/apps/Cortensor-Price-Analyzer/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/public/vercel.svg b/apps/Cortensor-Price-Analyzer/public/vercel.svg
new file mode 100644
index 0000000..7705396
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/public/window.svg b/apps/Cortensor-Price-Analyzer/public/window.svg
new file mode 100644
index 0000000..b2b2a44
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/public/window.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/solrc b/apps/Cortensor-Price-Analyzer/solrc
new file mode 100644
index 0000000..0b571c3
Binary files /dev/null and b/apps/Cortensor-Price-Analyzer/solrc differ
diff --git a/apps/Cortensor-Price-Analyzer/src/app/api/market-tickers/route.ts b/apps/Cortensor-Price-Analyzer/src/app/api/market-tickers/route.ts
new file mode 100644
index 0000000..f961d16
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/src/app/api/market-tickers/route.ts
@@ -0,0 +1,1163 @@
+import { snapshotStore } from '@/lib/snapshotStore';
+import axios from 'axios';
+import { NextResponse } from 'next/server';
+
+export type AssetKind = 'equity' | 'crypto' | 'forex' | 'commodity';
+export type QuoteProvider = 'coingecko' | 'stooq' | 'twelvedata' | 'alphavantage' | 'marketstack' | 'massive';
+
+type WatchItem = {
+ symbol: string;
+ name: string;
+ type: AssetKind;
+ currency?: string;
+ providers?: Partial>;
+};
+
+export type MarketTickerItem = WatchItem & {
+ price?: number;
+ changePercent?: number;
+};
+
+type ProviderResult = {
+ items: MarketTickerItem[];
+ refreshedAt: string | null;
+};
+
+const EQUITY_WATCHLIST: WatchItem[] = [
+ { symbol: 'NVDA', name: 'NVIDIA', type: 'equity', providers: { stooq: 'nvda.us', twelvedata: 'NVDA', massive: 'NVDA' } },
+ { symbol: 'AAPL', name: 'Apple', type: 'equity', providers: { stooq: 'aapl.us', twelvedata: 'AAPL', massive: 'AAPL' } },
+ { symbol: 'MSFT', name: 'Microsoft', type: 'equity', providers: { stooq: 'msft.us', twelvedata: 'MSFT', massive: 'MSFT' } },
+ { symbol: 'TSLA', name: 'Tesla', type: 'equity', providers: { stooq: 'tsla.us', twelvedata: 'TSLA', massive: 'TSLA' } },
+ { symbol: 'META', name: 'Meta Platforms', type: 'equity', providers: { stooq: 'meta.us', twelvedata: 'META', massive: 'META' } },
+ { symbol: 'AMZN', name: 'Amazon', type: 'equity', providers: { stooq: 'amzn.us', twelvedata: 'AMZN', massive: 'AMZN' } },
+];
+
+const CRYPTO_WATCHLIST: WatchItem[] = [
+ { symbol: 'BTCUSD', name: 'Bitcoin', type: 'crypto', providers: { coingecko: 'bitcoin', twelvedata: 'BTC/USD' } },
+ { symbol: 'ETHUSD', name: 'Ethereum', type: 'crypto', providers: { coingecko: 'ethereum', twelvedata: 'ETH/USD' } },
+ { symbol: 'SOLUSD', name: 'Solana', type: 'crypto', providers: { coingecko: 'solana', twelvedata: 'SOL/USD' } },
+ { symbol: 'XRPUSD', name: 'XRP', type: 'crypto', providers: { coingecko: 'ripple', twelvedata: 'XRP/USD' } },
+ { symbol: 'DOGEUSD', name: 'Dogecoin', type: 'crypto', providers: { coingecko: 'dogecoin', twelvedata: 'DOGE/USD' } },
+];
+
+const FOREX_WATCHLIST: WatchItem[] = [
+ { symbol: 'EURUSD', name: 'Euro / US Dollar', type: 'forex', providers: { alphavantage: 'EURUSD', twelvedata: 'EUR/USD' } },
+ { symbol: 'USDJPY', name: 'US Dollar / Japanese Yen', type: 'forex', providers: { alphavantage: 'USDJPY', twelvedata: 'USD/JPY' } },
+ { symbol: 'GBPUSD', name: 'British Pound / US Dollar', type: 'forex', providers: { alphavantage: 'GBPUSD', twelvedata: 'GBP/USD' } },
+ { symbol: 'AUDUSD', name: 'Australian Dollar / US Dollar', type: 'forex', providers: { alphavantage: 'AUDUSD', twelvedata: 'AUD/USD' } },
+ { symbol: 'USDCAD', name: 'US Dollar / Canadian Dollar', type: 'forex', providers: { alphavantage: 'USDCAD', twelvedata: 'USD/CAD' } },
+];
+
+const COMMODITY_WATCHLIST: WatchItem[] = [
+ {
+ symbol: 'XAUUSD',
+ name: 'Gold',
+ type: 'commodity',
+ providers: {
+ alphavantage: 'XAUUSD',
+ massive: 'product:GC',
+ marketstack: 'XAUUSD',
+ stooq: 'xauusd',
+ twelvedata: 'XAU/USD',
+ },
+ },
+ {
+ symbol: 'XAGUSD',
+ name: 'Silver',
+ type: 'commodity',
+ providers: {
+ alphavantage: 'XAGUSD',
+ massive: 'product:SI',
+ marketstack: 'XAGUSD',
+ stooq: 'xagusd',
+ twelvedata: 'XAG/USD',
+ },
+ },
+ {
+ symbol: 'WTIUSD',
+ name: 'Crude Oil WTI',
+ type: 'commodity',
+ providers: {
+ alphavantage: 'WTI',
+ massive: 'product:CL',
+ marketstack: 'WTIUSD',
+ stooq: 'cl.f',
+ twelvedata: 'WTI/USD',
+ },
+ },
+ {
+ symbol: 'BRENTUSD',
+ name: 'Crude Oil Brent',
+ type: 'commodity',
+ providers: {
+ alphavantage: 'BRENT',
+ stooq: 'brn.f',
+ },
+ },
+ {
+ symbol: 'NGUSD',
+ name: 'Natural Gas',
+ type: 'commodity',
+ providers: {
+ alphavantage: 'NATURAL_GAS',
+ massive: 'product:NG',
+ marketstack: 'NGUSD',
+ stooq: 'ng.f',
+ twelvedata: 'NG/USD',
+ },
+ },
+];
+
+const TWELVEDATA_BASE_URL = 'https://api.twelvedata.com';
+const STOOQ_QUOTE_URL = 'https://stooq.com/q/l/';
+const ALPHA_VANTAGE_BASE_URL = 'https://www.alphavantage.co/query';
+const MARKETSTACK_BASE_URL = 'https://api.marketstack.com/v1';
+const MASSIVE_BASE_URL = 'https://api.massive.com';
+const COINGECKO_BASE_URL = 'https://api.coingecko.com/api/v3';
+
+const twelvedataKey = process.env.TWELVEDATA_API_KEY;
+const twelvedataCommodityKey = process.env.TWELVEDATA_COMMODITY_API_KEY ?? null;
+const twelvedataStocksKey = process.env.TWELVEDATA_STOCKS_API_KEY ?? null;
+const alphaVantagePrimaryKey = process.env.ALPHA_VANTAGE_API_KEY;
+const alphaVantageForexKey = process.env.ALPHA_VANTAGE_FOREX_API_KEY ?? alphaVantagePrimaryKey;
+const alphaVantageCommodityKey = alphaVantagePrimaryKey ?? alphaVantageForexKey;
+const alphaVantageRetryKey = process.env.ALPHA_VANTAGE_RETRY_API_KEY ?? 'BWAHOQOJKEV0ER1A';
+const marketstackKey = process.env.MARKETSTACK_API_KEY;
+const massiveKey = process.env.MASSIVE_API_KEY;
+const coingeckoKey = process.env.COINGECKO_API_KEY;
+
+type AlphaMacroCommodityFunction = 'WTI' | 'BRENT' | 'NATURAL_GAS';
+
+type AlphaCommoditySpec =
+ | { mode: 'dailySeries'; symbol: string }
+ | { mode: 'macroSeries'; function: AlphaMacroCommodityFunction; interval: 'daily' | 'weekly' | 'monthly' };
+
+const ALPHA_COMMODITY_SPECS: Record = {
+ XAUUSD: { mode: 'dailySeries', symbol: 'XAUUSD' },
+ XAGUSD: { mode: 'dailySeries', symbol: 'XAGUSD' },
+ WTIUSD: { mode: 'macroSeries', function: 'WTI', interval: 'daily' },
+ BRENTUSD: { mode: 'macroSeries', function: 'BRENT', interval: 'daily' },
+ NGUSD: { mode: 'macroSeries', function: 'NATURAL_GAS', interval: 'daily' },
+};
+
+export type WatchlistKey = 'equities' | 'crypto' | 'forex' | 'commodities';
+
+type CategorySpec = {
+ items: WatchItem[];
+ providers: QuoteProvider[];
+ ttlMs: number;
+ requireComplete?: boolean;
+};
+
+const CATEGORY_SPECS: Record = {
+ equities: { items: EQUITY_WATCHLIST, providers: ['twelvedata', 'stooq'], ttlMs: 5 * 60 * 1000 },
+ crypto: { items: CRYPTO_WATCHLIST, providers: ['coingecko', 'twelvedata'], ttlMs: 10 * 60 * 1000 },
+ forex: { items: FOREX_WATCHLIST, providers: ['alphavantage', 'twelvedata'], ttlMs: 60 * 60 * 1000 },
+ commodities: {
+ items: COMMODITY_WATCHLIST,
+ providers: ['alphavantage', 'twelvedata', 'stooq', 'marketstack', 'massive'],
+ ttlMs: 15 * 60 * 1000,
+ requireComplete: true,
+ },
+};
+
+export type CategorySnapshot = {
+ items: MarketTickerItem[];
+ provider: QuoteProvider;
+ refreshedAt: string | null;
+ errors: string[];
+};
+
+export type CategoryMeta = {
+ provider: QuoteProvider;
+ ttlSeconds: number;
+ lastUpdated: string | null;
+ errors: string[];
+};
+
+const categoryCache: Partial> = {};
+
+export async function GET() {
+ const keys = Object.keys(CATEGORY_SPECS) as WatchlistKey[];
+ const snapshots = await Promise.all(keys.map((key) => getCategorySnapshot(key)));
+
+ const data = keys.reduce(
+ (acc, key, index) => {
+ acc[key] = snapshots[index].items;
+ return acc;
+ },
+ {} as Record
+ );
+
+ const refreshedAt = getLatestTimestamp(snapshots.map((snapshot) => snapshot.refreshedAt));
+
+ const metaCategories = keys.reduce(
+ (acc, key, index) => {
+ const spec = CATEGORY_SPECS[key];
+ acc[key] = {
+ provider: snapshots[index].provider,
+ ttlSeconds: spec.ttlMs / 1000,
+ lastUpdated: snapshots[index].refreshedAt,
+ errors: snapshots[index].errors,
+ } satisfies CategoryMeta;
+ return acc;
+ },
+ {} as Record
+ );
+
+ return NextResponse.json({
+ data: {
+ ...data,
+ refreshedAt,
+ },
+ meta: {
+ categories: metaCategories,
+ },
+ });
+}
+
+async function getCategorySnapshot(key: WatchlistKey): Promise {
+ const spec = CATEGORY_SPECS[key];
+ const cacheEntry = categoryCache[key];
+ if (cacheEntry && Date.now() - cacheEntry.timestamp < spec.ttlMs) {
+ return cacheEntry.snapshot;
+ }
+
+ const persisted = snapshotStore.getSnapshotWithinTtl(key, spec.ttlMs);
+ if (persisted && matchesWatchlist(persisted.items, spec.items)) {
+ const snapshot: CategorySnapshot = {
+ items: persisted.items,
+ provider: persisted.provider,
+ refreshedAt: persisted.refreshedAt,
+ errors: [],
+ };
+ categoryCache[key] = { timestamp: Date.now(), snapshot };
+ return snapshot;
+ }
+ if (persisted && !matchesWatchlist(persisted.items, spec.items)) {
+ console.info(`Ignoring snapshot for ${key} because watchlist changed.`);
+ }
+
+ const attemptErrors: string[] = [];
+
+ for (const provider of spec.providers) {
+ try {
+ const result = await fetchByProvider(provider, spec.items, key);
+ if (!hasLiveQuotes(result.items, spec.requireComplete ?? false)) {
+ attemptErrors.push(`${provider}:no-prices`);
+ continue;
+ }
+ const snapshot: CategorySnapshot = {
+ items: result.items,
+ provider,
+ refreshedAt: result.refreshedAt ?? new Date().toISOString(),
+ errors: attemptErrors,
+ };
+ categoryCache[key] = { timestamp: Date.now(), snapshot };
+ snapshotStore.saveSnapshot(key, snapshot);
+ return snapshot;
+ } catch (error) {
+ const message = error instanceof Error ? error.message : String(error);
+ attemptErrors.push(`${provider}:${message}`);
+ console.error(`Market ticker ${key} via ${provider} error:`, error);
+ }
+ }
+
+ const staleSnapshot = snapshotStore.getLatestSnapshot(key);
+ if (staleSnapshot) {
+ const snapshot: CategorySnapshot = {
+ items: staleSnapshot.items,
+ provider: staleSnapshot.provider,
+ refreshedAt: staleSnapshot.refreshedAt,
+ errors: [...attemptErrors, 'snapshot-store:stale'],
+ };
+ categoryCache[key] = { timestamp: Date.now(), snapshot };
+ return snapshot;
+ }
+
+ if (cacheEntry) {
+ return {
+ ...cacheEntry.snapshot,
+ errors: [...cacheEntry.snapshot.errors, ...attemptErrors],
+ };
+ }
+
+ return {
+ items: spec.items.map((item) => ({ ...item, currency: item.currency ?? 'USD' })),
+ provider: spec.providers[0],
+ refreshedAt: null,
+ errors: attemptErrors,
+ };
+}
+
+async function fetchByProvider(provider: QuoteProvider, list: WatchItem[], category: WatchlistKey): Promise {
+ switch (provider) {
+ case 'stooq':
+ return fetchStooqCategory(list);
+ case 'coingecko':
+ return fetchCoinGeckoCategory(list);
+ case 'twelvedata':
+ return fetchTwelveDataCategory(list, resolveTwelveDataKey(category));
+ case 'alphavantage':
+ return fetchAlphaVantageCategory(list, category);
+ case 'marketstack':
+ return fetchMarketstackCategory(list);
+ case 'massive':
+ return fetchMassiveCategory(list);
+ default:
+ throw new Error(`Unsupported provider: ${provider satisfies never}`);
+ }
+}
+
+function resolveTwelveDataKey(category: WatchlistKey): string | null | undefined {
+ if (category === 'commodities') {
+ return twelvedataCommodityKey ?? twelvedataKey;
+ }
+ if (category === 'equities') {
+ return twelvedataStocksKey ?? twelvedataKey;
+ }
+ return twelvedataKey;
+}
+
+interface StooqQuoteRow {
+ symbol: string;
+ open?: number;
+ close?: number;
+}
+
+async function fetchStooqCategory(list: WatchItem[]): Promise {
+ const symbols = list
+ .map((item) => (item.providers?.stooq ?? item.symbol)?.toLowerCase())
+ .filter((symbol): symbol is string => Boolean(symbol));
+
+ if (!symbols.length) {
+ return { items: list, refreshedAt: null };
+ }
+
+ const quotes = await downloadStooqQuotes(symbols);
+ return {
+ items: applyStooqQuotes(list, quotes),
+ refreshedAt: new Date().toISOString(),
+ };
+}
+
+type TwelveDataQuote = {
+ symbol?: string;
+ name?: string;
+ price?: string;
+ close?: string;
+ percent_change?: string;
+ currency?: string;
+ datetime?: string;
+ status?: string;
+};
+
+type CoinGeckoPriceRow = {
+ usd?: number;
+ usd_24h_change?: number;
+ last_updated_at?: number;
+};
+
+const COINGECKO_SYMBOL_MAP: Record = {
+ BTCUSD: 'bitcoin',
+ ETHUSD: 'ethereum',
+ SOLUSD: 'solana',
+ XRPUSD: 'ripple',
+ DOGEUSD: 'dogecoin',
+};
+
+async function fetchTwelveDataCategory(list: WatchItem[], apiKey?: string | null): Promise {
+ if (!apiKey) {
+ throw new Error('TWELVEDATA_API_KEY is required for TwelveData quotes.');
+ }
+
+ const items = await fetchFromTwelveData(list, apiKey);
+ const refreshedAt = new Date().toISOString();
+ return { items, refreshedAt };
+}
+
+async function fetchCoinGeckoCategory(list: WatchItem[]): Promise {
+ const targets = list
+ .map((item) => ({
+ item,
+ id: (item.providers?.coingecko ?? COINGECKO_SYMBOL_MAP[item.symbol])?.toLowerCase(),
+ }))
+ .filter((entry): entry is { item: WatchItem; id: string } => Boolean(entry.id));
+
+ if (!targets.length) {
+ throw new Error('Missing CoinGecko identifiers for crypto watchlist.');
+ }
+
+ const ids = Array.from(new Set(targets.map((target) => target.id)));
+ const params = {
+ ids: ids.join(','),
+ vs_currencies: 'usd',
+ include_24hr_change: 'true',
+ include_last_updated_at: 'true',
+ } as const;
+
+ const headers = coingeckoKey ? { 'x-cg-demo-api-key': coingeckoKey } : undefined;
+ const response = await axios
+ .get(`${COINGECKO_BASE_URL}/simple/price`, { params, headers })
+ .catch((error) => {
+ if (axios.isAxiosError(error)) {
+ const detail = typeof error.response?.data?.error === 'string' ? error.response?.data?.error : error.message;
+ throw new Error(`coingecko:${detail}`);
+ }
+ throw error;
+ });
+ const payload = response.data && typeof response.data === 'object' ? (response.data as Record) : {};
+
+ let latest: string | null = null;
+ const items = list.map((item) => {
+ const id = (item.providers?.coingecko ?? COINGECKO_SYMBOL_MAP[item.symbol])?.toLowerCase();
+ const quote = id ? payload[id] : undefined;
+ const price = parseMaybeNumber(quote?.usd);
+ const changePercent = parseMaybeNumber(quote?.usd_24h_change);
+ const refreshed = typeof quote?.last_updated_at === 'number' ? toIsoFromTimestamp(quote.last_updated_at * 1000) : null;
+ if (refreshed && (!latest || refreshed > latest)) {
+ latest = refreshed;
+ }
+
+ return {
+ ...item,
+ currency: 'USD',
+ price,
+ changePercent,
+ };
+ });
+
+ return {
+ items,
+ refreshedAt: latest,
+ };
+}
+
+async function fetchAlphaVantageCategory(list: WatchItem[], category: WatchlistKey): Promise {
+ if (category === 'forex') {
+ return fetchAlphaVantageForex(list);
+ }
+ if (category === 'commodities') {
+ return fetchAlphaVantageCommodities(list);
+ }
+ throw new Error(`Alpha Vantage provider not configured for "${category}".`);
+}
+
+async function fetchAlphaVantageForex(list: WatchItem[]): Promise {
+ if (!alphaVantageForexKey) {
+ throw new Error('ALPHA_VANTAGE_FOREX_API_KEY (or ALPHA_VANTAGE_API_KEY) is required for forex quotes.');
+ }
+
+ const items: MarketTickerItem[] = [];
+ let latest: string | null = null;
+
+ for (const item of list) {
+ const pair = (item.providers?.alphavantage ?? item.symbol).toUpperCase();
+ const { from, to } = splitForexSymbol(pair);
+ const response = await requestAlphaVantage(
+ {
+ function: 'CURRENCY_EXCHANGE_RATE',
+ from_currency: from,
+ to_currency: to,
+ },
+ alphaVantageForexKey
+ );
+
+ const block: Record | undefined = response.data?.['Realtime Currency Exchange Rate'];
+ if (!block) {
+ const note = response.data?.Note ?? response.data?.['Error Message'];
+ throw new Error(note ?? 'Alpha Vantage returned an empty payload.');
+ }
+
+ const exchangeRate = parseMaybeNumber(block['5. Exchange Rate']);
+ const refreshed = toIsoTimestamp(block['6. Last Refreshed']);
+ if (refreshed && (!latest || refreshed > latest)) {
+ latest = refreshed;
+ }
+
+ items.push({
+ ...item,
+ currency: to,
+ price: exchangeRate,
+ changePercent: undefined,
+ });
+ }
+
+ return {
+ items,
+ refreshedAt: latest,
+ };
+}
+
+type AlphaCommodityQuote = {
+ price?: number;
+ changePercent?: number;
+ refreshedAt: string | null;
+};
+
+async function fetchAlphaVantageCommodities(list: WatchItem[]): Promise {
+ if (!alphaVantageCommodityKey) {
+ throw new Error('ALPHA_VANTAGE_API_KEY (or ALPHA_VANTAGE_FOREX_API_KEY) is required for commodity quotes.');
+ }
+
+ const timestampCandidates: Array = [];
+ const items: MarketTickerItem[] = [];
+
+ for (const item of list) {
+ const spec = ALPHA_COMMODITY_SPECS[item.symbol];
+ if (!spec) {
+ throw new Error(`Missing Alpha Vantage commodity mapping for ${item.symbol}`);
+ }
+
+ const quote: AlphaCommodityQuote =
+ spec.mode === 'dailySeries'
+ ? await loadAlphaDailySeriesQuote(spec.symbol, alphaVantageCommodityKey)
+ : await loadAlphaMacroCommodityQuote(spec.function, spec.interval, alphaVantageCommodityKey);
+
+ timestampCandidates.push(quote.refreshedAt);
+ items.push({
+ ...item,
+ currency: item.currency ?? 'USD',
+ price: quote.price,
+ changePercent: quote.changePercent,
+ });
+ }
+
+ return {
+ items,
+ refreshedAt: getLatestTimestamp(timestampCandidates),
+ };
+}
+
+async function loadAlphaDailySeriesQuote(symbol: string, apiKey: string): Promise {
+ const response = await requestAlphaVantage(
+ {
+ function: 'TIME_SERIES_DAILY',
+ symbol,
+ outputsize: 'compact',
+ },
+ apiKey
+ );
+
+ const series = response.data?.['Time Series (Daily)'];
+ if (!series || typeof series !== 'object') {
+ const note = response.data?.Note ?? response.data?.['Error Message'];
+ throw new Error(note ?? `Alpha Vantage returned no daily series for ${symbol}`);
+ }
+
+ const entries = Object.entries(series as Record>)
+ .filter(([date]) => Boolean(date))
+ .sort(([a], [b]) => (a > b ? -1 : 1));
+
+ if (!entries.length) {
+ throw new Error(`Alpha Vantage returned an empty daily series for ${symbol}`);
+ }
+
+ const [latestDate, latestRow] = entries[0];
+ const price =
+ parseMaybeNumber(latestRow['4. close']) ??
+ parseMaybeNumber(latestRow['5. adjusted close']) ??
+ parseMaybeNumber(latestRow['4. Close']);
+
+ const previousRow = entries[1]?.[1];
+ const previousClose = previousRow
+ ? parseMaybeNumber(previousRow['4. close']) ?? parseMaybeNumber(previousRow['5. adjusted close'])
+ : undefined;
+
+ const changePercent =
+ typeof price === 'number' && typeof previousClose === 'number'
+ ? computeChangePercent(price - previousClose, previousClose)
+ : undefined;
+
+ return {
+ price,
+ changePercent,
+ refreshedAt: toIsoTimestamp(latestDate),
+ };
+}
+
+async function loadAlphaMacroCommodityQuote(
+ func: AlphaMacroCommodityFunction,
+ interval: 'daily' | 'weekly' | 'monthly',
+ apiKey: string
+): Promise {
+ const response = await requestAlphaVantage(
+ {
+ function: func,
+ interval,
+ },
+ apiKey
+ );
+
+ const rows = (Array.isArray(response.data?.data) ? response.data.data : []) as Record[];
+ const parsed = rows
+ .map((row) => ({
+ date: typeof row?.date === 'string' ? row.date : null,
+ value: parseMaybeNumber(row?.value),
+ }))
+ .filter((entry): entry is { date: string; value: number } => Boolean(entry.date) && typeof entry.value === 'number')
+ .sort((a, b) => (a.date > b.date ? -1 : 1));
+
+ if (!parsed.length) {
+ const note = response.data?.Note ?? response.data?.['Error Message'];
+ throw new Error(note ?? `Alpha Vantage returned no data for ${func}`);
+ }
+
+ const latest = parsed[0];
+ const previous = parsed[1];
+ const changePercent =
+ previous?.value !== undefined
+ ? computeChangePercent(latest.value - previous.value, previous.value)
+ : undefined;
+
+ return {
+ price: latest.value,
+ changePercent,
+ refreshedAt: toIsoTimestamp(latest.date),
+ };
+}
+
+type MarketstackQuote = {
+ symbol?: string;
+ date?: string;
+ open?: number;
+ close?: number;
+ last?: number;
+};
+
+type MassiveSummaryResult = {
+ ticker?: string;
+ price?: number | string;
+ session?: {
+ change?: number | string;
+ change_percent?: number | string;
+ previous_close?: number | string;
+ close?: number | string;
+ price?: number | string;
+ };
+ last_updated?: number | string;
+};
+
+type MassiveFuturesSnapshot = {
+ product_code?: string;
+ ticker?: string;
+ last_trade?: {
+ price?: number | string;
+ last_updated?: number | string;
+ };
+ last_quote?: {
+ ask?: number | string;
+ bid?: number | string;
+ last_updated?: number | string;
+ };
+ last_minute?: {
+ last_updated?: number | string;
+ };
+ session?: {
+ change?: number | string;
+ change_percent?: number | string;
+ previous_settlement?: number | string;
+ settlement_price?: number | string;
+ close?: number | string;
+ };
+ details?: {
+ settlement_date?: number | string;
+ };
+};
+
+async function fetchMarketstackCategory(list: WatchItem[]): Promise {
+ if (!marketstackKey) {
+ throw new Error('MARKETSTACK_API_KEY is required for commodity quotes.');
+ }
+
+ const symbols = Array.from(
+ new Set(
+ list
+ .map((item) => (item.providers?.marketstack ?? item.symbol)?.toUpperCase())
+ .filter((symbol): symbol is string => Boolean(symbol))
+ )
+ );
+
+ if (!symbols.length) {
+ return { items: list, refreshedAt: null };
+ }
+
+ const response = await axios.get(`${MARKETSTACK_BASE_URL}/eod/latest`, {
+ params: {
+ access_key: marketstackKey,
+ symbols: symbols.join(','),
+ limit: symbols.length,
+ },
+ });
+
+ if (response.data?.error) {
+ const message = response.data.error?.message ?? 'MarketStack returned an error response.';
+ throw new Error(message);
+ }
+
+ const rows: MarketstackQuote[] = Array.isArray(response.data?.data) ? response.data.data : [];
+ const lookup = new Map();
+ for (const row of rows) {
+ const symbol = typeof row?.symbol === 'string' ? row.symbol.toUpperCase() : undefined;
+ if (symbol) {
+ lookup.set(symbol, row);
+ }
+ }
+
+ let latest: string | null = null;
+ const items: MarketTickerItem[] = list.map((item) => {
+ const providerSymbol = (item.providers?.marketstack ?? item.symbol).toUpperCase();
+ const quote = lookup.get(providerSymbol);
+ if (quote?.date) {
+ const iso = toIsoTimestamp(quote.date);
+ if (iso && (!latest || iso > latest)) {
+ latest = iso;
+ }
+ }
+ const price = quote ? parseMaybeNumber(quote.close ?? quote.last) : undefined;
+ const changePercent =
+ quote?.open && quote?.open !== 0 && price !== undefined
+ ? ((price - quote.open) / quote.open) * 100
+ : undefined;
+
+ return {
+ ...item,
+ currency: item.currency ?? 'USD',
+ price,
+ changePercent,
+ };
+ });
+
+ return {
+ items,
+ refreshedAt: latest,
+ };
+}
+
+async function fetchMassiveCategory(list: WatchItem[]): Promise {
+ if (!massiveKey) {
+ throw new Error('MASSIVE_API_KEY is required for Massive quotes.');
+ }
+
+ const massiveAuthHeaders = {
+ Authorization: `Bearer ${massiveKey}`,
+ } as const;
+
+ type SummaryTarget = { ticker: string; item: WatchItem };
+ type FuturesTarget = { productCode: string; item: WatchItem };
+
+ const summaryTargets: SummaryTarget[] = [];
+ const futuresTargets: FuturesTarget[] = [];
+
+ for (const item of list) {
+ const raw = (item.providers?.massive ?? item.symbol)?.trim();
+ if (!raw) {
+ continue;
+ }
+ if (raw.toLowerCase().startsWith('product:')) {
+ const productCode = raw.slice('product:'.length).toUpperCase();
+ if (productCode) {
+ futuresTargets.push({ productCode, item });
+ }
+ continue;
+ }
+ summaryTargets.push({ ticker: raw, item });
+ }
+
+ const assignments = new Map();
+ const timestampCandidates: Array = [];
+
+ if (summaryTargets.length) {
+ const tickers = Array.from(new Set(summaryTargets.map((entry) => entry.ticker)));
+ const response = await axios.get(`${MASSIVE_BASE_URL}/v1/summaries`, {
+ headers: massiveAuthHeaders,
+ params: {
+ apiKey: massiveKey,
+ 'ticker.any_of': tickers.join(','),
+ },
+ });
+
+ const rawResults = Array.isArray(response.data?.results) ? (response.data.results as MassiveSummaryResult[]) : [];
+ const lookup = new Map();
+ for (const row of rawResults) {
+ if (typeof row?.ticker === 'string') {
+ lookup.set(row.ticker, row);
+ }
+ }
+
+ for (const target of summaryTargets) {
+ const snapshot = lookup.get(target.ticker);
+ if (!snapshot) {
+ continue;
+ }
+ const session = snapshot.session;
+ const price = parseMaybeNumber(snapshot.price ?? session?.price ?? session?.close);
+ const changePercent = computeChangePercent(
+ parseMaybeNumber(session?.change),
+ parseMaybeNumber(session?.previous_close),
+ parseMaybeNumber(session?.change_percent)
+ );
+ const refreshed = toIsoFromTimestamp(parseMaybeNumber(snapshot.last_updated));
+ timestampCandidates.push(refreshed);
+ assignments.set(target.item.symbol, {
+ ...target.item,
+ currency: target.item.currency ?? 'USD',
+ price,
+ changePercent,
+ });
+ }
+ }
+
+ if (futuresTargets.length) {
+ const productCodes = Array.from(new Set(futuresTargets.map((entry) => entry.productCode)));
+ const snapshotLimit = Math.min(Math.max(productCodes.length * 25, 25), 500);
+ const response = await axios.get(`${MASSIVE_BASE_URL}/futures/vX/snapshot`, {
+ headers: massiveAuthHeaders,
+ params: {
+ apiKey: massiveKey,
+ 'product_code.any_of': productCodes.join(','),
+ limit: snapshotLimit,
+ },
+ });
+
+ const rawResults = Array.isArray(response.data?.results) ? (response.data.results as MassiveFuturesSnapshot[]) : [];
+ const grouped = new Map();
+ for (const row of rawResults) {
+ const productCode = typeof row?.product_code === 'string' ? row.product_code.toUpperCase() : undefined;
+ if (!productCode) {
+ continue;
+ }
+ const current = grouped.get(productCode);
+ if (!current) {
+ grouped.set(productCode, row);
+ continue;
+ }
+ const currentDate = parseMaybeNumber(current.details?.settlement_date) ?? Number.MAX_VALUE;
+ const candidateDate = parseMaybeNumber(row.details?.settlement_date) ?? Number.MAX_VALUE;
+ if (candidateDate < currentDate) {
+ grouped.set(productCode, row);
+ }
+ }
+
+ for (const target of futuresTargets) {
+ const snapshot = grouped.get(target.productCode);
+ if (!snapshot) {
+ continue;
+ }
+ const session = snapshot.session;
+ const price =
+ parseMaybeNumber(snapshot.last_trade?.price) ??
+ parseMaybeNumber(session?.settlement_price) ??
+ parseMaybeNumber(session?.close) ??
+ parseMaybeNumber(snapshot.last_quote?.bid);
+ const changePercent = computeChangePercent(
+ parseMaybeNumber(session?.change),
+ parseMaybeNumber(session?.previous_settlement),
+ parseMaybeNumber(session?.change_percent)
+ );
+ const refreshed = toIsoFromTimestamp(
+ parseMaybeNumber(snapshot.last_trade?.last_updated) ??
+ parseMaybeNumber(snapshot.last_quote?.last_updated) ??
+ parseMaybeNumber(snapshot.last_minute?.last_updated)
+ );
+ timestampCandidates.push(refreshed);
+ assignments.set(target.item.symbol, {
+ ...target.item,
+ currency: target.item.currency ?? 'USD',
+ price,
+ changePercent,
+ });
+ }
+ }
+
+ const refreshedAt = getLatestTimestamp(timestampCandidates);
+ const items = list.map((item) => assignments.get(item.symbol) ?? { ...item, currency: item.currency ?? 'USD' });
+
+ return {
+ items,
+ refreshedAt,
+ };
+}
+
+async function downloadStooqQuotes(symbols: string[]): Promise> {
+ if (!symbols.length) {
+ return {};
+ }
+
+ const uniqueSymbols = Array.from(new Set(symbols));
+ const params = new URLSearchParams({
+ s: uniqueSymbols.join('+'),
+ f: 'sd2t2ohlcv',
+ e: 'csv',
+ h: '1',
+ });
+
+ const response = await axios.get(`${STOOQ_QUOTE_URL}?${params.toString()}`, {
+ responseType: 'text',
+ });
+
+ return parseStooqCsv(response.data);
+}
+
+function parseStooqCsv(text: string): Record {
+ const trimmed = text.trim();
+ if (!trimmed) {
+ return {};
+ }
+
+ const [headerLine, ...rows] = trimmed.split(/\r?\n/).filter(Boolean);
+ const headers = headerLine.split(',');
+ const idx = (key: string) => headers.findIndex((column) => column.toLowerCase() === key.toLowerCase());
+ const symbolIdx = idx('Symbol');
+ const openIdx = idx('Open');
+ const closeIdx = idx('Close');
+
+ const result: Record = {};
+
+ for (const row of rows) {
+ const cells = row.split(',');
+ const symbol = cells[symbolIdx]?.trim();
+ if (!symbol || symbol === 'N/D') {
+ continue;
+ }
+ const open = cells[openIdx]?.trim();
+ const close = cells[closeIdx]?.trim();
+ const normalizedSymbol = symbol.toLowerCase();
+ result[normalizedSymbol] = {
+ symbol,
+ open: parseMaybeNumber(open),
+ close: parseMaybeNumber(close),
+ };
+ }
+
+ return result;
+}
+
+function applyStooqQuotes(list: WatchItem[], quotes?: Record): MarketTickerItem[] {
+ return list.map((item) => {
+ const providerSymbol = (item.providers?.stooq ?? item.symbol)?.toLowerCase();
+ const quote = providerSymbol && quotes ? quotes[providerSymbol] : undefined;
+ const price = quote?.close;
+ const changePercent =
+ quote?.open && quote?.open !== 0 && price !== undefined
+ ? ((price - quote.open) / quote.open) * 100
+ : undefined;
+
+ return {
+ ...item,
+ currency: item.currency ?? 'USD',
+ price,
+ changePercent,
+ };
+ });
+}
+
+function normalizeTwelveDataResponse(raw: unknown): Record {
+ if (!raw || typeof raw !== 'object') {
+ return {};
+ }
+
+ if ('status' in raw && (raw as Record).status === 'error') {
+ return {};
+ }
+
+ if ('symbol' in raw) {
+ const quote = raw as TwelveDataQuote;
+ const key = quote.symbol ?? '';
+ return key ? { [key]: quote } : {};
+ }
+
+ return raw as Record;
+}
+
+async function fetchFromTwelveData(list: WatchItem[], apiKey: string): Promise {
+ const mapped = list
+ .map((item) => ({ item, symbol: item.providers?.twelvedata ?? item.symbol }))
+ .filter(({ symbol }) => Boolean(symbol));
+
+ if (!mapped.length) {
+ return list;
+ }
+
+ const uniqueSymbols = Array.from(new Set(mapped.map(({ symbol }) => symbol)));
+
+ const response = await axios.get(`${TWELVEDATA_BASE_URL}/quote`, {
+ params: {
+ symbol: uniqueSymbols.join(','),
+ apikey: apiKey,
+ },
+ });
+
+ const normalized = normalizeTwelveDataResponse(response.data);
+
+ return list.map((item) => {
+ const providerSymbol = item.providers?.twelvedata ?? item.symbol;
+ const quote = providerSymbol ? normalized[providerSymbol] : undefined;
+ const price = quote ? parseMaybeNumber(quote.price ?? quote.close) : undefined;
+ const changePercent = quote ? parseMaybeNumber(quote.percent_change) : undefined;
+
+ return {
+ ...item,
+ currency: quote?.currency ?? item.currency ?? 'USD',
+ price,
+ changePercent,
+ };
+ });
+}
+
+type AlphaVantageParams = Record;
+
+async function requestAlphaVantage(params: AlphaVantageParams, preferredKey?: string | null) {
+ const candidateKeys = [preferredKey, alphaVantageRetryKey]
+ .filter((key): key is string => Boolean(key))
+ .filter((key, index, arr) => arr.indexOf(key) === index);
+
+ if (!candidateKeys.length) {
+ throw new Error('Alpha Vantage API key is required.');
+ }
+
+ let lastError: Error | null = null;
+
+ for (let index = 0; index < candidateKeys.length; index++) {
+ const key = candidateKeys[index];
+ const isLastAttempt = index === candidateKeys.length - 1;
+ try {
+ const response = await axios.get(ALPHA_VANTAGE_BASE_URL, {
+ params: {
+ ...params,
+ apikey: key,
+ },
+ });
+ const limitMessage = getAlphaLimitMessage(response.data);
+ if (limitMessage) {
+ lastError = new Error(limitMessage);
+ if (isLastAttempt) {
+ throw lastError;
+ }
+ continue;
+ }
+ return response;
+ } catch (error) {
+ if (shouldRetryAlphaError(error) && !isLastAttempt) {
+ lastError = error instanceof Error ? error : new Error(String(error));
+ continue;
+ }
+ throw error;
+ }
+ }
+
+ if (lastError) {
+ throw lastError;
+ }
+ throw new Error('Alpha Vantage request failed.');
+}
+
+function getAlphaLimitMessage(payload: unknown): string | null {
+ if (!payload || typeof payload !== 'object') {
+ return null;
+ }
+ const note = typeof (payload as Record).Note === 'string' ? (payload as Record).Note : null;
+ const info = typeof (payload as Record).Information === 'string' ? (payload as Record).Information : null;
+ const message = note ?? info;
+ if (!message) {
+ return null;
+ }
+ const normalized = message.toLowerCase();
+ if (normalized.includes('thank you for using alpha vantage') || normalized.includes('premium support') || normalized.includes('frequency')) {
+ return message;
+ }
+ return null;
+}
+
+function shouldRetryAlphaError(error: unknown): boolean {
+ if (!axios.isAxiosError(error)) {
+ return false;
+ }
+ const status = error.response?.status;
+ if (status === 429) {
+ return true;
+ }
+ return Boolean(getAlphaLimitMessage(error.response?.data));
+}
+
+function parseMaybeNumber(value: unknown): number | undefined {
+ if (typeof value === 'number' && Number.isFinite(value)) {
+ return value;
+ }
+ if (typeof value === 'string') {
+ const parsed = Number(value);
+ if (!Number.isNaN(parsed)) {
+ return parsed;
+ }
+ }
+ return undefined;
+}
+
+function splitForexSymbol(symbol: string): { from: string; to: string } {
+ if (symbol.length === 6) {
+ return { from: symbol.slice(0, 3), to: symbol.slice(3, 6) };
+ }
+ const match = symbol.match(/([A-Z]{3})[\/_-]?([A-Z]{3})/);
+ if (match) {
+ return { from: match[1], to: match[2] };
+ }
+ throw new Error(`Unable to parse forex symbol "${symbol}"`);
+}
+
+function toIsoFromTimestamp(value?: number): string | null {
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
+ return null;
+ }
+ const milliseconds = value > 1e15 ? value / 1_000_000 : value;
+ const date = new Date(milliseconds);
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
+}
+
+function toIsoTimestamp(value?: string): string | null {
+ if (!value) {
+ return null;
+ }
+ const normalized = /[zZ+]/.test(value) ? value : `${value}Z`;
+ const date = new Date(normalized);
+ return Number.isNaN(date.getTime()) ? null : date.toISOString();
+}
+
+function getLatestTimestamp(values: Array): string | null {
+ const timestamps = values
+ .map((value) => (value ? Date.parse(value) : NaN))
+ .filter((time) => Number.isFinite(time)) as number[];
+
+ if (!timestamps.length) {
+ return null;
+ }
+
+ return new Date(Math.max(...timestamps)).toISOString();
+}
+
+function hasLiveQuotes(items: MarketTickerItem[], requireComplete = false): boolean {
+ const hasPrice = (item: MarketTickerItem) => typeof item.price === 'number' && Number.isFinite(item.price);
+ return requireComplete ? items.every(hasPrice) : items.some(hasPrice);
+}
+
+function computeChangePercent(change?: number, baseline?: number, fallback?: number): number | undefined {
+ if (typeof change === 'number' && typeof baseline === 'number' && baseline !== 0) {
+ return (change / baseline) * 100;
+ }
+ if (typeof fallback === 'number') {
+ return fallback;
+ }
+ return undefined;
+}
+
+function matchesWatchlist(snapshotItems: MarketTickerItem[], specItems: WatchItem[]): boolean {
+ if (snapshotItems.length !== specItems.length) {
+ return false;
+ }
+ const expected = new Set(specItems.map((item) => item.symbol));
+ for (const item of snapshotItems) {
+ if (!expected.has(item.symbol)) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts b/apps/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts
similarity index 88%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts
rename to apps/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts
index 2f9b073..be17d9e 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts
+++ b/apps/Cortensor-Price-Analyzer/src/app/api/price-analyzer/route.ts
@@ -1,5 +1,5 @@
import { NextRequest, NextResponse } from 'next/server';
-import { MarketDataService } from '@/lib/marketDataService';
+import { MarketDataService, MarketDataError } from '@/lib/marketDataService';
import { NewsService } from '@/lib/newsService';
import { CortensorService } from '@/lib/cortensorService';
import type { AnalysisHorizon, AnalyzerResponse, AssetType, MarketAnalysisContext } from '@/lib/marketTypes';
@@ -64,6 +64,11 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: true, data: response });
} catch (error) {
+ if (error instanceof MarketDataError) {
+ console.warn('Market data request rejected:', error.message);
+ return NextResponse.json({ error: error.message, code: error.code ?? 'MARKET_DATA_ERROR' }, { status: error.status });
+ }
+
console.error('Price analyzer error:', error);
return NextResponse.json({ error: 'Failed to process analysis request' }, { status: 500 });
}
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/api/summarize/route.ts b/apps/Cortensor-Price-Analyzer/src/app/api/summarize/route.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/api/summarize/route.ts
rename to apps/Cortensor-Price-Analyzer/src/app/api/summarize/route.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/favicon.ico b/apps/Cortensor-Price-Analyzer/src/app/favicon.ico
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/favicon.ico
rename to apps/Cortensor-Price-Analyzer/src/app/favicon.ico
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/globals.css b/apps/Cortensor-Price-Analyzer/src/app/globals.css
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/globals.css
rename to apps/Cortensor-Price-Analyzer/src/app/globals.css
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/layout.tsx b/apps/Cortensor-Price-Analyzer/src/app/layout.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/layout.tsx
rename to apps/Cortensor-Price-Analyzer/src/app/layout.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/page.tsx b/apps/Cortensor-Price-Analyzer/src/app/page.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/app/page.tsx
rename to apps/Cortensor-Price-Analyzer/src/app/page.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx b/apps/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx
index 48546f2..9b94845 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx
+++ b/apps/Cortensor-Price-Analyzer/src/components/HistoryPanel.tsx
@@ -34,6 +34,11 @@ export function HistoryPanel({ onLoadHistoryItem, onHistoryChange, className }:
const [query, setQuery] = useState('');
const [stats, setStats] = useState({ total: 0, oldestDate: null });
+ const refreshHistory = () => {
+ const items = HistoryService.getHistory();
+ setHistory(items);
+ };
+
useEffect(() => {
refreshHistory();
}, []);
@@ -47,11 +52,6 @@ export function HistoryPanel({ onLoadHistoryItem, onHistoryChange, className }:
return HistoryService.searchHistory(query.trim());
}, [query, history]);
- const refreshHistory = () => {
- const items = HistoryService.getHistory();
- setHistory(items);
- };
-
const handleLoad = (item: HistoryItem) => {
onLoadHistoryItem(item);
};
diff --git a/apps/Cortensor-Price-Analyzer/src/components/MarketTickerSidebar.tsx b/apps/Cortensor-Price-Analyzer/src/components/MarketTickerSidebar.tsx
new file mode 100644
index 0000000..fff8e08
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/src/components/MarketTickerSidebar.tsx
@@ -0,0 +1,320 @@
+'use client';
+
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import { ChevronLeft, ChevronRight, RefreshCw, TrendingUp } from 'lucide-react';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { Badge } from '@/components/ui/badge';
+import { Alert, AlertDescription } from '@/components/ui/alert';
+import { Button } from '@/components/ui/button';
+import { cn } from '@/lib/utils';
+
+type AssetKind = 'equity' | 'crypto' | 'forex' | 'commodity';
+
+type MarketTickerItem = {
+ symbol: string;
+ name: string;
+ type: AssetKind;
+ price?: number;
+ changePercent?: number;
+ currency?: string;
+};
+
+type MarketTickerGroups = {
+ equities: MarketTickerItem[];
+ crypto: MarketTickerItem[];
+ forex: MarketTickerItem[];
+ commodities: MarketTickerItem[];
+};
+
+type MarketTickerResponse = MarketTickerGroups & { refreshedAt?: string };
+
+const CATEGORY_CONFIG: Record = {
+ equities: { title: 'US Equities Focus', badge: 'Stocks', description: 'Growth + mega-cap movers' },
+ crypto: { title: 'Crypto Majors', badge: 'Digital Assets', description: 'Layer-1 and top memecoins' },
+ forex: { title: 'FX Pairs', badge: 'Forex', description: 'G10 volatility snapshot' },
+ commodities: { title: 'Macro Commodities', badge: 'Commodities', description: 'Energy & precious metals' },
+};
+
+const CURRENCY_SYMBOL: Record = {
+ USD: '$',
+ EUR: '€',
+ GBP: '£',
+ JPY: '¥',
+};
+
+export function MarketTickerSidebar() {
+ const [data, setData] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [refreshing, setRefreshing] = useState(false);
+ const [error, setError] = useState(null);
+ const [activeCategory, setActiveCategory] = useState('equities');
+ const [userCategoryOverride, setUserCategoryOverride] = useState(false);
+ const swipeRef = useRef(null);
+
+ const loadTickers = useCallback(async () => {
+ try {
+ setRefreshing(true);
+ const response = await fetch('/api/market-tickers');
+ if (!response.ok) {
+ throw new Error('Failed to load live quotes.');
+ }
+ const payload = await response.json();
+ setData(payload.data ?? null);
+ setError(null);
+ } catch (err) {
+ setError(err instanceof Error ? err.message : 'Unable to retrieve quote data.');
+ } finally {
+ setLoading(false);
+ setRefreshing(false);
+ }
+ }, []);
+
+ const categories = useMemo(() => Object.keys(CATEGORY_CONFIG) as Array, []);
+
+ const categoryHasPrices = useCallback(
+ (category: keyof MarketTickerGroups) =>
+ Boolean(data?.[category]?.some((item) => typeof item.price === 'number')),
+ [data]
+ );
+
+ const handleNextCategory = useCallback(() => {
+ setUserCategoryOverride(true);
+ setActiveCategory((current) => {
+ const index = categories.indexOf(current);
+ const nextIndex = index === categories.length - 1 ? 0 : index + 1;
+ return categories[nextIndex];
+ });
+ }, [categories]);
+
+ const handlePrevCategory = useCallback(() => {
+ setUserCategoryOverride(true);
+ setActiveCategory((current) => {
+ const index = categories.indexOf(current);
+ const prevIndex = index === 0 ? categories.length - 1 : index - 1;
+ return categories[prevIndex];
+ });
+ }, [categories]);
+
+ useEffect(() => {
+ const handleKey = (event: KeyboardEvent) => {
+ if (event.key === 'ArrowLeft') {
+ handlePrevCategory();
+ } else if (event.key === 'ArrowRight') {
+ handleNextCategory();
+ }
+ };
+ window.addEventListener('keydown', handleKey);
+ return () => window.removeEventListener('keydown', handleKey);
+ }, [categories, handleNextCategory, handlePrevCategory]);
+
+ useEffect(() => {
+ const node = swipeRef.current;
+ if (!node) return;
+
+ let startX = 0;
+
+ const onTouchStart = (event: TouchEvent) => {
+ startX = event.touches[0]?.clientX ?? 0;
+ };
+
+ const onTouchEnd = (event: TouchEvent) => {
+ const endX = event.changedTouches[0]?.clientX ?? 0;
+ const delta = endX - startX;
+ if (Math.abs(delta) < 40) return;
+ if (delta > 0) {
+ handlePrevCategory();
+ } else {
+ handleNextCategory();
+ }
+ };
+
+ node.addEventListener('touchstart', onTouchStart);
+ node.addEventListener('touchend', onTouchEnd);
+ return () => {
+ node.removeEventListener('touchstart', onTouchStart);
+ node.removeEventListener('touchend', onTouchEnd);
+ };
+ }, [handleNextCategory, handlePrevCategory]);
+
+ useEffect(() => {
+ loadTickers();
+ }, [loadTickers]);
+
+ useEffect(() => {
+ if (!data || userCategoryOverride) {
+ return;
+ }
+ if (categoryHasPrices(activeCategory)) {
+ return;
+ }
+
+ const fallback = categories.find((category) => categoryHasPrices(category));
+ if (fallback && fallback !== activeCategory) {
+ setActiveCategory(fallback);
+ }
+ }, [data, activeCategory, categories, categoryHasPrices, userCategoryOverride]);
+
+ const updatedLabel = data?.refreshedAt
+ ? new Date(data.refreshedAt).toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' })
+ : null;
+ const activeCategoryHasPrices = categoryHasPrices(activeCategory);
+
+ const renderItems = (items: MarketTickerItem[]) => {
+ if (!items.length) {
+ return No symbols available yet.
;
+ }
+
+ return (
+
+ {items.map((item) => (
+
+
+
{item.symbol}
+
{item.name}
+
+
+
+ {formatPrice(item.price, item.currency)}
+ {item.currency && (
+ {item.currency}
+ )}
+
+
+ {formatChange(item.changePercent)}
+
+
+
+ ))}
+
+ );
+ };
+
+ return (
+
+
+
+
+ Market Pulse
+
+
+ Curated watchlists spanning equities, crypto, FX, and macro commodities powered by Stooq + Twelve Data.
+
+
+
+ {updatedLabel ? `Last sync ${updatedLabel}` : 'Waiting for live data...'}
+
+
+
+ Refresh
+
+
+
+
+ {error && !loading && (
+
+ {error}
+
+ )}
+ {loading && (
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+ ))}
+
+ )}
+ {!loading && data && (
+
+
+
+
+ {CATEGORY_CONFIG[activeCategory].title}
+
+ {CATEGORY_CONFIG[activeCategory].badge}
+
+
+
+ {CATEGORY_CONFIG[activeCategory].description}
+
+ {!activeCategoryHasPrices && (
+
Live pricing unavailable — refresh or switch views.
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {renderItems(data[activeCategory] ?? [])}
+
+
+ {categories.map((key) => (
+ {
+ setUserCategoryOverride(true);
+ setActiveCategory(key);
+ }}
+ />
+ ))}
+
+
+ )}
+
+
+ );
+}
+
+function formatPrice(value?: number, currency = 'USD'): string {
+ if (value === undefined || Number.isNaN(value)) {
+ return '—';
+ }
+ const symbol = CURRENCY_SYMBOL[currency] ?? '';
+ const abs = Math.abs(value);
+ const digits = abs >= 100 ? 2 : abs >= 1 ? 3 : 4;
+ return `${symbol}${value.toFixed(digits)}`;
+}
+
+function formatChange(value?: number): string {
+ if (value === undefined || Number.isNaN(value)) {
+ return '—';
+ }
+ const display = value.toFixed(2);
+ return `${value >= 0 ? '+' : ''}${display}%`;
+}
+
+function getChangeColor(value?: number): string {
+ if (value === undefined || Number.isNaN(value)) {
+ return 'text-slate-500';
+ }
+ return value >= 0 ? 'text-emerald-600' : 'text-red-600';
+}
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx b/apps/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx
similarity index 98%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx
index 82cd762..3ee66e4 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx
+++ b/apps/Cortensor-Price-Analyzer/src/components/PriceAnalyzerForm.tsx
@@ -9,6 +9,7 @@ import { Badge } from '@/components/ui/badge';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Progress } from '@/components/ui/progress';
import { HistoryPanel } from '@/components/HistoryPanel';
+import { MarketTickerSidebar } from '@/components/MarketTickerSidebar';
import PriceHistoryChart, { CandleWithClose } from '@/components/PriceHistoryChart';
import { cn } from '@/lib/utils';
import { HistoryService, HistoryItem } from '@/lib/historyService';
@@ -528,18 +529,8 @@ export default function PriceAnalyzerForm() {
-
-
+
+
@@ -1066,13 +1057,18 @@ export default function PriceAnalyzerForm() {
)}
- {showHistory && (
-
-
- setHistoryCount(HistoryService.getHistory().length)} className="shadow-lg" />
-
+
+
+
+ {showHistory && (
+ setHistoryCount(HistoryService.getHistory().length)}
+ className="shadow-lg"
+ />
+ )}
- )}
+
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/PriceHistoryChart.tsx b/apps/Cortensor-Price-Analyzer/src/components/PriceHistoryChart.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/PriceHistoryChart.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/PriceHistoryChart.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/alert.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/alert.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/alert.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/alert.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/badge.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/badge.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/badge.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/badge.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/button.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/button.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/button.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/button.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/card.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/card.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/card.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/card.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/input.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/input.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/input.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/input.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/label.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/label.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/label.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/label.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/progress.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/progress.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/progress.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/progress.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/separator.tsx b/apps/Cortensor-Price-Analyzer/src/components/ui/separator.tsx
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/components/ui/separator.tsx
rename to apps/Cortensor-Price-Analyzer/src/components/ui/separator.tsx
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/cortensorService.ts b/apps/Cortensor-Price-Analyzer/src/lib/cortensorService.ts
similarity index 75%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/cortensorService.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/cortensorService.ts
index 271d023..b0015b9 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/cortensorService.ts
+++ b/apps/Cortensor-Price-Analyzer/src/lib/cortensorService.ts
@@ -1,4 +1,4 @@
-import axios from 'axios';
+import axios, { type AxiosError } from 'axios';
import type { AIAnalysis, CatalystHighlight, MarketAnalysisContext, MarketNewsItem } from './marketTypes';
interface CortensorChoiceResponse {
@@ -19,6 +19,7 @@ export class CortensorService {
private readonly temperature: number;
private readonly maxTokens: number;
private readonly timeoutMs: number;
+ private readonly retryTimeoutMs: number;
constructor() {
this.apiKey = process.env.CORTENSOR_API_KEY ?? '';
@@ -27,45 +28,90 @@ export class CortensorService {
}
const baseUrl = process.env.CORTENSOR_BASE_URL ?? 'http://69.164.253.134:5010';
- this.apiUrl = `${baseUrl.replace(/\/$/, '')}/api/v1/completions`;
-
- this.sessionId = Number.parseInt(process.env.CORTENSOR_SESSION ?? '6', 10);
+ const explicitUrl = process.env.CORTENSOR_API_URL;
+ this.apiUrl = explicitUrl
+ ? explicitUrl.trim().replace(/\/$/, '')
+ : `${baseUrl.replace(/\/$/, '')}/api/v1/completions`;
+
+ const sessionEnv =
+ process.env.CORTENSOR_SESSION_ID ?? process.env.CORTENSOR_SESSION ?? process.env.CORTENSOR_SESSIONID ?? '6';
+ const parsedSession = Number.parseInt(sessionEnv, 10);
+ this.sessionId = Number.isFinite(parsedSession) ? parsedSession : 6;
this.temperature = Number.parseFloat(process.env.CORTENSOR_TEMPERATURE ?? '0.35');
this.maxTokens = Number.parseInt(process.env.CORTENSOR_MAX_TOKENS ?? '2800', 10);
- const timeoutSeconds = Number.parseInt(process.env.CORTENSOR_TIMEOUT ?? '300', 10);
- this.timeoutMs = Number.isFinite(timeoutSeconds) ? timeoutSeconds * 1000 : 300_000;
+ const timeoutSeconds = Number.parseInt(process.env.CORTENSOR_TIMEOUT ?? '45', 10);
+ this.timeoutMs = Number.isFinite(timeoutSeconds) ? timeoutSeconds * 1000 : 45_000;
+ const retrySeconds = Number.parseInt(process.env.CORTENSOR_RETRY_TIMEOUT ?? '20', 10);
+ this.retryTimeoutMs = Number.isFinite(retrySeconds) ? retrySeconds * 1000 : 20_000;
}
async generatePriceAnalysis(context: MarketAnalysisContext): Promise
{
const prompt = this.buildPrompt(context);
try {
- const response = await axios.post(
- this.apiUrl,
- {
- session_id: this.sessionId,
- prompt,
- stream: false,
- temperature: this.temperature,
- max_tokens: this.maxTokens,
- },
- {
- headers: {
- Authorization: `Bearer ${this.apiKey}`,
- 'Content-Type': 'application/json',
- },
- timeout: this.timeoutMs,
- },
- );
-
- const raw = response.data?.choices?.[0]?.text ?? response.data?.text ?? '';
+ const raw = await this.requestWithRetry(prompt);
return this.parseResponse(raw, context);
} catch (error) {
+ if (axios.isAxiosError(error)) {
+ const descriptor = this.describeAxiosError(error);
+ console.warn(`Cortensor price analysis degraded: ${descriptor}`);
+ const fallbackNarrative = `${this.composeFallbackNarrative(context)} (AI narrative unavailable — ${descriptor}).`;
+ return this.fallbackAnalysis(context, fallbackNarrative);
+ }
+
console.error('Cortensor price analysis error:', error);
- return this.fallbackAnalysis(context, 'AI analysis unavailable — displaying raw market context.');
+ return this.fallbackAnalysis(context, this.composeFallbackNarrative(context));
}
}
+ private async requestWithRetry(prompt: string): Promise {
+ const attempts = [
+ { maxTokens: this.maxTokens, timeout: this.timeoutMs },
+ { maxTokens: Math.max(512, Math.round(this.maxTokens * 0.6)), timeout: this.retryTimeoutMs },
+ ];
+
+ let lastError: unknown;
+ for (let index = 0; index < attempts.length; index += 1) {
+ const attempt = attempts[index];
+ try {
+ const response = await axios.post(
+ this.apiUrl,
+ {
+ session_id: this.sessionId,
+ prompt,
+ stream: false,
+ temperature: this.temperature,
+ max_tokens: attempt.maxTokens,
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${this.apiKey}`,
+ 'Content-Type': 'application/json',
+ },
+ timeout: attempt.timeout,
+ },
+ );
+
+ const raw = response.data?.choices?.[0]?.text ?? response.data?.text ?? '';
+ if (raw.trim().length === 0) {
+ throw new Error('Empty Cortensor response');
+ }
+ return raw;
+ } catch (error) {
+ lastError = error;
+ if (!axios.isAxiosError(error) || !this.isRetriableError(error) || index === attempts.length - 1) {
+ throw error;
+ }
+
+ const descriptor = this.describeAxiosError(error);
+ console.warn(`Cortensor request attempt ${index + 1} failed (${descriptor}); retrying with lighter payload.`);
+ await this.delay(1_000 * (index + 1));
+ }
+ }
+
+ throw lastError;
+ }
+
private buildPrompt(context: MarketAnalysisContext): string {
const { snapshot, technicals, fundamentals, catalysts, news, horizon } = context;
@@ -320,4 +366,37 @@ GUIDELINES
if (Math.abs(value) >= 1_000) return `${(value / 1_000).toFixed(1)}K`;
return value.toFixed(0);
}
+
+ private describeAxiosError(error: unknown): string {
+ if (!axios.isAxiosError(error)) {
+ return 'unknown error';
+ }
+
+ const status = error.response?.status;
+ const message = (error.response?.data as { error?: string } | undefined)?.error ?? error.message;
+ if (status) {
+ return `${status} ${message}`;
+ }
+ if (error.code) {
+ return `${error.code} ${message}`;
+ }
+ return message;
+ }
+
+ private isRetriableError(error: AxiosError): boolean {
+ if (!error) {
+ return false;
+ }
+ const retriableStatuses = new Set([408, 429, 502, 503, 504]);
+ if (error.response?.status && retriableStatuses.has(error.response.status)) {
+ return true;
+ }
+ return error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT';
+ }
+
+ private delay(durationMs: number): Promise {
+ return new Promise((resolve) => {
+ setTimeout(resolve, durationMs);
+ });
+ }
}
\ No newline at end of file
diff --git a/apps/Cortensor-Price-Analyzer/src/lib/db/client.ts b/apps/Cortensor-Price-Analyzer/src/lib/db/client.ts
new file mode 100644
index 0000000..724fd6b
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/src/lib/db/client.ts
@@ -0,0 +1,45 @@
+import Database from 'better-sqlite3';
+import fs from 'node:fs';
+import path from 'node:path';
+
+const DEFAULT_DATA_DIR = path.join(process.cwd(), '.data');
+const DEFAULT_DB_PATH = path.join(DEFAULT_DATA_DIR, 'market-snapshots.db');
+
+function ensureDirectoryExists(dirPath: string): void {
+ if (!fs.existsSync(dirPath)) {
+ fs.mkdirSync(dirPath, { recursive: true });
+ }
+}
+
+function resolveDbPath(): string {
+ const customPath = process.env.MARKET_SNAPSHOT_DB_PATH;
+ if (customPath) {
+ const absolute = path.isAbsolute(customPath) ? customPath : path.join(process.cwd(), customPath);
+ ensureDirectoryExists(path.dirname(absolute));
+ return absolute;
+ }
+
+ ensureDirectoryExists(DEFAULT_DATA_DIR);
+ return DEFAULT_DB_PATH;
+}
+
+const dbPath = resolveDbPath();
+
+const db = new Database(dbPath);
+db.pragma('journal_mode = WAL');
+db.pragma('foreign_keys = ON');
+
+db.exec(`
+ CREATE TABLE IF NOT EXISTS market_snapshots (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ category TEXT NOT NULL,
+ provider TEXT NOT NULL,
+ payload TEXT NOT NULL,
+ refreshed_at TEXT,
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
+ );
+ CREATE INDEX IF NOT EXISTS idx_market_snapshots_category_created_at
+ ON market_snapshots (category, created_at DESC);
+`);
+
+export const snapshotDb = db;
diff --git a/apps/Cortensor-Price-Analyzer/src/lib/fmp.ts b/apps/Cortensor-Price-Analyzer/src/lib/fmp.ts
new file mode 100644
index 0000000..7218168
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/src/lib/fmp.ts
@@ -0,0 +1,4 @@
+const DEFAULT_FMP_BASE_URL = 'https://financialmodelingprep.com/stable';
+
+// Financial Modeling Prep now serves all public APIs under the /stable base URL.
+export const FMP_BASE_URL = (process.env.FMP_BASE_URL ?? DEFAULT_FMP_BASE_URL).replace(/\/$/, '');
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/historyService.ts b/apps/Cortensor-Price-Analyzer/src/lib/historyService.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/historyService.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/historyService.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/marketDataService.ts b/apps/Cortensor-Price-Analyzer/src/lib/marketDataService.ts
similarity index 96%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/marketDataService.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/marketDataService.ts
index 2f5963c..800d0b6 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/marketDataService.ts
+++ b/apps/Cortensor-Price-Analyzer/src/lib/marketDataService.ts
@@ -9,6 +9,7 @@ import {
MarketSnapshot,
TechnicalSummary,
} from './marketTypes';
+import { FMP_BASE_URL } from './fmp';
interface BuildContextParams {
ticker: string;
@@ -613,8 +614,8 @@ export class MarketDataService {
private async fetchFMPProfile(ticker: string): Promise> {
if (!this.fmpKey) return {};
try {
- const response = await axios.get(`https://financialmodelingprep.com/api/v3/profile/${ticker}`, {
- params: { apikey: this.fmpKey },
+ const response = await axios.get(`${FMP_BASE_URL}/profile`, {
+ params: { apikey: this.fmpKey, symbol: ticker },
});
const data = Array.isArray(response.data) ? response.data[0] : undefined;
if (!data) return {};
@@ -637,8 +638,8 @@ export class MarketDataService {
private async fetchFMPQuote(ticker: string): Promise<{ marketCap?: number; pe?: number; dividendYield?: number; eps?: number }> {
if (!this.fmpKey) return {};
try {
- const response = await axios.get(`https://financialmodelingprep.com/api/v3/quote/${ticker}`, {
- params: { apikey: this.fmpKey },
+ const response = await axios.get(`${FMP_BASE_URL}/quote`, {
+ params: { apikey: this.fmpKey, symbol: ticker },
});
const data = Array.isArray(response.data) ? response.data[0] : undefined;
if (!data) return {};
@@ -786,8 +787,8 @@ export class MarketDataService {
} | null> {
if (!this.fmpKey) return null;
try {
- const response = await axios.get(`https://financialmodelingprep.com/api/v3/key-metrics-ttm/${ticker}`, {
- params: { apikey: this.fmpKey },
+ const response = await axios.get(`${FMP_BASE_URL}/key-metrics-ttm`, {
+ params: { apikey: this.fmpKey, symbol: ticker },
});
const data = Array.isArray(response.data) ? response.data[0] : undefined;
if (!data) return null;
@@ -1170,11 +1171,30 @@ export class MarketDataService {
},
});
- const data = response.data as { status?: string; values?: Array>; message?: string } | undefined;
+ const data = response.data as {
+ status?: string;
+ values?: Array>;
+ message?: string;
+ code?: string;
+ } | undefined;
+
if (!data || data.status !== 'ok' || !Array.isArray(data.values)) {
- if (data?.status && data.status !== 'ok') {
- const message = data.message ?? 'Unknown TwelveData error';
- console.warn(`TwelveData history error (${ticker}): ${data.status} ${message}`);
+ const status = data?.status ?? 'error';
+ const message = data?.message ?? 'Unknown TwelveData error';
+ const code = data?.code;
+ console.warn(`TwelveData history error (${ticker}): ${status} ${message}`);
+
+ const normalizedMessage = message.toLowerCase();
+ const looksInvalidSymbol =
+ normalizedMessage.includes('symbol') ||
+ normalizedMessage.includes('figi') ||
+ status === 'error' && (code === 'symbol_not_found' || code === '400');
+
+ if (looksInvalidSymbol) {
+ throw new MarketDataError(`TwelveData rejected symbol "${ticker}": ${message}`, {
+ status: 400,
+ code: 'INVALID_SYMBOL',
+ });
}
return [];
}
@@ -1286,4 +1306,17 @@ export class MarketDataService {
}
}
+class MarketDataError extends Error {
+ status: number;
+ code?: string;
+
+ constructor(message: string, options?: { status?: number; code?: string }) {
+ super(message);
+ this.status = options?.status ?? 500;
+ this.code = options?.code;
+ this.name = 'MarketDataError';
+ }
+}
+
+export { MarketDataError };
export type { BuildContextParams };
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/marketTypes.ts b/apps/Cortensor-Price-Analyzer/src/lib/marketTypes.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/marketTypes.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/marketTypes.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/newsService.ts b/apps/Cortensor-Price-Analyzer/src/lib/newsService.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/newsService.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/newsService.ts
diff --git a/apps/Cortensor-Price-Analyzer/src/lib/snapshotStore.ts b/apps/Cortensor-Price-Analyzer/src/lib/snapshotStore.ts
new file mode 100644
index 0000000..d39911a
--- /dev/null
+++ b/apps/Cortensor-Price-Analyzer/src/lib/snapshotStore.ts
@@ -0,0 +1,93 @@
+import type {
+ CategorySnapshot,
+ MarketTickerItem,
+ QuoteProvider,
+ WatchlistKey,
+} from '@/app/api/market-tickers/route';
+import { snapshotDb } from './db/client';
+
+const INSERT_SNAPSHOT = snapshotDb.prepare(`
+ INSERT INTO market_snapshots (category, provider, payload, refreshed_at)
+ VALUES (@category, @provider, @payload, @refreshedAt)
+`);
+
+const SELECT_LATEST = snapshotDb.prepare(`
+ SELECT provider, payload, refreshed_at AS refreshedAt, created_at AS createdAt
+ FROM market_snapshots
+ WHERE category = @category
+ ORDER BY created_at DESC
+ LIMIT 1
+`);
+
+export type PersistedSnapshot = {
+ category: WatchlistKey;
+ provider: QuoteProvider;
+ items: MarketTickerItem[];
+ refreshedAt: string | null;
+ createdAt: string;
+};
+
+class SnapshotStore {
+ saveSnapshot(category: WatchlistKey, snapshot: Pick): void {
+ try {
+ INSERT_SNAPSHOT.run({
+ category,
+ provider: snapshot.provider,
+ payload: JSON.stringify(snapshot.items),
+ refreshedAt: snapshot.refreshedAt ?? null,
+ });
+ } catch (error) {
+ console.error('Failed to persist market snapshot', error);
+ }
+ }
+
+ getLatestSnapshot(category: WatchlistKey): PersistedSnapshot | null {
+ try {
+ const row = SELECT_LATEST.get({ category }) as
+ | { provider: string; payload: string; refreshedAt: string | null; createdAt: string }
+ | undefined;
+ if (!row) {
+ return null;
+ }
+ return {
+ category,
+ provider: row.provider as QuoteProvider,
+ items: parseItems(row.payload),
+ refreshedAt: row.refreshedAt ?? null,
+ createdAt: row.createdAt,
+ };
+ } catch (error) {
+ console.error('Failed to load market snapshot', error);
+ return null;
+ }
+ }
+
+ getSnapshotWithinTtl(category: WatchlistKey, ttlMs: number): PersistedSnapshot | null {
+ const snapshot = this.getLatestSnapshot(category);
+ if (!snapshot) {
+ return null;
+ }
+
+ return isWithinTtl(snapshot.createdAt, ttlMs) ? snapshot : null;
+ }
+}
+
+function parseItems(payload: string): MarketTickerItem[] {
+ try {
+ const parsed = JSON.parse(payload);
+ return Array.isArray(parsed) ? (parsed as MarketTickerItem[]) : [];
+ } catch (error) {
+ console.error('Failed to parse snapshot payload', error);
+ return [];
+ }
+}
+
+function isWithinTtl(createdAtIso: string, ttlMs: number): boolean {
+ const createdAt = Date.parse(createdAtIso);
+ if (!Number.isFinite(createdAt)) {
+ return false;
+ }
+ return Date.now() - createdAt <= ttlMs;
+}
+
+export const snapshotStore = new SnapshotStore();
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/urlFetcher.ts b/apps/Cortensor-Price-Analyzer/src/lib/urlFetcher.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/urlFetcher.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/urlFetcher.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/utils.ts b/apps/Cortensor-Price-Analyzer/src/lib/utils.ts
similarity index 100%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/src/lib/utils.ts
rename to apps/Cortensor-Price-Analyzer/src/lib/utils.ts
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/tsconfig.json b/apps/Cortensor-Price-Analyzer/tsconfig.json
similarity index 56%
rename from apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/tsconfig.json
rename to apps/Cortensor-Price-Analyzer/tsconfig.json
index c133409..b575f7d 100644
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/tsconfig.json
+++ b/apps/Cortensor-Price-Analyzer/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -19,9 +23,19 @@
}
],
"paths": {
- "@/*": ["./src/*"]
+ "@/*": [
+ "./src/*"
+ ]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/apps/Cortensor-Research-Summarizer/.gitignore b/apps/Cortensor-Research-Summarizer/.gitignore
index 4447703..4578373 100644
--- a/apps/Cortensor-Research-Summarizer/.gitignore
+++ b/apps/Cortensor-Research-Summarizer/.gitignore
@@ -9,6 +9,8 @@
!.yarn/plugins
!.yarn/releases
!.yarn/versions
+/.turbo
+/.cache
# testing
/coverage
@@ -23,6 +25,29 @@
# misc
.DS_Store
*.pem
+*.key
+*.p8
+*.p12
+*.pfx
+*.cer
+*.crt
+*.csr
+*.der
+*.jks
+*.keystore
+.npmrc
+.yarnrc*
+*.pid
+*.pid.lock
+*.log
+*.sqlite*
+tmp/
+logs/
+*.swp
+*.swo
+*.bak
+*.orig
+.envrc
# debug
npm-debug.log*
@@ -33,6 +58,7 @@ yarn-error.log*
# local env files
.env*.local
.env
+.env.*
# vercel
.vercel
diff --git a/apps/Cortensor-Research-Summarizer/eslint.config.mjs b/apps/Cortensor-Research-Summarizer/eslint.config.mjs
index 719cea2..e29b739 100644
--- a/apps/Cortensor-Research-Summarizer/eslint.config.mjs
+++ b/apps/Cortensor-Research-Summarizer/eslint.config.mjs
@@ -1,16 +1,7 @@
-import { dirname } from "path";
-import { fileURLToPath } from "url";
-import { FlatCompat } from "@eslint/eslintrc";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-const compat = new FlatCompat({
- baseDirectory: __dirname,
-});
+import nextCoreWebVitals from "eslint-config-next/core-web-vitals";
const eslintConfig = [
- ...compat.extends("next/core-web-vitals", "next/typescript"),
+ ...nextCoreWebVitals,
{
ignores: [
"node_modules/**",
diff --git a/apps/Cortensor-Research-Summarizer/package-lock.json b/apps/Cortensor-Research-Summarizer/package-lock.json
index 629e7c7..1a5f246 100644
--- a/apps/Cortensor-Research-Summarizer/package-lock.json
+++ b/apps/Cortensor-Research-Summarizer/package-lock.json
@@ -17,8 +17,10 @@
"cheerio": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "dommatrix": "^0.1.1",
"lucide-react": "^0.545.0",
- "next": "15.5.4",
+ "next": "^16.0.7",
+ "pdf-parse": "^2.2.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1"
@@ -30,7 +32,7 @@
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
- "eslint-config-next": "15.5.4",
+ "eslint-config-next": "^16.0.7",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
"typescript": "^5"
@@ -49,6 +51,279 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/@babel/code-frame": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
+ "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz",
+ "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
+ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-compilation-targets": "^7.27.2",
+ "@babel/helper-module-transforms": "^7.28.3",
+ "@babel/helpers": "^7.28.4",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz",
+ "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.5",
+ "@babel/types": "^7.28.5",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
+ "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.27.2",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+ "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.28.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz",
+ "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.27.1",
+ "@babel/traverse": "^7.28.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz",
+ "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz",
+ "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.5"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.27.2",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
+ "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/parser": "^7.27.2",
+ "@babel/types": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
+ "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.27.1",
+ "@babel/generator": "^7.28.5",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.28.5",
+ "@babel/template": "^7.27.2",
+ "@babel/types": "^7.28.5",
+ "debug": "^4.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz",
+ "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@emnapi/core": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz",
@@ -769,6 +1044,191 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
+ "node_modules/@napi-rs/canvas": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.81.tgz",
+ "integrity": "sha512-ReCjd5SYI/UKx/olaQLC4GtN6wUQGjlgHXs1lvUvWGXfBMR3Fxnik3cL+OxKN5ithNdoU0/GlCrdKcQDFh2XKQ==",
+ "license": "MIT",
+ "optional": true,
+ "workspaces": [
+ "e2e/*"
+ ],
+ "engines": {
+ "node": ">= 10"
+ },
+ "optionalDependencies": {
+ "@napi-rs/canvas-android-arm64": "0.1.81",
+ "@napi-rs/canvas-darwin-arm64": "0.1.81",
+ "@napi-rs/canvas-darwin-x64": "0.1.81",
+ "@napi-rs/canvas-linux-arm-gnueabihf": "0.1.81",
+ "@napi-rs/canvas-linux-arm64-gnu": "0.1.81",
+ "@napi-rs/canvas-linux-arm64-musl": "0.1.81",
+ "@napi-rs/canvas-linux-riscv64-gnu": "0.1.81",
+ "@napi-rs/canvas-linux-x64-gnu": "0.1.81",
+ "@napi-rs/canvas-linux-x64-musl": "0.1.81",
+ "@napi-rs/canvas-win32-x64-msvc": "0.1.81"
+ }
+ },
+ "node_modules/@napi-rs/canvas-android-arm64": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.81.tgz",
+ "integrity": "sha512-78Lz+AUi+MsWupyZjXwpwQrp1QCwncPvRZrdvrROcZ9Gq9grP7LfQZiGdR8LKyHIq3OR18mDP+JESGT15V1nXw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-darwin-arm64": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.81.tgz",
+ "integrity": "sha512-omejuKgHWKDGoh8rsgsyhm/whwxMaryTQjJTd9zD7hiB9/rzcEEJLHnzXWR5ysy4/tTjHaQotE6k2t8eodTLnA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-darwin-x64": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.81.tgz",
+ "integrity": "sha512-EYfk+co6BElq5DXNH9PBLYDYwc4QsvIVbyrsVHsxVpn4p6Y3/s8MChgC69AGqj3vzZBQ1qx2CRCMtg5cub+XuQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.81.tgz",
+ "integrity": "sha512-teh6Q74CyAcH31yLNQGR9MtXSFxlZa5CI6vvNUISI14gWIJWrhOwUAOly+KRe1aztWR0FWTVSPxM4p5y+06aow==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-arm64-gnu": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.81.tgz",
+ "integrity": "sha512-AGEopHFYRzJOjxY+2G1RmHPRnuWvO3Qdhq7sIazlSjxb3Z6dZHg7OB/4ZimXaimPjDACm9qWa6t5bn9bhXvkcw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-arm64-musl": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.81.tgz",
+ "integrity": "sha512-Bj3m1cl4GIhsigkdwOxii4g4Ump3/QhNpx85IgAlCCYXpaly6mcsWpuDYEabfIGWOWhDUNBOndaQUPfWK1czOQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-riscv64-gnu": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.81.tgz",
+ "integrity": "sha512-yg/5NkHykVdwPlD3XObwCa/EswkOwLHswJcI9rHrac+znHsmCSj5AMX/RTU9Z9F6lZTwL60JM2Esit33XhAMiw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-x64-gnu": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.81.tgz",
+ "integrity": "sha512-tPfMpSEBuV5dJSKexO/UZxpOqnYTaNbG8aKa1ek8QsWu+4SJ/foWkaxscra/RUv85vepx6WWDjzBNbNJsTnO0w==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-linux-x64-musl": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.81.tgz",
+ "integrity": "sha512-1L0xnYgzqn8Baef+inPvY4dKqdmw3KCBoe0NEDgezuBZN7MA5xElwifoG8609uNdrMtJ9J6QZarsslLRVqri7g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@napi-rs/canvas-win32-x64-msvc": {
+ "version": "0.1.81",
+ "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.81.tgz",
+ "integrity": "sha512-57ryVbhm/z7RE9/UVcS7mrLPdlayLesy+9U0Uf6epCoeSGrs99tfieCcgZWFbIgmByQ1AZnNtFI2N6huqDLlWQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
@@ -783,15 +1243,15 @@
}
},
"node_modules/@next/env": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-15.5.4.tgz",
- "integrity": "sha512-27SQhYp5QryzIT5uO8hq99C69eLQ7qkzkDPsk3N+GuS2XgOgoYEeOav7Pf8Tn4drECOVDsDg8oj+/DVy8qQL2A==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.7.tgz",
+ "integrity": "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==",
"license": "MIT"
},
"node_modules/@next/eslint-plugin-next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.5.4.tgz",
- "integrity": "sha512-SR1vhXNNg16T4zffhJ4TS7Xn7eq4NfKfcOsRwea7RIAHrjRpI9ALYbamqIJqkAhowLlERffiwk0FMvTLNdnVtw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.7.tgz",
+ "integrity": "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -799,9 +1259,9 @@
}
},
"node_modules/@next/swc-darwin-arm64": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.5.4.tgz",
- "integrity": "sha512-nopqz+Ov6uvorej8ndRX6HlxCYWCO3AHLfKK2TYvxoSB2scETOcfm/HSS3piPqc3A+MUgyHoqE6je4wnkjfrOA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.7.tgz",
+ "integrity": "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==",
"cpu": [
"arm64"
],
@@ -815,9 +1275,9 @@
}
},
"node_modules/@next/swc-darwin-x64": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.5.4.tgz",
- "integrity": "sha512-QOTCFq8b09ghfjRJKfb68kU9k2K+2wsC4A67psOiMn849K9ZXgCSRQr0oVHfmKnoqCbEmQWG1f2h1T2vtJJ9mA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.7.tgz",
+ "integrity": "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==",
"cpu": [
"x64"
],
@@ -831,9 +1291,9 @@
}
},
"node_modules/@next/swc-linux-arm64-gnu": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.5.4.tgz",
- "integrity": "sha512-eRD5zkts6jS3VfE/J0Kt1VxdFqTnMc3QgO5lFE5GKN3KDI/uUpSyK3CjQHmfEkYR4wCOl0R0XrsjpxfWEA++XA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.7.tgz",
+ "integrity": "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==",
"cpu": [
"arm64"
],
@@ -847,9 +1307,9 @@
}
},
"node_modules/@next/swc-linux-arm64-musl": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.5.4.tgz",
- "integrity": "sha512-TOK7iTxmXFc45UrtKqWdZ1shfxuL4tnVAOuuJK4S88rX3oyVV4ZkLjtMT85wQkfBrOOvU55aLty+MV8xmcJR8A==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.7.tgz",
+ "integrity": "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==",
"cpu": [
"arm64"
],
@@ -863,9 +1323,9 @@
}
},
"node_modules/@next/swc-linux-x64-gnu": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.5.4.tgz",
- "integrity": "sha512-7HKolaj+481FSW/5lL0BcTkA4Ueam9SPYWyN/ib/WGAFZf0DGAN8frNpNZYFHtM4ZstrHZS3LY3vrwlIQfsiMA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.7.tgz",
+ "integrity": "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==",
"cpu": [
"x64"
],
@@ -879,9 +1339,9 @@
}
},
"node_modules/@next/swc-linux-x64-musl": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.5.4.tgz",
- "integrity": "sha512-nlQQ6nfgN0nCO/KuyEUwwOdwQIGjOs4WNMjEUtpIQJPR2NUfmGpW2wkJln1d4nJ7oUzd1g4GivH5GoEPBgfsdw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.7.tgz",
+ "integrity": "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==",
"cpu": [
"x64"
],
@@ -895,9 +1355,9 @@
}
},
"node_modules/@next/swc-win32-arm64-msvc": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.5.4.tgz",
- "integrity": "sha512-PcR2bN7FlM32XM6eumklmyWLLbu2vs+D7nJX8OAIoWy69Kef8mfiN4e8TUv2KohprwifdpFKPzIP1njuCjD0YA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.7.tgz",
+ "integrity": "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==",
"cpu": [
"arm64"
],
@@ -911,9 +1371,9 @@
}
},
"node_modules/@next/swc-win32-x64-msvc": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.5.4.tgz",
- "integrity": "sha512-1ur2tSHZj8Px/KMAthmuI9FMp/YFusMMGoRNJaRZMOlSkgvLjzosSdQI0cJAKogdHl3qXUQKL9MGaYvKwA7DXg==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.7.tgz",
+ "integrity": "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==",
"cpu": [
"x64"
],
@@ -1122,13 +1582,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@rushstack/eslint-patch": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.13.0.tgz",
- "integrity": "sha512-2ih5qGw5SZJ+2fLZxP6Lr6Na2NTIgPRL/7Kmyuw0uIyBQnuhQ8fi8fzUTd38eIQmqp+GYLC00cI6WgtqHxBwmw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@swc/helpers": {
"version": "0.5.15",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1485,17 +1938,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.0.tgz",
- "integrity": "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz",
+ "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/type-utils": "8.46.0",
- "@typescript-eslint/utils": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/type-utils": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
@@ -1509,7 +1962,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^8.46.0",
+ "@typescript-eslint/parser": "^8.48.1",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
@@ -1525,16 +1978,16 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.0.tgz",
- "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz",
+ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1550,14 +2003,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.0.tgz",
- "integrity": "sha512-OEhec0mH+U5Je2NZOeK1AbVCdm0ChyapAyTeXVIYTPXDJ3F07+cu87PPXcGoYqZ7M9YJVvFnfpGg1UmCIqM+QQ==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz",
+ "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.46.0",
- "@typescript-eslint/types": "^8.46.0",
+ "@typescript-eslint/tsconfig-utils": "^8.48.1",
+ "@typescript-eslint/types": "^8.48.1",
"debug": "^4.3.4"
},
"engines": {
@@ -1572,14 +2025,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.0.tgz",
- "integrity": "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz",
+ "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0"
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1590,9 +2043,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.0.tgz",
- "integrity": "sha512-WrYXKGAHY836/N7zoK/kzi6p8tXFhasHh8ocFL9VZSAkvH956gfeRfcnhs3xzRy8qQ/dq3q44v1jvQieMFg2cw==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz",
+ "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1607,15 +2060,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.0.tgz",
- "integrity": "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz",
+ "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0",
- "@typescript-eslint/utils": "8.46.0",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@@ -1632,9 +2085,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.0.tgz",
- "integrity": "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz",
+ "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1646,21 +2099,20 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.0.tgz",
- "integrity": "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz",
+ "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.46.0",
- "@typescript-eslint/tsconfig-utils": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/visitor-keys": "8.46.0",
+ "@typescript-eslint/project-service": "8.48.1",
+ "@typescript-eslint/tsconfig-utils": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/visitor-keys": "8.48.1",
"debug": "^4.3.4",
- "fast-glob": "^3.3.2",
- "is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
+ "tinyglobby": "^0.2.15",
"ts-api-utils": "^2.1.0"
},
"engines": {
@@ -1684,36 +2136,6 @@
"balanced-match": "^1.0.0"
}
},
- "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
@@ -1731,16 +2153,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.0.tgz",
- "integrity": "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz",
+ "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.46.0",
- "@typescript-eslint/types": "8.46.0",
- "@typescript-eslint/typescript-estree": "8.46.0"
+ "@typescript-eslint/scope-manager": "8.48.1",
+ "@typescript-eslint/types": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -1755,13 +2177,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.46.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.0.tgz",
- "integrity": "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q==",
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz",
+ "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.46.0",
+ "@typescript-eslint/types": "8.48.1",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -2351,6 +2773,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.9.4",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz",
+ "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
@@ -2381,6 +2813,40 @@
"node": ">=8"
}
},
+ "node_modules/browserslist": {
+ "version": "4.28.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+ "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "baseline-browser-mapping": "^2.9.0",
+ "caniuse-lite": "^1.0.30001759",
+ "electron-to-chromium": "^1.5.263",
+ "node-releases": "^2.0.27",
+ "update-browserslist-db": "^1.2.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -2441,9 +2907,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001749",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz",
- "integrity": "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==",
+ "version": "1.0.30001759",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz",
+ "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==",
"funding": [
{
"type": "opencollective",
@@ -2595,6 +3061,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2840,6 +3313,12 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
+ "node_modules/dommatrix": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-0.1.1.tgz",
+ "integrity": "sha512-45CQT2bjnN9DXF07PXgG7hfQ2r8a6trrupNuTizRzfLHWWujdebAx8Xry0CB5uVBQlQY/m0TE/Whe5nrua+lsQ==",
+ "license": "MIT"
+ },
"node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
@@ -2868,6 +3347,13 @@
"node": ">= 0.4"
}
},
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.266",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz",
+ "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
@@ -3087,6 +3573,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3162,25 +3658,24 @@
}
},
"node_modules/eslint-config-next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.5.4.tgz",
- "integrity": "sha512-BzgVVuT3kfJes8i2GHenC1SRJ+W3BTML11lAOYFOOPzrk2xp66jBOAGEFRw+3LkYCln5UzvFsLhojrshb5Zfaw==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.7.tgz",
+ "integrity": "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "15.5.4",
- "@rushstack/eslint-patch": "^1.10.3",
- "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
- "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@next/eslint-plugin-next": "16.0.7",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.0",
"eslint-plugin-react": "^7.37.0",
- "eslint-plugin-react-hooks": "^5.0.0"
+ "eslint-plugin-react-hooks": "^7.0.0",
+ "globals": "16.4.0",
+ "typescript-eslint": "^8.46.0"
},
"peerDependencies": {
- "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0",
+ "eslint": ">=9.0.0",
"typescript": ">=3.3.1"
},
"peerDependenciesMeta": {
@@ -3189,6 +3684,19 @@
}
}
},
+ "node_modules/eslint-config-next/node_modules/globals": {
+ "version": "16.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
+ "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -3392,13 +3900,20 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
- "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
+ "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.25.0 || ^4.0.0",
+ "zod-validation-error": "^3.5.0 || ^4.0.0"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"peerDependencies": {
"eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
@@ -3753,6 +4268,16 @@
"node": ">= 0.4"
}
},
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -3981,6 +4506,23 @@
"node": ">= 0.4"
}
},
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
"node_modules/htmlparser2": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
@@ -4540,6 +5082,19 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/jsesc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -4909,6 +5464,23 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lru-cache/node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/lucide-react": {
"version": "0.545.0",
"resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.545.0.tgz",
@@ -5077,12 +5649,12 @@
"license": "MIT"
},
"node_modules/next": {
- "version": "15.5.4",
- "resolved": "https://registry.npmjs.org/next/-/next-15.5.4.tgz",
- "integrity": "sha512-xH4Yjhb82sFYQfY3vbkJfgSDgXvBB6a8xPs9i35k6oZJRoQRihZH+4s9Yo2qsWpzBmZ3lPXaJ2KPXLfkvW4LnA==",
+ "version": "16.0.7",
+ "resolved": "https://registry.npmjs.org/next/-/next-16.0.7.tgz",
+ "integrity": "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==",
"license": "MIT",
"dependencies": {
- "@next/env": "15.5.4",
+ "@next/env": "16.0.7",
"@swc/helpers": "0.5.15",
"caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
@@ -5092,18 +5664,18 @@
"next": "dist/bin/next"
},
"engines": {
- "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
+ "node": ">=20.9.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "15.5.4",
- "@next/swc-darwin-x64": "15.5.4",
- "@next/swc-linux-arm64-gnu": "15.5.4",
- "@next/swc-linux-arm64-musl": "15.5.4",
- "@next/swc-linux-x64-gnu": "15.5.4",
- "@next/swc-linux-x64-musl": "15.5.4",
- "@next/swc-win32-arm64-msvc": "15.5.4",
- "@next/swc-win32-x64-msvc": "15.5.4",
- "sharp": "^0.34.3"
+ "@next/swc-darwin-arm64": "16.0.7",
+ "@next/swc-darwin-x64": "16.0.7",
+ "@next/swc-linux-arm64-gnu": "16.0.7",
+ "@next/swc-linux-arm64-musl": "16.0.7",
+ "@next/swc-linux-x64-gnu": "16.0.7",
+ "@next/swc-linux-x64-musl": "16.0.7",
+ "@next/swc-win32-arm64-msvc": "16.0.7",
+ "@next/swc-win32-x64-msvc": "16.0.7",
+ "sharp": "^0.34.4"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
@@ -5156,6 +5728,13 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/node-releases": {
+ "version": "2.0.27",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz",
+ "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
@@ -5448,6 +6027,30 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/pdf-parse": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/pdf-parse/-/pdf-parse-2.2.2.tgz",
+ "integrity": "sha512-0wPEWpTRfvtjh8u+b0QVt9/NAUJFi/KetVm/S+tKucGjpqRL6LfXzH2o21NNvx5JkCReHJcBOHW8aq89QbcoUA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "pdfjs-dist": "^5.4.296"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/pdfjs-dist": {
+ "version": "5.4.394",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.4.394.tgz",
+ "integrity": "sha512-9ariAYGqUJzx+V/1W4jHyiyCep6IZALmDzoaTLZ6VNu8q9LWi1/ukhzHgE2Xsx96AZi0mbZuK4/ttIbqSbLypg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=20.16.0 || >=22.3.0"
+ },
+ "optionalDependencies": {
+ "@napi-rs/canvas": "^0.1.81"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -6455,6 +7058,30 @@
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.48.1",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz",
+ "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.48.1",
+ "@typescript-eslint/parser": "8.48.1",
+ "@typescript-eslint/typescript-estree": "8.48.1",
+ "@typescript-eslint/utils": "8.48.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
@@ -6524,6 +7151,37 @@
"@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
}
},
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz",
+ "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -6692,6 +7350,29 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "4.1.13",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz",
+ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zod-validation-error": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
+ "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.25.0 || ^4.0.0"
+ }
}
}
}
diff --git a/apps/Cortensor-Research-Summarizer/package.json b/apps/Cortensor-Research-Summarizer/package.json
index 89c7417..5617475 100644
--- a/apps/Cortensor-Research-Summarizer/package.json
+++ b/apps/Cortensor-Research-Summarizer/package.json
@@ -18,8 +18,10 @@
"cheerio": "^1.1.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "dommatrix": "^0.1.1",
"lucide-react": "^0.545.0",
- "next": "15.5.4",
+ "next": "^16.0.7",
+ "pdf-parse": "^2.2.2",
"react": "19.1.0",
"react-dom": "19.1.0",
"tailwind-merge": "^3.3.1"
@@ -31,7 +33,7 @@
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
- "eslint-config-next": "15.5.4",
+ "eslint-config-next": "^16.0.7",
"tailwindcss": "^4",
"tw-animate-css": "^1.4.0",
"typescript": "^5"
diff --git a/apps/Cortensor-Research-Summarizer/public/file.svg b/apps/Cortensor-Research-Summarizer/public/file.svg
new file mode 100644
index 0000000..004145c
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/public/file.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Research-Summarizer/public/globe.svg b/apps/Cortensor-Research-Summarizer/public/globe.svg
new file mode 100644
index 0000000..567f17b
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/public/globe.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Research-Summarizer/public/next.svg b/apps/Cortensor-Research-Summarizer/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Research-Summarizer/public/vercel.svg b/apps/Cortensor-Research-Summarizer/public/vercel.svg
new file mode 100644
index 0000000..7705396
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Research-Summarizer/public/window.svg b/apps/Cortensor-Research-Summarizer/public/window.svg
new file mode 100644
index 0000000..b2b2a44
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/public/window.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/apps/Cortensor-Research-Summarizer/src/app/api/news/route.ts b/apps/Cortensor-Research-Summarizer/src/app/api/news/route.ts
new file mode 100644
index 0000000..b56fd00
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/src/app/api/news/route.ts
@@ -0,0 +1,17 @@
+import { NextResponse } from 'next/server';
+import { fetchNews } from '@/lib/newsService';
+
+type Category = 'general' | 'technology' | 'science' | 'random';
+
+export async function GET(request: Request) {
+ const { searchParams } = new URL(request.url);
+ const category = (searchParams.get('category') as Category) || 'general';
+
+ try {
+ const items = await fetchNews(category);
+ return NextResponse.json({ items, category });
+ } catch (error) {
+ console.error('news route error', error);
+ return NextResponse.json({ items: [], category, error: 'Failed to load news' }, { status: 500 });
+ }
+}
diff --git a/apps/Cortensor-Research-Summarizer/src/app/api/summarize/route.ts b/apps/Cortensor-Research-Summarizer/src/app/api/summarize/route.ts
index 497b69e..76521c9 100644
--- a/apps/Cortensor-Research-Summarizer/src/app/api/summarize/route.ts
+++ b/apps/Cortensor-Research-Summarizer/src/app/api/summarize/route.ts
@@ -111,9 +111,18 @@ function processSummaryResponse(summaryData: { summary?: string; keyPoints?: str
return { summary, keyPoints, wordCount, wasEnriched };
}
+function buildClientReference(rawUserId: unknown): string {
+ const raw = typeof rawUserId === 'string' ? rawUserId.trim() : '';
+ const cleaned = raw.replace(/[^a-zA-Z0-9_-]/g, '');
+ const baseId = cleaned.length > 0
+ ? cleaned
+ : `session-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
+ return baseId.startsWith('user-summarizer-') ? baseId : `user-summarizer-${baseId}`;
+}
+
export async function POST(request: NextRequest) {
try {
- const { url } = await request.json();
+ const { url, userId } = await request.json();
if (!url) {
return NextResponse.json({ error: 'URL is required' }, { status: 400 });
@@ -121,6 +130,9 @@ export async function POST(request: NextRequest) {
console.log('Processing URL:', url);
+ const clientReference = buildClientReference(userId);
+ console.log('Using client reference:', clientReference);
+
const urlFetcher = new URLFetcher();
const article = await urlFetcher.fetchArticle(url);
@@ -145,10 +157,14 @@ export async function POST(request: NextRequest) {
let summaryResult;
try {
- summaryResult = await cortensorService.generateSummary(article);
+ summaryResult = await cortensorService.generateSummary(article, clientReference);
if (summaryResult.needsEnrichment && searchResults.length > 0) {
- summaryResult = await cortensorService.enrichSummary(summaryResult, searchResults);
+ summaryResult = await cortensorService.enrichSummary(
+ summaryResult,
+ searchResults,
+ `${clientReference}-enrich`
+ );
}
} catch (error) {
@@ -170,7 +186,12 @@ export async function POST(request: NextRequest) {
summary: processedSummary.summary,
keyPoints: processedSummary.keyPoints,
wordCount: processedSummary.wordCount,
- wasEnriched: processedSummary.wasEnriched
+ wasEnriched: processedSummary.wasEnriched,
+ needsEnrichment: summaryResult.needsEnrichment,
+ contentTruncated: summaryResult.sourceTruncated ?? false,
+ originalContentLength: summaryResult.originalContentLength ?? article.content.length,
+ submittedContentLength: summaryResult.submittedContentLength ?? article.content.length,
+ compressionMethod: summaryResult.compressionMethod ?? 'pass-through'
}
});
diff --git a/apps/Cortensor-Research-Summarizer/src/components/HistoryPanel.tsx b/apps/Cortensor-Research-Summarizer/src/components/HistoryPanel.tsx
index 2b7ca7e..e8ec3f0 100644
--- a/apps/Cortensor-Research-Summarizer/src/components/HistoryPanel.tsx
+++ b/apps/Cortensor-Research-Summarizer/src/components/HistoryPanel.tsx
@@ -12,7 +12,6 @@ import {
Search,
Trash2,
ExternalLink,
- Calendar,
User,
FileText,
RotateCcw,
@@ -171,7 +170,11 @@ export function HistoryPanel({ onLoadHistoryItem, onHistoryChange, className }:
) : (
<>
- No summaries found matching "{searchQuery}"
+
+ No summaries found matching “
+ {searchQuery}
+ ”
+
('general');
+ const [items, setItems] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ const loadNews = async (category: Category) => {
+ setLoading(true);
+ setError(null);
+ try {
+ const res = await fetch(`/api/news?category=${category}&t=${Date.now()}`);
+ if (!res.ok) throw new Error('Gagal memuat berita');
+ const data = await res.json();
+ setItems(Array.isArray(data.items) ? data.items : []);
+ } catch (err) {
+ setError(err instanceof Error ? err.message : 'Terjadi kesalahan');
+ setItems([]);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ loadNews(activeCategory);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [activeCategory]);
+
+ return (
+
+
+
+
+
+
+ News & Articles
+
+
+ Quick curation for research ideas and fresh trends.
+
+
+
loadNews(activeCategory)} disabled={loading}>
+ {loading ? : 'Refresh'}
+
+
+
+ {categories.map((cat) => (
+ setActiveCategory(cat.id)}
+ >
+
+ {cat.label}
+
+ ))}
+
+
+
+ {loading ? (
+
+
+ Loading…
+
+ ) : error ? (
+ {error}
+ ) : items.length === 0 ? (
+ No data.
+ ) : (
+
+ {items.map((item, idx) => (
+
+
+
+
+ {item.title}
+
+ {item.description && (
+
{item.description}
+ )}
+
+ {String(item.source)}
+ {item.publishedAt && {new Date(item.publishedAt).toLocaleDateString()}}
+ {item.category && {item.category}}
+
+
+
+
+ ))}
+
+
+ Sources: NewsAPI / GNews / Mediastack / HN / Dev.to / Reddit / NASA / arXiv / Wikipedia.
+
+
+ )}
+
+
+ );
+}
diff --git a/apps/Cortensor-Research-Summarizer/src/components/SummarizerForm.tsx b/apps/Cortensor-Research-Summarizer/src/components/SummarizerForm.tsx
index 110d526..933d0e2 100644
--- a/apps/Cortensor-Research-Summarizer/src/components/SummarizerForm.tsx
+++ b/apps/Cortensor-Research-Summarizer/src/components/SummarizerForm.tsx
@@ -10,7 +10,8 @@ import { Progress } from '@/components/ui/progress';
import { cn } from '@/lib/utils';
import { HistoryService, HistoryItem } from '@/lib/historyService';
import { HistoryPanel } from '@/components/HistoryPanel';
-import {
+import { NewsPanel } from '@/components/NewsPanel';
+import {
Loader2,
ExternalLink,
Globe,
@@ -29,8 +30,10 @@ import {
Brain,
Lightbulb,
History,
- PanelRightOpen,
- PanelRightClose
+ PanelRightClose,
+ Scissors,
+ Minimize2,
+ Newspaper
} from 'lucide-react';
interface SummaryResult {
@@ -46,6 +49,11 @@ interface SummaryResult {
keyPoints: string[];
wordCount: number;
wasEnriched?: boolean;
+ needsEnrichment?: boolean;
+ contentTruncated?: boolean;
+ originalContentLength?: number;
+ submittedContentLength?: number;
+ compressionMethod?: 'pass-through' | 'extractive-summary' | 'truncate';
}
interface LoadingStep {
@@ -57,13 +65,43 @@ interface LoadingStep {
duration?: string;
}
+const USER_ID_STORAGE_KEY = 'research-summarizer:user-id';
+
+const generateUserId = (): string => {
+ if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
+ return crypto.randomUUID().replace(/-/g, '').slice(0, 12);
+ }
+ return Math.random().toString(36).slice(2, 14);
+};
+
+const getOrCreateUserId = (): string | null => {
+ if (typeof window === 'undefined') {
+ return null;
+ }
+ try {
+ const existing = window.localStorage.getItem(USER_ID_STORAGE_KEY);
+ if (existing && existing.trim().length > 0) {
+ return existing;
+ }
+ const newId = generateUserId();
+ window.localStorage.setItem(USER_ID_STORAGE_KEY, newId);
+ return newId;
+ } catch (error) {
+ console.error('User ID initialization failed:', error);
+ return null;
+ }
+};
+
export default function SummarizerForm() {
+ const [userId, setUserId] = useState(null);
const [url, setUrl] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [result, setResult] = useState(null);
const [error, setError] = useState(null);
const [progress, setProgress] = useState(0);
- const [showHistory, setShowHistory] = useState(false);
+ const [showSidePanel, setShowSidePanel] = useState(true);
+ const [showHistoryPanel, setShowHistoryPanel] = useState(true);
+ const [showNewsPanel, setShowNewsPanel] = useState(true);
const [historyCount, setHistoryCount] = useState(0);
// Handle history changes
@@ -74,6 +112,10 @@ export default function SummarizerForm() {
// Load history count on component mount
useEffect(() => {
handleHistoryChange();
+ const initializedId = getOrCreateUserId();
+ if (initializedId) {
+ setUserId(initializedId);
+ }
}, []);
// Save result to history using HistoryService
@@ -281,6 +323,15 @@ export default function SummarizerForm() {
e.preventDefault();
if (!url.trim()) return;
+ const activeUserId = userId ?? getOrCreateUserId();
+ if (!activeUserId) {
+ setError('Unable to initialize your session. Please refresh and try again.');
+ return;
+ }
+ if (activeUserId !== userId) {
+ setUserId(activeUserId);
+ }
+
setIsLoading(true);
setError(null);
setResult(null);
@@ -312,7 +363,7 @@ export default function SummarizerForm() {
headers: {
'Content-Type': 'application/json',
},
- body: JSON.stringify({ url }),
+ body: JSON.stringify({ url, userId: activeUserId }),
});
if (!response.ok) {
@@ -422,7 +473,12 @@ ${result.keyPoints.map(point => `- ${point}`).join('\n')}
return (
-
+
+
+
+ {`User ID: ${userId ?? 'initializing...'}`}
+
+
{/* Header */}
@@ -436,22 +492,32 @@ ${result.keyPoints.map(point => `- ${point}`).join('\n')}
comprehensive, professional summaries with automatic quality enhancement.
- {/* History Toggle Button */}
+ {/* Side Panel Toggle */}
setShowHistory(!showHistory)}
+ onClick={() => {
+ if (showSidePanel) {
+ setShowSidePanel(false);
+ } else {
+ if (!showHistoryPanel && !showNewsPanel) {
+ setShowHistoryPanel(true);
+ setShowNewsPanel(true);
+ }
+ setShowSidePanel(true);
+ }
+ }}
className="flex items-center space-x-2 text-sm hover:bg-blue-50 transition-colors"
>
- {showHistory ? (
+ {showSidePanel ? (
<>
- Hide History
+ Hide Side Panel
>
) : (
<>
- Show Recent Summaries
+ Show Side Panel
{historyCount > 0 && (
{historyCount}
@@ -466,12 +532,12 @@ ${result.keyPoints.map(point => `- ${point}`).join('\n')}
{/* Main Content */}
{/* Main Column - Form and Results */}
{/* Input Form */}
@@ -678,7 +744,28 @@ ${result.keyPoints.map(point => `- ${point}`).join('\n')}
Enhanced with additional sources
)}
+ {result.contentTruncated && (
+
+ {result.compressionMethod === 'extractive-summary' ? (
+
+ ) : (
+
+ )}
+ {result.compressionMethod === 'extractive-summary'
+ ? 'Source compressed to fit model context limit'
+ : 'Source truncated to fit model context limit'}
+
+ )}
+ {result.contentTruncated && (
+
+ Submitted {result.submittedContentLength ?? 0} of {result.originalContentLength ?? 0} characters after
+ {result.compressionMethod === 'extractive-summary' ? ' compression' : ' truncation'} to honor the Cortensor context window.
+
+ )}
@@ -741,15 +828,56 @@ ${result.keyPoints.map(point => `- ${point}`).join('\n')}
)}
- {/* History Panel - Conditional */}
- {showHistory && (
+ {/* Side Panel - Conditional */}
+ {showSidePanel && (showHistoryPanel || showNewsPanel) && (
-
-
+
+
+ setShowHistoryPanel((v) => {
+ const next = !v;
+ if (!next && !showNewsPanel) setShowNewsPanel(true);
+ return next;
+ })}
+ >
+
+ History
+
+ setShowNewsPanel((v) => {
+ const next = !v;
+ if (!next && !showHistoryPanel) setShowHistoryPanel(true);
+ return next;
+ })}
+ >
+
+ News
+
+
+
+ {showHistoryPanel && (
+
+ )}
+
+ {showNewsPanel && (
+
+ )}
+
+ {!showHistoryPanel && !showNewsPanel && (
+
+ Pilih panel yang ingin ditampilkan.
+
+ )}
)}
diff --git a/apps/Cortensor-Research-Summarizer/src/lib/cortensorService.ts b/apps/Cortensor-Research-Summarizer/src/lib/cortensorService.ts
index d1b4ee7..72604d6 100644
--- a/apps/Cortensor-Research-Summarizer/src/lib/cortensorService.ts
+++ b/apps/Cortensor-Research-Summarizer/src/lib/cortensorService.ts
@@ -6,6 +6,11 @@ export interface SummaryResult {
keyPoints: string[];
wordCount: number;
needsEnrichment: boolean;
+ wasEnriched?: boolean;
+ sourceTruncated?: boolean;
+ originalContentLength?: number;
+ submittedContentLength?: number;
+ compressionMethod?: 'pass-through' | 'extractive-summary' | 'truncate';
}
export interface EnrichmentSource {
@@ -28,6 +33,12 @@ export class CortensorService {
private presencePenalty: number;
private frequencyPenalty: number;
private stream: boolean;
+ private maxContextTokens?: number;
+ private sessionLimitsLoaded: boolean;
+ private readonly fallbackMaxContextTokens: number;
+ private readonly promptTokenReserve: number;
+ private readonly averageCharsPerToken: number;
+ private readonly maxContentCharactersCap: number | null;
constructor() {
this.apiKey = process.env.CORTENSOR_API_KEY || '';
@@ -48,25 +59,37 @@ export class CortensorService {
this.presencePenalty = parseFloat(process.env.CORTENSOR_PRESENCE_PENALTY || '0');
this.frequencyPenalty = parseFloat(process.env.CORTENSOR_FREQUENCY_PENALTY || '0');
this.stream = process.env.CORTENSOR_STREAM === 'true';
+ this.sessionLimitsLoaded = false;
+ this.fallbackMaxContextTokens = parseInt(process.env.CORTENSOR_FALLBACK_MAX_CONTEXT_TOKENS || '5000', 10);
+ this.promptTokenReserve = parseInt(process.env.CORTENSOR_PROMPT_TOKEN_RESERVE || '1200', 10);
+ this.averageCharsPerToken = parseFloat(process.env.CORTENSOR_AVG_CHARS_PER_TOKEN || '3');
+ const configuredMaxChars = parseInt(process.env.CORTENSOR_MAX_CONTENT_CHARS || '9500', 10);
+ this.maxContentCharactersCap = Number.isFinite(configuredMaxChars) && configuredMaxChars > 0 ? configuredMaxChars : null;
if (!this.apiKey) {
throw new Error('CORTENSOR_API_KEY is required');
}
}
- async generateSummary(article: ArticleContent): Promise
{
+ async generateSummary(article: ArticleContent, clientReference?: string): Promise {
try {
- const prompt = this.createSummaryPrompt(article);
- const clientReference = `summarize-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
+ await this.ensureSessionLimits();
+
+ const truncation = this.truncateArticleContent(article.content);
+ const promptArticle: ArticleContent = { ...article, content: truncation.text };
+ const prompt = this.createSummaryPrompt(promptArticle, truncation.truncated);
+ const effectiveClientReference = clientReference ?? this.generateFallbackClientReference('summary');
+ const requestPayload = {
+ session_id: this.sessionId, // Use session_id from environment variable
+ prompt,
+ stream: this.stream,
+ timeout: this.timeout,
+ client_reference: effectiveClientReference
+ };
const response = await axios.post(
this.apiUrl,
- {
- session_id: this.sessionId, // Use session_id from environment variable
- prompt: prompt,
- stream: this.stream,
- timeout: this.timeout
- },
+ requestPayload,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`,
@@ -82,6 +105,11 @@ export class CortensorService {
// Check if summary needs enrichment
result.needsEnrichment = this.shouldEnrich(result);
+ result.wasEnriched = false;
+ result.sourceTruncated = truncation.truncated;
+ result.originalContentLength = truncation.originalLength;
+ result.submittedContentLength = truncation.submittedLength;
+ result.compressionMethod = truncation.method;
return result;
@@ -93,20 +121,23 @@ export class CortensorService {
async enrichSummary(
originalSummary: SummaryResult,
- additionalSources: EnrichmentSource[]
+ additionalSources: EnrichmentSource[],
+ clientReference?: string
): Promise {
try {
const prompt = this.createEnrichmentPrompt(originalSummary, additionalSources);
- const clientReference = `enrich-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
+ const effectiveClientReference = clientReference ?? this.generateFallbackClientReference('enrich');
+ const requestPayload = {
+ session_id: this.sessionId, // Use session_id from environment variable
+ prompt,
+ stream: this.stream,
+ timeout: this.timeout,
+ client_reference: effectiveClientReference
+ };
const response = await axios.post(
this.apiUrl,
- {
- session_id: this.sessionId, // Use session_id from environment variable
- prompt: prompt,
- stream: this.stream,
- timeout: this.timeout
- },
+ requestPayload,
{
headers: {
'Authorization': `Bearer ${this.apiKey}`,
@@ -118,7 +149,12 @@ export class CortensorService {
const enrichedText = response.data.choices?.[0]?.text || response.data.text || '';
const result = this.parseSummaryResponse(enrichedText);
result.needsEnrichment = false; // Already enriched
-
+ result.wasEnriched = true;
+ result.sourceTruncated = originalSummary.sourceTruncated;
+ result.originalContentLength = originalSummary.originalContentLength;
+ result.submittedContentLength = originalSummary.submittedContentLength;
+ result.compressionMethod = originalSummary.compressionMethod;
+
return result;
} catch (error) {
@@ -128,12 +164,22 @@ export class CortensorService {
}
}
- private createSummaryPrompt(article: ArticleContent): string {
+ private generateFallbackClientReference(label: string): string {
+ const timestampSegment = Date.now().toString(36);
+ const randomSegment = Math.random().toString(36).slice(2, 8);
+ return `user-summarizer-${label}-${timestampSegment}${randomSegment}`;
+ }
+
+ private createSummaryPrompt(article: ArticleContent, wasTruncated = false): string {
+ const truncationNotice = wasTruncated
+ ? '\n\nNOTE: Source content was truncated to fit the model\'s context window. Summarize using only the provided content.'
+ : '';
+
return `You are a professional research analyst. Analyze the following article and provide a clean, well-structured summary.
Title: ${article.title}
Source: ${article.url}
-Content: ${article.content}
+Content: ${article.content}${truncationNotice}
CRITICAL FORMATTING REQUIREMENTS:
- Write in clean, professional language
@@ -172,6 +218,293 @@ IMPORTANT: Write naturally without any special formatting, tokens, or artifacts.
Begin your professional analysis now:`;
}
+ private async ensureSessionLimits(): Promise {
+ if (this.sessionLimitsLoaded) {
+ return;
+ }
+
+ this.sessionLimitsLoaded = true;
+
+ try {
+ const discoveredLimit = await this.fetchContextLimit();
+ if (typeof discoveredLimit === 'number') {
+ this.maxContextTokens = discoveredLimit;
+ console.log('Cortensor session max context (tokens):', discoveredLimit);
+ return;
+ }
+ console.warn('Cortensor session response did not include a max context value. Falling back to 5K-token defaults.');
+ } catch (error) {
+ console.warn('Unable to fetch Cortensor session limits via HTTP. Using fallback 5K-token configuration.');
+ if (error instanceof Error) {
+ console.warn(error.message);
+ }
+ }
+ }
+
+ private async fetchContextLimit(): Promise {
+ const timeoutMs = Number.isFinite(this.timeout) ? this.timeout * 1000 : 300000;
+ const endpoints: string[] = [];
+
+ const baseUrl = this.apiUrl.endsWith('/') ? this.apiUrl.slice(0, -1) : this.apiUrl;
+ endpoints.push(`${baseUrl}/${this.sessionId}`);
+
+ const sessionsUrl = baseUrl.replace(/\/completions$/, '/sessions');
+ if (sessionsUrl !== baseUrl) {
+ endpoints.push(`${sessionsUrl}/${this.sessionId}`);
+ }
+
+ const routerUrl = baseUrl.replace(/\/completions$/, '/router');
+ if (routerUrl !== baseUrl) {
+ endpoints.push(routerUrl);
+ }
+
+ for (const url of endpoints) {
+ try {
+ const response = await axios.get(url, {
+ headers: {
+ 'Authorization': `Bearer ${this.apiKey}`,
+ 'Content-Type': 'application/json'
+ },
+ timeout: timeoutMs,
+ validateStatus: (status) => status >= 200 && status < 400
+ });
+
+ const limitFromResponse = this.extractMaxContextTokens(response.data, response.headers as Record);
+ if (typeof limitFromResponse === 'number') {
+ return limitFromResponse;
+ }
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ const status = error.response?.status;
+ if (status && [401, 403].includes(status)) {
+ throw new Error(`Authorization failed while fetching context limits (status ${status}).`);
+ }
+ if (status && [400, 404, 405, 500].includes(status)) {
+ // Expected for unsupported endpoints; try next option silently
+ continue;
+ }
+ }
+ throw error;
+ }
+ }
+
+ return null;
+ }
+
+ private extractMaxContextTokens(data: unknown, headers: Record): number | null {
+ type ContextSource = Record;
+ const sourceRecord: ContextSource = (data && typeof data === 'object') ? (data as ContextSource) : {};
+
+ const candidatePaths: Array<(source: ContextSource) => unknown> = [
+ (source) => source?.max_context_tokens,
+ (source) => source?.max_context_length,
+ (source) => source?.max_context,
+ (source) => source?.context_window,
+ (source) => (source.session as ContextSource | undefined)?.max_context_tokens,
+ (source) => (source.router as ContextSource | undefined)?.max_context_tokens,
+ () => headers['x-cortensor-max-context'],
+ () => headers['x-max-context-tokens'],
+ () => headers['x-context-window']
+ ];
+
+ for (const getValue of candidatePaths) {
+ const value = getValue(sourceRecord);
+ const parsed = this.parseNumeric(value);
+ if (parsed !== null) {
+ return parsed;
+ }
+ }
+
+ return null;
+ }
+
+ private parseNumeric(value: unknown): number | null {
+ if (typeof value === 'number' && Number.isFinite(value)) {
+ return value;
+ }
+ if (typeof value === 'string') {
+ const parsed = Number.parseInt(value, 10);
+ if (Number.isFinite(parsed)) {
+ return parsed;
+ }
+ }
+ return null;
+ }
+
+ private getMaxContextTokens(): number {
+ const limit = typeof this.maxContextTokens === 'number' && this.maxContextTokens > 0
+ ? this.maxContextTokens
+ : this.fallbackMaxContextTokens;
+ return Math.max(limit, 2048);
+ }
+
+ private getMaxContentCharacters(): number {
+ const tokenLimit = this.getMaxContextTokens();
+ const availableTokens = Math.max(tokenLimit - this.promptTokenReserve, Math.floor(tokenLimit * 0.5));
+ const approxChars = Math.floor(availableTokens * this.averageCharsPerToken);
+ const minBudget = Math.max(approxChars, 3500);
+ if (this.maxContentCharactersCap) {
+ return Math.min(minBudget, this.maxContentCharactersCap);
+ }
+ return minBudget;
+ }
+
+ private truncateArticleContent(content: string): {
+ text: string;
+ truncated: boolean;
+ originalLength: number;
+ submittedLength: number;
+ method: 'pass-through' | 'extractive-summary' | 'truncate';
+ } {
+ const originalLength = content.length;
+ const maxChars = this.getMaxContentCharacters();
+
+ if (originalLength <= maxChars) {
+ return {
+ text: content,
+ truncated: false,
+ originalLength,
+ submittedLength: originalLength,
+ method: 'pass-through'
+ };
+ }
+
+ const summary = this.buildExtractiveSummary(content, maxChars);
+ if (summary) {
+ const annotatedSummary = `${summary}\n\n[Content compressed from ${originalLength} to ${summary.length} characters to comply with model context limits.]`;
+ console.warn(`Article content compressed from ${originalLength} to ${summary.length} characters using extractive summary.`);
+ return {
+ text: annotatedSummary,
+ truncated: true,
+ originalLength,
+ submittedLength: annotatedSummary.length,
+ method: 'extractive-summary'
+ };
+ }
+
+ const excerpt = this.buildLeadingExcerpt(content, maxChars);
+ const annotatedExcerpt = `${excerpt}\n\n[Content truncated after ${excerpt.length} of ${originalLength} characters to comply with model context limits.]`;
+ console.warn(`Article content truncated from ${originalLength} to ${excerpt.length} characters as a fallback to fit context window.`);
+
+ return {
+ text: annotatedExcerpt,
+ truncated: true,
+ originalLength,
+ submittedLength: annotatedExcerpt.length,
+ method: 'truncate'
+ };
+ }
+
+ private buildExtractiveSummary(content: string, maxChars: number): string | null {
+ const normalized = content.replace(/\s+/g, ' ').trim();
+ if (normalized.length === 0) {
+ return null;
+ }
+
+ const sentenceSplitRegex = /(?<=[.!?。!?])\s+(?=[A-Z0-9])/g;
+ const sentences = normalized.split(sentenceSplitRegex).map(sentence => sentence.trim()).filter(Boolean);
+
+ if (sentences.length < 4) {
+ return null;
+ }
+
+ const stopWords = new Set([
+ 'the','is','in','at','of','a','an','and','to','for','with','on','by','from','as','that','this','it','be','are','was','were','or','but','if','then','so','than','too','very','into','about','over','after','before','between','through','during','while','because','what','which','who','whom','whose','can','could','should','would'
+ ]);
+
+ const frequencies = new Map();
+
+ const sentenceTokens = sentences.map(sentence => {
+ const tokens = sentence.toLowerCase().match(/[a-z0-9']+/g) || [];
+ return tokens.filter(token => !stopWords.has(token));
+ });
+
+ for (const tokens of sentenceTokens) {
+ for (const token of tokens) {
+ frequencies.set(token, (frequencies.get(token) || 0) + 1);
+ }
+ }
+
+ if (frequencies.size === 0) {
+ return null;
+ }
+
+ const scoredSentences = sentences.map((sentence, index) => {
+ const tokens = sentenceTokens[index];
+ const score = tokens.reduce((acc, token) => acc + (frequencies.get(token) || 0), 0);
+ const normalizedScore = tokens.length > 0 ? score / tokens.length : 0;
+ return { sentence, index, score: normalizedScore };
+ });
+
+ const sortedByScore = scoredSentences
+ .filter(item => item.sentence.length > 40)
+ .sort((a, b) => b.score - a.score);
+
+ if (sortedByScore.length === 0) {
+ return null;
+ }
+
+ const selected: typeof sortedByScore = [];
+ let currentLength = 0;
+ const targetLength = Math.max(Math.floor(maxChars * 0.75), maxChars - 2000);
+
+ for (const candidate of sortedByScore) {
+ const newLength = currentLength === 0
+ ? candidate.sentence.length
+ : currentLength + 1 + candidate.sentence.length;
+
+ if (newLength > targetLength) {
+ continue;
+ }
+
+ selected.push(candidate);
+ currentLength = newLength;
+
+ if (currentLength >= targetLength) {
+ break;
+ }
+ }
+
+ if (selected.length < 3) {
+ return null;
+ }
+
+ const ordered = selected.sort((a, b) => a.index - b.index).map(item => item.sentence);
+ const summary = ordered.join(' ');
+ return summary.length <= maxChars ? summary : summary.slice(0, maxChars);
+ }
+
+ private buildLeadingExcerpt(content: string, maxChars: number): string {
+ const sentences = content.split(/(?<=[.!?。!?])\s+/);
+ let collected = '';
+
+ for (const sentence of sentences) {
+ if (!sentence) continue;
+ const trimmedSentence = sentence.trim();
+ if (!trimmedSentence) continue;
+ const nextLength = collected.length === 0 ? trimmedSentence.length : collected.length + 1 + trimmedSentence.length;
+ if (nextLength > maxChars) {
+ break;
+ }
+ collected = collected.length === 0 ? trimmedSentence : `${collected} ${trimmedSentence}`;
+ }
+
+ if (collected.length < Math.ceil(maxChars * 0.5)) {
+ collected = content.slice(0, maxChars);
+ const lastSentenceBoundary = Math.max(
+ collected.lastIndexOf('. '),
+ collected.lastIndexOf('! '),
+ collected.lastIndexOf('? '),
+ collected.lastIndexOf('\n\n')
+ );
+ if (lastSentenceBoundary > maxChars * 0.2) {
+ collected = collected.slice(0, lastSentenceBoundary + 1);
+ }
+ }
+
+ return collected.trim();
+ }
+
private createEnrichmentPrompt(
originalSummary: SummaryResult,
sources: EnrichmentSource[]
diff --git a/apps/Cortensor-Research-Summarizer/src/lib/newsService.ts b/apps/Cortensor-Research-Summarizer/src/lib/newsService.ts
new file mode 100644
index 0000000..9d73197
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/src/lib/newsService.ts
@@ -0,0 +1,234 @@
+type Category = 'general' | 'technology' | 'science' | 'random';
+
+export interface NewsItem {
+ title: string;
+ url: string;
+ source: string;
+ publishedAt?: string;
+ category?: string;
+ description?: string;
+}
+
+const NEWS_LIMIT = 6;
+
+const getEnv = (key: string): string => process.env[key] || '';
+
+async function safeJsonFetch(url: string, init?: RequestInit): Promise {
+ try {
+ const res = await fetch(url, init);
+ if (!res.ok) return null;
+ return (await res.json()) as T;
+ } catch (error) {
+ console.warn('news fetch failed', url, error);
+ return null;
+ }
+}
+
+function normalizeSource(src: any, fallback: string): string {
+ if (!src) return fallback;
+ if (typeof src === 'string') return src;
+ if (typeof src === 'object') {
+ return src.name || src.id || src.url || fallback;
+ }
+ return fallback;
+}
+
+function mapNewsApiArticles(data: any): NewsItem[] {
+ if (!data?.articles) return [];
+ return (data.articles as any[])
+ .slice(0, NEWS_LIMIT)
+ .map((a) => ({
+ title: a.title || 'Untitled',
+ url: a.url,
+ source: normalizeSource(a.source, 'NewsAPI'),
+ publishedAt: a.publishedAt,
+ description: a.description,
+ }))
+ .filter((a) => a.url);
+}
+
+function mapGNewsArticles(data: any): NewsItem[] {
+ if (!data?.articles) return [];
+ return (data.articles as any[])
+ .slice(0, NEWS_LIMIT)
+ .map((a) => ({
+ title: a.title || 'Untitled',
+ url: a.url,
+ source: normalizeSource(a.source, 'GNews'),
+ publishedAt: a.publishedAt,
+ description: a.description,
+ }))
+ .filter((a) => a.url);
+}
+
+function mapMediastackArticles(data: any): NewsItem[] {
+ if (!data?.data) return [];
+ return (data.data as any[])
+ .slice(0, NEWS_LIMIT)
+ .map((a) => ({
+ title: a.title || 'Untitled',
+ url: a.url || a.source || '',
+ source: normalizeSource(a.source, 'Mediastack'),
+ publishedAt: a.published_at,
+ description: a.description,
+ }))
+ .filter((a) => a.url);
+}
+
+function mapHN(data: any): NewsItem[] {
+ if (!data?.hits) return [];
+ return (data.hits as any[]).slice(0, NEWS_LIMIT).map((h) => ({
+ title: h.title || 'HN story',
+ url: h.url || `https://news.ycombinator.com/item?id=${h.objectID}`,
+ source: 'Hacker News',
+ publishedAt: h.created_at,
+ }));
+}
+
+function mapReddit(data: any): NewsItem[] {
+ const children = data?.data?.children;
+ if (!children) return [];
+ return children.slice(0, NEWS_LIMIT).map((c: any) => ({
+ title: c.data?.title || 'Reddit post',
+ url: `https://reddit.com${c.data?.permalink}`,
+ source: 'r/technology',
+ publishedAt: c.data?.created_utc ? new Date(c.data.created_utc * 1000).toISOString() : undefined,
+ }));
+}
+
+function parseRssTitles(xml: string, source: string): NewsItem[] {
+ const items: NewsItem[] = [];
+ const regex = /- ([\s\S]*?)<\/item>/gim;
+ let match: RegExpExecArray | null;
+ while ((match = regex.exec(xml)) && items.length < NEWS_LIMIT) {
+ const itemXml = match[1];
+ const titleMatch = itemXml.match(/([\s\S]*?)<\/title>/i);
+ const linkMatch = itemXml.match(/([\s\S]*?)<\/link>/i);
+ if (titleMatch && linkMatch) {
+ items.push({
+ title: decode(titleMatch[1]),
+ url: decode(linkMatch[1]),
+ source,
+ });
+ }
+ }
+ return items;
+}
+
+function decode(value: string): string {
+ return value
+ .replace(//g, '$1')
+ .replace(/&/g, '&')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .trim();
+}
+
+async function fetchWikipediaRandom(): Promise {
+ const data = await safeJsonFetch('https://en.wikipedia.org/api/rest_v1/page/random/summary');
+ if (!data) return [];
+ return [{
+ title: data.title || 'Random Article',
+ url: data.content_urls?.desktop?.page || data.content_urls?.mobile?.page || '',
+ source: 'Wikipedia',
+ description: data.extract,
+ }].filter((a) => a.url);
+}
+
+async function fetchPublicApisNews(): Promise {
+ const data = await safeJsonFetch('https://api.publicapis.org/entries?category=News');
+ if (!data?.entries) return [];
+ return (data.entries as any[]).slice(0, NEWS_LIMIT).map((e) => ({
+ title: e.API,
+ url: e.Link,
+ source: e.Category || 'Public APIs',
+ description: e.Description,
+ })).filter((a) => a.url);
+}
+
+async function fetchScienceSpotlight(nasaKey: string): Promise {
+ const items: NewsItem[] = [];
+ const nasa = await safeJsonFetch(`https://api.nasa.gov/planetary/apod?api_key=${nasaKey || 'DEMO_KEY'}`);
+ if (nasa?.url) {
+ items.push({
+ title: nasa.title || 'NASA Astronomy Picture of the Day',
+ url: nasa.hdurl || nasa.url,
+ source: 'NASA APOD',
+ description: nasa.explanation,
+ publishedAt: nasa.date,
+ });
+ }
+ const arxivRes = await fetch('http://export.arxiv.org/api/query?search_query=cat:cs.AI&start=0&max_results=5');
+ if (arxivRes.ok) {
+ const xml = await arxivRes.text();
+ const entryRegex = /[\s\S]*?([\s\S]*?)<\/title>[\s\S]*?([\s\S]*?)<\/id>/gim;
+ let match: RegExpExecArray | null;
+ while ((match = entryRegex.exec(xml)) && items.length < NEWS_LIMIT) {
+ items.push({
+ title: decode(match[1]),
+ url: decode(match[2]),
+ source: 'arXiv cs.AI',
+ });
+ }
+ }
+ return items;
+}
+
+export async function fetchNews(category: Category): Promise {
+ const newsApiKey = getEnv('NEWSAPI_API_KEY');
+ const gnewsKey = getEnv('GNEWS_API_KEY');
+ const mediastackKey = getEnv('MEDIASTACK_API_KEY');
+ const nasaKey = getEnv('NASA_API_KEY');
+
+ if (category === 'random') {
+ return fetchWikipediaRandom();
+ }
+
+ if (category === 'science') {
+ return fetchScienceSpotlight(nasaKey);
+ }
+
+ if (category === 'technology') {
+ const [hn, devTo, reddit] = await Promise.all([
+ safeJsonFetch('https://hn.algolia.com/api/v1/search?tags=front_page'),
+ (async () => {
+ try {
+ const res = await fetch('https://dev.to/feed');
+ if (!res.ok) return null;
+ const xml = await res.text();
+ return parseRssTitles(xml, 'Dev.to');
+ } catch (error) {
+ console.warn('dev.to fetch failed', error);
+ return null;
+ }
+ })(),
+ safeJsonFetch('https://www.reddit.com/r/technology/.json')
+ ]);
+
+ const list: NewsItem[] = [];
+ if (hn) list.push(...mapHN(hn));
+ if (Array.isArray(devTo)) list.push(...devTo);
+ if (reddit) list.push(...mapReddit(reddit));
+ return list.slice(0, NEWS_LIMIT);
+ }
+
+ // Default/general news: try NewsAPI, GNews, then Mediastack
+ if (newsApiKey) {
+ const data = await safeJsonFetch(`https://newsapi.org/v2/top-headlines?country=id&pageSize=${NEWS_LIMIT}&apiKey=${newsApiKey}`);
+ const mapped = mapNewsApiArticles(data);
+ if (mapped.length) return mapped;
+ }
+ if (gnewsKey) {
+ const data = await safeJsonFetch(`https://gnews.io/api/v4/top-headlines?lang=en&max=${NEWS_LIMIT}&token=${gnewsKey}`);
+ const mapped = mapGNewsArticles(data);
+ if (mapped.length) return mapped;
+ }
+ if (mediastackKey) {
+ const data = await safeJsonFetch(`http://api.mediastack.com/v1/news?access_key=${mediastackKey}&countries=us,id&limit=${NEWS_LIMIT}`);
+ const mapped = mapMediastackArticles(data);
+ if (mapped.length) return mapped;
+ }
+
+ // Fallback to Wikipedia random if everything fails
+ return fetchWikipediaRandom();
+}
diff --git a/apps/Cortensor-Research-Summarizer/src/lib/urlFetcher.ts b/apps/Cortensor-Research-Summarizer/src/lib/urlFetcher.ts
index 6599a2b..fde80dc 100644
--- a/apps/Cortensor-Research-Summarizer/src/lib/urlFetcher.ts
+++ b/apps/Cortensor-Research-Summarizer/src/lib/urlFetcher.ts
@@ -9,12 +9,14 @@ export interface ArticleContent {
}
export class URLFetcher {
+ private static pdfParseLoader?: Promise<((data: Uint8Array | ArrayBuffer | Buffer | string | URL | number[]) => Promise<{ text: string; info?: { Title?: string; Author?: string } | undefined }>) | null>;
+
async fetchArticle(url: string): Promise {
try {
// Validate URL
- new URL(url);
+ const parsedUrl = new URL(url);
const requestTimeout = parseInt(process.env.ARTICLE_FETCH_TIMEOUT || '60000', 10);
-
+
const response = await axios.get(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
@@ -25,11 +27,40 @@ export class URLFetcher {
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
},
+ responseType: 'arraybuffer',
timeout: Number.isFinite(requestTimeout) ? requestTimeout : 60000
});
- const html = response.data;
-
+ const buffer = Buffer.isBuffer(response.data)
+ ? response.data
+ : Buffer.from(response.data);
+
+ const rawContentType = typeof response.headers['content-type'] === 'string'
+ ? response.headers['content-type']
+ : Array.isArray(response.headers['content-type'])
+ ? response.headers['content-type'][0]
+ : '';
+ const contentType = rawContentType.toLowerCase();
+ const pathLower = parsedUrl.pathname.toLowerCase();
+ const looksLikePdf = contentType.includes('application/pdf') || pathLower.endsWith('.pdf');
+
+ if (looksLikePdf) {
+ const pdfArticle = await this.extractPdfArticle(buffer, url);
+ if (pdfArticle) {
+ return pdfArticle;
+ }
+
+ return {
+ title: 'PDF Document',
+ content: 'Unable to extract readable text from this PDF using built-in parsers. The document may be scanned or contain unsupported encoding.',
+ url,
+ author: undefined,
+ publishDate: undefined
+ };
+ }
+
+ const html = this.decodeBufferToString(buffer, contentType);
+
// Extract title using regex
const title = this.extractTitle(html);
@@ -60,6 +91,168 @@ export class URLFetcher {
}
}
+ private decodeBufferToString(buffer: Buffer, contentType: string): string {
+ try {
+ if (contentType.includes('charset=')) {
+ const charset = contentType.split('charset=')[1]?.split(';')[0]?.trim().toLowerCase();
+ if (charset && charset !== 'utf-8' && charset !== 'utf8') {
+ return buffer.toString(charset as BufferEncoding);
+ }
+ }
+ } catch (error) {
+ console.warn('Character set decoding failed, falling back to UTF-8:', error);
+ }
+ return buffer.toString('utf-8');
+ }
+
+ private async extractPdfArticle(buffer: Buffer, url: string): Promise {
+ try {
+ const pdfData = await this.parsePdf(buffer);
+ if (!pdfData) {
+ return null;
+ }
+
+ const sanitizedText = this.cleanText(pdfData.text);
+ if (!sanitizedText) {
+ return null;
+ }
+
+ const titleFromMetadata = pdfData.info?.Title?.trim();
+ const derivedTitle = titleFromMetadata || this.deriveTitleFromPdfText(sanitizedText);
+ const authorFromMetadata = pdfData.info?.Author?.trim();
+
+ return {
+ title: derivedTitle || 'PDF Document',
+ content: sanitizedText,
+ url,
+ author: authorFromMetadata,
+ publishDate: undefined
+ };
+ } catch (error) {
+ console.warn('PDF extraction failed:', error);
+ return null;
+ }
+ }
+
+ private async parsePdf(buffer: Buffer): Promise<{ text: string; info?: { Title?: string; Author?: string } } | null> {
+ try {
+ await this.ensurePdfDomPolyfills();
+
+ const pdfParse = await this.loadPdfParse();
+ if (!pdfParse) {
+ return null;
+ }
+
+ const pdfResult = await pdfParse(buffer);
+ if (!pdfResult?.text) {
+ return null;
+ }
+
+ const normalizedText = pdfResult.text
+ .replace(/\u0000/g, ' ')
+ .replace(/\r\n/g, '\n')
+ .replace(/\r/g, '\n')
+ .replace(/\f/g, '\n')
+ .replace(/\n{3,}/g, '\n\n')
+ .trim();
+
+ if (!normalizedText) {
+ return null;
+ }
+
+ return {
+ text: normalizedText,
+ info: pdfResult.info
+ };
+ } catch (error) {
+ console.warn('pdf-parse module failed:', error);
+ return null;
+ }
+ }
+
+ private async loadPdfParse(): Promise<((data: Uint8Array | ArrayBuffer | Buffer | string | URL | number[]) => Promise<{ text: string; info?: { Title?: string; Author?: string } | undefined }>) | null> {
+ if (!URLFetcher.pdfParseLoader) {
+ URLFetcher.pdfParseLoader = (async () => {
+ try {
+ const pdfModule = await import('pdf-parse');
+ const candidates: unknown[] = [
+ (pdfModule as { default?: unknown }).default,
+ (pdfModule as { pdf?: unknown }).pdf,
+ pdfModule
+ ];
+
+ for (const candidate of candidates) {
+ if (typeof candidate === 'function') {
+ return candidate as (data: Uint8Array | ArrayBuffer | Buffer | string | URL | number[]) => Promise<{ text: string; info?: { Title?: string; Author?: string } | undefined }>;
+ }
+ }
+
+ console.warn('pdf-parse import did not expose a callable parser.');
+ } catch (error) {
+ console.warn('pdf-parse import failed:', error);
+ }
+
+ return null;
+ })();
+ }
+
+ return URLFetcher.pdfParseLoader;
+ }
+
+ private async ensurePdfDomPolyfills(): Promise {
+ const globalAny = globalThis as Record;
+
+ if (typeof globalAny.DOMMatrix === 'undefined') {
+ try {
+ const domMatrixModule = await import('dommatrix');
+ const DomMatrixCtor = (domMatrixModule as { default?: unknown }).default;
+ if (DomMatrixCtor && typeof DomMatrixCtor === 'function') {
+ globalAny.DOMMatrix = DomMatrixCtor;
+ }
+ } catch (error) {
+ console.warn('DOMMatrix polyfill unavailable:', error);
+ }
+ }
+
+ if (typeof globalAny.Path2D === 'undefined') {
+ class Path2DShim {
+ constructor(_path?: string | Path2D) {
+ // Path arguments ignored in server environment
+ void _path;
+ }
+ addPath(): void {
+ // No drawing support needed on server
+ void 0;
+ }
+ }
+ globalAny.Path2D = Path2DShim;
+ }
+
+ if (typeof globalAny.ImageData === 'undefined') {
+ class ImageDataShim {
+ data: Uint8ClampedArray;
+ width: number;
+ height: number;
+ constructor(data: Uint8ClampedArray, width: number, height: number) {
+ this.data = data;
+ this.width = width;
+ this.height = height;
+ }
+ }
+ globalAny.ImageData = ImageDataShim;
+ }
+ }
+
+ private deriveTitleFromPdfText(text: string): string {
+ const lines = text.split('\n').map(line => line.trim()).filter(Boolean);
+ for (const line of lines) {
+ if (line.length >= 8 && line.length <= 180) {
+ return line.replace(/\s+/g, ' ');
+ }
+ }
+ return 'PDF Document';
+ }
+
private extractTitle(html: string): string {
// Try to extract title from various meta tags and h1
const patterns = [
diff --git a/apps/Cortensor-Research-Summarizer/src/types/pdf-parse.d.ts b/apps/Cortensor-Research-Summarizer/src/types/pdf-parse.d.ts
new file mode 100644
index 0000000..fc4cfed
--- /dev/null
+++ b/apps/Cortensor-Research-Summarizer/src/types/pdf-parse.d.ts
@@ -0,0 +1,6 @@
+declare module 'pdf-parse' {
+ import type { TextResult } from 'pdf-parse/dist/esm/TextResult';
+ type PdfParseInput = ArrayBuffer | Uint8Array | number[] | string | URL | Buffer;
+ export type PdfParse = (data: PdfParseInput) => Promise;
+ export const pdf: PdfParse;
+}
diff --git a/apps/Cortensor-Research-Summarizer/tsconfig.json b/apps/Cortensor-Research-Summarizer/tsconfig.json
index c133409..b575f7d 100644
--- a/apps/Cortensor-Research-Summarizer/tsconfig.json
+++ b/apps/Cortensor-Research-Summarizer/tsconfig.json
@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "ES2017",
- "lib": ["dom", "dom.iterable", "esnext"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -11,7 +15,7 @@
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
- "jsx": "preserve",
+ "jsx": "react-jsx",
"incremental": true,
"plugins": [
{
@@ -19,9 +23,19 @@
}
],
"paths": {
- "@/*": ["./src/*"]
+ "@/*": [
+ "./src/*"
+ ]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
- "exclude": ["node_modules"]
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
}
diff --git a/apps/Cortensor-XGenBot/src/bot.py b/apps/Cortensor-XGenBot/src/bot.py
index 948c91a..df4b0e1 100644
--- a/apps/Cortensor-XGenBot/src/bot.py
+++ b/apps/Cortensor-XGenBot/src/bot.py
@@ -2,6 +2,7 @@
import os
import re
import json
+import requests
from urllib.parse import quote_plus
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ForceReply, ReplyKeyboardMarkup, ReplyKeyboardRemove, ChatAction
from telegram.ext import CallbackContext
@@ -24,6 +25,24 @@
_TONES = ["concise", "informative", "persuasive", "technical", "conversational", "authoritative"]
_SESS: dict[str, dict] = {}
+_IP_RE = re.compile(r"(?:\d{1,3}\.){3}\d{1,3}")
+_HOST_FIELD_RE = re.compile(r"host='[^']+'", re.I)
+
+
+def _friendly_error(err: Exception) -> str:
+ if isinstance(err, requests.exceptions.Timeout):
+ return "Request to the generation service timed out. Please try again."
+ if isinstance(err, requests.exceptions.ConnectionError):
+ return "Cannot reach the generation service right now. Please retry shortly."
+ if isinstance(err, requests.exceptions.RequestException):
+ return "Generation service returned an error. Please retry."
+ msg = (str(err) or '').strip()
+ if not msg:
+ msg = err.__class__.__name__
+ msg = _IP_RE.sub('', msg)
+ msg = _HOST_FIELD_RE.sub("host=''", msg)
+ return msg
+
def _audit(uid: str, event: str, **fields):
try:
extras = " ".join(f"{k}={fields[k]}" for k in fields if fields.get(k) is not None)
@@ -296,7 +315,7 @@ def thread_command(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
@@ -549,7 +568,7 @@ def _thread_callback(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- q.answer(f"Failed: {e}", show_alert=True)
+ q.answer(f"Failed: {_friendly_error(e)}", show_alert=True)
return
finally:
try:
@@ -578,7 +597,7 @@ def _thread_callback(update: Update, context: CallbackContext):
_send_thread_preview(context, q.message.chat.id, sess)
return
except Exception as e:
- q.answer(f"Fail: {e}", show_alert=True)
+ q.answer(f"Fail: {_friendly_error(e)}", show_alert=True)
return
except Exception as e:
try:
@@ -586,7 +605,7 @@ def _thread_callback(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- q.answer(f"Failed: {e}", show_alert=True)
+ q.answer(f"Failed: {_friendly_error(e)}", show_alert=True)
return
finally:
try:
@@ -952,7 +971,7 @@ def handle_text_input(update: Update, context: CallbackContext):
new_line = generate_tweet(topic=f"{topic}\n{guide}", tone=tone, length=length, hashtags="")
except Exception as e:
sess.pop("regen_line_mode", None)
- update.message.reply_text(f"Failed to regenerate: {e}", reply_markup=_reply_kb(sess))
+ update.message.reply_text(f"Failed to regenerate: {_friendly_error(e)}", reply_markup=_reply_kb(sess))
return
if new_line:
posts[idx-1] = new_line
@@ -1231,7 +1250,7 @@ def handle_text_input(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
@@ -1292,7 +1311,7 @@ def handle_text_input(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
@@ -1349,7 +1368,7 @@ def handle_text_input(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
@@ -1401,7 +1420,7 @@ def handle_text_input(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
@@ -1486,7 +1505,7 @@ def handle_text_input(update: Update, context: CallbackContext):
context.bot.delete_message(chat_id=loading_msg.chat_id, message_id=loading_msg.message_id)
except Exception:
pass
- update.message.reply_text(f"Failed to generate: {e}")
+ update.message.reply_text(f"Failed to generate: {_friendly_error(e)}")
return
finally:
try:
diff --git a/apps/Cortensor-XGenBot/src/config.py b/apps/Cortensor-XGenBot/src/config.py
index 6211ff8..7302f11 100644
--- a/apps/Cortensor-XGenBot/src/config.py
+++ b/apps/Cortensor-XGenBot/src/config.py
@@ -58,5 +58,9 @@
# If true, send thread preview as multiple Telegram messages (one per post) to avoid single-message length limits.
THREAD_SPLIT_SEND = (os.getenv('THREAD_SPLIT_SEND', 'false').lower() in ('1','true','yes','on'))
+# Optional comma or newline separated list of words to strip from generated copy.
+_irrelevant_raw = (os.getenv('IRRELEVANT_WORDS') or '').replace('\n', ',')
+IRRELEVANT_WORDS = [w.strip().lower() for w in _irrelevant_raw.split(',') if w.strip()]
+
if CORTENSOR_TLS_INSECURE:
logger.getChild('config').warning('CORTENSOR_TLS_INSECURE is enabled. SSL certificate verification is DISABLED for Cortensor requests.')
diff --git a/apps/Cortensor-XGenBot/src/cortensor_api.py b/apps/Cortensor-XGenBot/src/cortensor_api.py
index b479ccd..77ae30f 100644
--- a/apps/Cortensor-XGenBot/src/cortensor_api.py
+++ b/apps/Cortensor-XGenBot/src/cortensor_api.py
@@ -3,12 +3,35 @@
import json
import logging
import requests
+from urllib.parse import urlsplit, urlunsplit
from typing import Dict, Any
from . import config
logger = logging.getLogger(__name__)
+def _mask_sensitive_text(text: str) -> str:
+ if not text:
+ return ''
+ masked = re.sub(r"(?:\d{1,3}\.){3}\d{1,3}", '', text)
+ masked = re.sub(r"host='[^']+'", "host=''", masked)
+ return masked
+
+
+def _mask_url_for_log(raw_url: str) -> str:
+ if not raw_url:
+ return ''
+ try:
+ parts = urlsplit(raw_url)
+ netloc = parts.netloc
+ netloc = re.sub(r"^[^@]+@", '***@', netloc)
+ netloc = re.sub(r"(?:\d{1,3}\.){3}\d{1,3}", '', netloc)
+ sanitized = parts._replace(netloc=netloc)
+ return urlunsplit(sanitized)
+ except Exception:
+ return ''
+
+
def _build_endpoint(base_url: str) -> str:
"""Build a safe completions endpoint per Cortensor Web2 API.
@@ -127,10 +150,15 @@ def _post(u, p):
if isinstance(data, dict):
text = data.get('output') or data.get('text') or ''
return {'choices': [{'text': text}]}
+ except requests.exceptions.Timeout as e:
+ safe_url = _mask_url_for_log(url)
+ logger.error('Cortensor request timed out for %s: %s', safe_url, _mask_sensitive_text(str(e)))
+ raise RuntimeError('Cortensor request timed out. Please try again.') from e
+ except requests.exceptions.RequestException as e:
+ safe_url = _mask_url_for_log(url)
+ logger.error('Cortensor request failed for %s: %s', safe_url, _mask_sensitive_text(str(e)))
+ raise RuntimeError('Unable to reach the Cortensor service. Please try again later.') from e
except Exception as e:
- # Sanitize URL for logs: drop scheme, strip query, and mask any userinfo
- safe_url = url.split('://', 1)[-1]
- safe_url = safe_url.split('?', 1)[0]
- safe_url = re.sub(r'^[^@]+@', '***@', safe_url)
- logger.error('Cortensor request failed: %s to %s', e, safe_url)
- raise
+ safe_url = _mask_url_for_log(url)
+ logger.error('Unexpected Cortensor error at %s: %s', safe_url, _mask_sensitive_text(str(e)))
+ raise RuntimeError('Generation failed unexpectedly. Please retry.') from e
diff --git a/apps/Cortensor-XGenBot/src/thread_gen.py b/apps/Cortensor-XGenBot/src/thread_gen.py
index f586dc6..12fe3a1 100644
--- a/apps/Cortensor-XGenBot/src/thread_gen.py
+++ b/apps/Cortensor-XGenBot/src/thread_gen.py
@@ -4,6 +4,36 @@
from . import config
+_IRRELEVANT_WORDS = {w.lower() for w in getattr(config, 'IRRELEVANT_WORDS', []) if w}
+
+
+def _filter_irrelevant_words(text: str) -> str:
+ if not text or not _IRRELEVANT_WORDS:
+ return text
+ tokens = re.split(r"(\s+)", text)
+ cleaned: list[str] = []
+ for token in tokens:
+ if not token:
+ continue
+ if token.isspace():
+ cleaned.append(token)
+ continue
+ normalized = re.sub(r"[^\w#]", "", token).lower().lstrip('#')
+ if normalized and normalized in _IRRELEVANT_WORDS:
+ continue
+ cleaned.append(token)
+ merged = "".join(cleaned)
+ merged = re.sub(r"\s{2,}", " ", merged).strip()
+ return merged
+
+
+def _finalize_line(text: str) -> str:
+ cleaned = _clean_line(text)
+ cleaned = _sanitize_text(cleaned)
+ cleaned = _filter_irrelevant_words(cleaned)
+ return cleaned
+
+
def _length_target(length: str, n_posts: int) -> Tuple[int, str]:
length = (length or 'medium').lower()
if length == 'short':
@@ -117,35 +147,49 @@ def generate_thread(topic: str, n_posts: int, tone: str | None, hashtags: str, i
n = max(2, min(25, int(n_posts or 6)))
target, _ = _length_target(length, n)
tone = tone or config.DEFAULT_TONE
- extra = (f"\nGuidance: {instructions.strip()}" if instructions else '')
role_pattern = (config.THREAD_ROLE_PATTERN or '')
roles: list[str] = []
if role_pattern:
roles = [r.strip() for r in role_pattern.split(',') if r.strip()]
- role_lines = ''
+ role_section = ''
if roles:
role_map = []
for i in range(n):
role = roles[(offset + i) % len(roles)]
- role_map.append(f"Post {i+1}: {role}")
- role_lines = "Roles:\n" + "\n".join(role_map) + "\n"
-
- numbering_clause = "No explicit numbering like 1/5." if config.THREAD_ENUM_FORMAT == 'none' else "Number each line implicitly only if needed for clarity."
- prompt = (
- "Create a social thread for X/Twitter.\n"
- "- Language: English.\n"
- "- Number of posts: {n}.\n"
- "- Tone: {tone}.\n"
- f"- {numbering_clause}\n"
- "- Each line is a separate post.\n"
- f"- Keep each line around {{target}} characters, max {config.TWEET_CHAR_LIMIT}.\n"
- "- No hashtags except possibly at the end of the last line.\n"
- "- Do NOT include UI words like More, Less, Edit, Delete, Note, Cancel, Final, Submit, Revert, Done, Yes, No.\n"
- "- Do NOT include phrases like 'The final output is', 'Output is ready', or any meta commentary.\n"
- + (role_lines if role_lines else "")
- + "Topic: {topic}{extra}\n"
- + "Return exactly {n} lines."
- ).format(n=n, tone=tone, target=target, topic=topic.strip(), extra=extra)
+ role_map.append(f"- Post {i+1}: {role}")
+ role_section = "Role focus per post:\n" + "\n".join(role_map)
+ guidance_section = ''
+ if instructions:
+ guidance_section = "Additional guidance:\n" + instructions.strip()
+
+ numbering_clause = "Never prepend ratios like 1/5 or (1)." if config.THREAD_ENUM_FORMAT == 'none' else "Use light, natural sequencing only when it reads organically; avoid '1/5' style counters."
+ prompt_parts = [
+ "You are Meta Llama 3.1 8B Instruct Q4_K_M acting as a senior social strategist.",
+ "Goal: craft a native X/Twitter thread that feels insightful and concise.",
+ "",
+ "Thread requirements:",
+ f"- Posts: {n}.",
+ f"- Tone: {tone}.",
+ "- Language: English.",
+ f"- Keep each post near {target} characters (hard max {config.TWEET_CHAR_LIMIT}).",
+ "- Each line must read as its own post—no combined paragraphs.",
+ f"- {numbering_clause}",
+ "- Avoid UI/control words (More, Edit, Delete, Final, Submit, Revert, Cancel, Done).",
+ "- Never include meta narration such as 'The final output is' or 'Output is ready'.",
+ "- No hashtags except optionally inside the final post.",
+ "",
+ "Topic:",
+ topic.strip(),
+ ]
+ if role_section:
+ prompt_parts.extend(["", role_section])
+ if guidance_section:
+ prompt_parts.extend(["", guidance_section])
+ prompt_parts.extend([
+ "",
+ f"Deliverable:\nReturn exactly {n} separate lines, each representing one post with no extra commentary.",
+ ])
+ prompt = "\n".join(part for part in prompt_parts if part is not None)
raw = _extract_text(request_completion(prompt, config.MODEL_PROVIDER, config.MODEL_NAME))
raw = _strip_think(raw)
# Split raw output into non-empty lines
@@ -160,13 +204,13 @@ def generate_thread(topic: str, n_posts: int, tone: str | None, hashtags: str, i
if len(lines) < n:
lines += [''] * (n - len(lines))
lines = lines[:n]
- lines = [_sanitize_text(_clean_line(l)) for l in lines]
+ lines = [_finalize_line(l) for l in lines]
# Append hashtags to final line if provided and room
if hashtags:
last = lines[-1]
suffix = ' ' + hashtags.strip()
if len(last) + len(suffix) <= config.TWEET_CHAR_LIMIT:
- lines[-1] = _sanitize_text((last + suffix).strip())
+ lines[-1] = _finalize_line((last + suffix).strip())
return lines
@@ -202,23 +246,28 @@ def format_thread_preview(posts: List[str]) -> List[str]:
def generate_tweet(topic: str, tone: str | None, length: str, hashtags: str) -> str:
target, _ = _length_target(length, 1)
tone = tone or config.DEFAULT_TONE
- prompt = (
- "Create one high-quality X/Twitter post (single tweet).\n"
- "- Language: English.\n"
- "- Tone: {tone}.\n"
- f"- Keep around {{target}} characters (hard max {config.TWEET_CHAR_LIMIT}).\n"
- "- Output EXACTLY one tweet.\n"
- "- Do NOT wrap the tweet in quotes.\n"
- "- Do NOT output multiple sentences separated by standalone quotes.\n"
- "- Avoid generic hype or filler.\n"
- "- Do NOT include UI/control words (More, Edit, Delete, Final, Submit, Revert, Cancel, Done).\n"
- "- No meta phrases like 'The final output is' or 'Output is ready'.\n"
- "Topic: {topic}\n"
- "Return only the tweet text with no explanations."
- ).format(tone=tone, target=target, topic=topic.strip())
+ prompt_parts = [
+ "You are Meta Llama 3.1 8B Instruct Q4_K_M acting as a senior X/Twitter copywriter.",
+ "Task: craft exactly one scroll-stopping tweet for the topic below.",
+ "",
+ "Tweet requirements:",
+ f"- Tone: {tone}.",
+ "- Language: English.",
+ f"- Aim for ~{target} characters and never exceed {config.TWEET_CHAR_LIMIT} characters.",
+ "- Deliver a single cohesive tweet—no quoted blocks or numbered lists.",
+ "- Avoid filler, generic hype, or trailing hashtags unless provided separately.",
+ "- Do not include UI/control words (More, Edit, Delete, Final, Submit, Revert, Cancel, Done).",
+ "- Remove any meta narration such as 'The final output is' or 'Output is ready'.",
+ "",
+ "Topic:",
+ topic.strip(),
+ "",
+ "Deliverable: Return only the tweet text with no explanations or markup.",
+ ]
+ prompt = "\n".join(prompt_parts)
raw = _extract_text(request_completion(prompt, config.MODEL_PROVIDER, config.MODEL_NAME))
raw = _strip_think(raw)
- out = _sanitize_text(_clean_line(raw))
+ out = _finalize_line(raw)
# If model still dumps multiple quoted sentences, keep first 2 concise sentences.
sentences = re.split(r"(?<=[.!?])\s+", out)
if len(sentences) > 2:
@@ -229,27 +278,41 @@ def generate_tweet(topic: str, tone: str | None, length: str, hashtags: str) ->
if second and len(combined) + 1 + len(second) <= config.TWEET_CHAR_LIMIT:
combined = f"{combined} {second}"
out = combined
+ out = _finalize_line(out)
if hashtags:
if len(out) + 1 + len(hashtags) <= config.TWEET_CHAR_LIMIT:
- out = _sanitize_text((out + ' ' + hashtags).strip())
+ out = _finalize_line((out + ' ' + hashtags).strip())
return out
def generate_reply(context_text: str, tone: str | None, length: str, instructions: str) -> str:
target, _ = _length_target(length, 1)
tone = tone or config.DEFAULT_TONE
- extra = (f"\nGuidance: {instructions.strip()}" if instructions else '')
- prompt = (
- "Write a reply to the following X/Twitter post.\n"
- "- Language: English.\n"
- "- Tone: {tone}.\n"
- f"- Keep around {{target}} characters, max {config.TWEET_CHAR_LIMIT}.\n"
- "- No numbering.\n"
- "- Avoid UI/control words (More, Edit, Delete, Final, Submit, Revert, Cancel, Done).\n"
- "- No meta phrases like 'The final output is' or 'Output is ready'.\n"
- "Context:\n{ctx}{extra}\n"
- "Return only the reply text."
- ).format(tone=tone, target=target, ctx=context_text.strip(), extra=extra)
+ guidance_section = ''
+ if instructions:
+ guidance_section = "Additional guidance:\n" + instructions.strip()
+ prompt_parts = [
+ "You are Meta Llama 3.1 8B Instruct Q4_K_M acting as a thoughtful X/Twitter responder.",
+ "Task: write one native reply to the post below.",
+ "",
+ "Reply requirements:",
+ f"- Tone: {tone}.",
+ "- Language: English.",
+ f"- Aim for ~{target} characters and never exceed {config.TWEET_CHAR_LIMIT} characters.",
+ "- No numbering, no greetings, and no closing signatures.",
+ "- Avoid UI/control words (More, Edit, Delete, Final, Submit, Revert, Cancel, Done).",
+ "- Remove any meta narration or chain-of-thought markers.",
+ "",
+ "Context:",
+ context_text.strip(),
+ ]
+ if guidance_section:
+ prompt_parts.extend(["", guidance_section])
+ prompt_parts.extend([
+ "",
+ "Deliverable: Return only the reply text with no explanations.",
+ ])
+ prompt = "\n".join(prompt_parts)
raw = _extract_text(request_completion(prompt, config.MODEL_PROVIDER, config.MODEL_NAME))
raw = _strip_think(raw)
- return _sanitize_text(_clean_line(raw))
+ return _finalize_line(raw)
diff --git a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/eslint.config.mjs b/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/eslint.config.mjs
deleted file mode 100644
index 719cea2..0000000
--- a/apps/price-analyzer-dev-recent/Cortensor-Price-Analyzer/eslint.config.mjs
+++ /dev/null
@@ -1,25 +0,0 @@
-import { dirname } from "path";
-import { fileURLToPath } from "url";
-import { FlatCompat } from "@eslint/eslintrc";
-
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = dirname(__filename);
-
-const compat = new FlatCompat({
- baseDirectory: __dirname,
-});
-
-const eslintConfig = [
- ...compat.extends("next/core-web-vitals", "next/typescript"),
- {
- ignores: [
- "node_modules/**",
- ".next/**",
- "out/**",
- "build/**",
- "next-env.d.ts",
- ],
- },
-];
-
-export default eslintConfig;