From 2973b36d249f66d8c698e8e76aa4cd855c2085ed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 16:12:39 +0000 Subject: [PATCH] Add blume-search extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - chore: release v1.0.67 - chore: release v1.0.67 - Measure agent hours as work done, not how long a tab stayed open (#737) - Add 1.0.64 email broadcast images (#742) - Remove two stray screenshot files named - - Redesign the first-run wizard around what the machine knows (#735) - Website hotfix 2 - Website hotfix attempt 1 - Add Blume Wrapped: weekly recap cards (#722) - Let the router deploy read AUTH_ISSUERS (#733) - Make the first-run wizard gate fail closed (#730) - Accept the issuer the auth service actually stamps (#732) - fix(auth): preserve session security across clients (#717) - Make PR review service-neutral and assign capability fallbacks (#731) - docs(review): close reviewer fallback gaps - docs(review): block when task posting fallback fails - docs(review): make PR review service-neutral - Merge pull request #726 from blumepage/codex/add-copywriting-skill - clarify social copy skill routing - fix(auth): deploy code and secrets atomically (#728) - fix copywriting skill default prompt - Add operator trigger for Web Lab host refresh (#727) - First-run experience for users with no agent, and a managed model route (#721) - Put the first-run surface in Storybook - Verify tokens against the issuer auth actually stamps - Add copywriting skill - Fix Web Lab preview helper drift (#724) - Give the resize test time for a login shell - Merge pull request #725 from blumepage/codex/fix-storybook-auth-play-race - Stop telling a signed-in user to sign in - fix(ui-preview): avoid Storybook auth play race - Merge remote-tracking branch \'origin/main\' into claude/blume-first-run-redesign-0f60da - Merge pull request #576 from blumepage/agent/ui-preview-storybook - Point the deployment contract at the renamed step - Add repository PR review process (#723) - fix(ui-preview): preserve base comparison build - Accept a carriage return as a line boundary - Say what the terminal actually produced when a wait times out - fix(ui-preview): close local auth bypasses - Run terminals in the user\'s shell, not /bin/sh - fix(ui-preview): preserve component button styles - Wait for the shell\'s reply, not its echo - Merge main: artifact sync, device-bound tokens, catalog cleanup - fix(ui-preview): cover latest shared components - Merge remote-tracking branch \'origin/main\' into agent/ui-preview-storybook - Fix the money and blast-radius findings from review - feat(ui-preview): deploy authenticated preview - Keep credential drops out of git - Merge pull request #649 from blumepage/codex/artifact-sync - Make the irreversible step the one CI enforces - Collect a name when collecting a VAT number - Merge remote-tracking branch \'origin/main\' into codex/artifact-sync - Merge pull request #720 from blumepage/codex/claude-usage-terminal-command - fix(ui-preview): encrypt preview sessions - fix(ui-preview): gate documentation app locally - Stop a merge from deploying live billing - Let the router own its customer in test mode only - Deploy each target to the Stripe world it belongs to - Show Claude install steps during onboarding - Deploy the router from CI, with secrets that sync themselves - fix: persist runner sync state through storage - feat(ui-preview): link composition consumers to stories - Detect missing Claude CLI with stale credentials - fix: reconcile runner metadata after main merge - chore: address review performance warnings - Merge remote-tracking branch \'origin/main\' into codex/artifact-sync - fix(ui-preview): always reset auth submission state - chore(ui-preview): refresh catalog after main merge - Merge remote-tracking branch \'origin/main\' into agent/ui-preview-storybook - feat(ui-preview): gate Storybook behind Blume auth - Decide the currency and tax questions - Merge remote-tracking branch \'origin/main\' into codex/claude-usage-terminal-command - Improve Claude usage setup and menu bar defaults - Model devices, installations, and runtime sessions - Merge pull request #719 from blumepage/codex/fix-postiz-hostname - Move Stripe from the sandbox to the real account - Fix missing menu bar tray icons under the resvg rasterizer (#696) - Refuse to run Stripe in the wrong world - chore(ui-preview): refresh generated catalog after main merge - Merge remote-tracking branch \'origin/main\' into agent/ui-preview-storybook - Keep the Stripe key in one place - docs: use canonical Postiz hostname - Add the Stripe customer column to the auth database - Merge pull request #689 from blumepage/claude/setup-details-redesign-4da1b6 - Let the auth service own the Stripe customer - Give an invalid draft a way out - Install the Pi that is actually maintained - Stop asking a human for a public key - Point the desktop app at the router that exists - Add admin user details and synced items - Point the router at its D1 database - Merge remote-tracking branch \'origin/main\' into claude/setup-details-redesign-4da1b6 - Replace sync preview back action with skip - Merge pull request #714 from blumepage/codex/revert-harness-pr-690 - Mirror the real PostHog flag definitions - Revert "Merge pull request #690 from blumepage/codex/harness-parser-certification" - Create Blume\'s feature flags from PostHog, not by hand - Merge pull request #690 from blumepage/codex/harness-parser-certification - fix harness certification review findings - Assert rejected writes leave existing content intact - Never seed or save a draft from another file\'s content - Make router provisioning one command - Move the guarded write route out of the legacy write predicate - Fail closed on older runners and match markdown\'s click-to-edit - Close the remaining compare-and-write gaps - Make setup file saves a compare-and-write across both runtimes - Address review findings on the setup detail page card - Redesign the setup artifact detail page and share its content card - Simplify synced item settings layout - Show filenames in single-file sync previews - Put sync location in preview timeline - Give newcomers a managed Pi route, billed through Blume - Merge remote-tracking branch \'origin/main\' into codex/harness-parser-certification - Align sync preview controls with suggestions - fix: configure git identity for Raycast publishing (#694) - Prebuild harness parser before certification tests - Show sync operations in settings card - Reuse change review components for sync - Serialize harness certification files - Group sync location controls - Make sync settings a page - Track Augment mutation evidence - Present missing synced directories as folders - Track Augment LevelDB certification evidence - Show content diffs in sync previews - Keep scoped review within service limit - Keep preview deploys green during comment outages - chore: release v1.0.66 - fix: publish public Raycast extension (#693) - Stabilize full PR test concurrency - fix(ci): make preview and parser suites deterministic - test(ci): exercise transient comment recovery - fix(ci): retry preview comment reconciliation - chore(review): scope full review below service limit - fix(ui): address harness review performance warnings - fix(admin): expose undeployed harness schema transparently - style(harness-lab): normalize certification sources - feat(harness-lab): add Linux TUI calibration tracks - test: enforce capture-gated registry routes - fix: keep capture-gated routes non-exact - fix: gate unaudited native harness formats - fix: keep parser certification consumers type-safe - fix: keep Kiro CLI capture gate semantically empty - feat: certify harness parsers and integrate admin monitoring - Preview sync placement automatically - Let the suggestion row scroll, and tuck the status inside the bubble - fix: publish Raycast from stable update feed (#691) - Show the command a terminal is running - Fix Improve analytics and processing history (#651) - Add safe artifact sync reconciliation - Stop asking about tools Blume cannot read - Gate Cloud Improve with PostHog (#692) - Require login only for new installations (#688) - Preserve synced folder boundaries - Make the terminal behave like a terminal - Handle rolling device endpoint deploys - Give the terminal dialog a single bar - Condense sync settings subtitle - Align synced items with artifact lists - Float the terminal as a minimisable dialog, and truly leave Blume - Close artifact sync review edge cases - Let users finish in their own terminal, and say where a key comes from - Parallelize independent path checks - Propose real project folders instead of an empty picker - Preserve local sync state on remote failures - Close artifact sync review edge cases - Harden artifact sync runtime boundaries - Guide first-run users all the way to a first session - Validate device timestamps consistently - Model account devices as stable installations - Preserve artifact sync state while offline - Merge remote-tracking branch \'origin/main\' into codex/artifact-sync - Fix signed-out artifact sync state - chore: release v1.0.65 - fix(release): preserve tag gate YAML (#686) - chore: release v1.0.64 - fix(release): verify protected tags locally (#685) - chore: release v1.0.63 - Use hero screenshot as social card and update meta title (#680) - Merge remote-tracking branch \'origin/main\' into codex/artifact-sync - fix(release): replace stale canary runners (#654) - Authorize runner artifact sync paths - Retire stalled release runners before deploy (#653) - Reject dangling VPS sync destinations - Fix missing synced artifact discovery - Reserve Web Lab runner ports across deployments (#652) - Let the terminal report command completion and suggest what to run next - Keep setup terminals usable after the command finishes - Harden sync path and move semantics - Fix sync coverage regression fixture - Allow slower Web Lab runner startup (#650) - Validate desktop sync paths - Harden artifact sync boundaries - Turn the first-run welcome into a branching wizard with in-app terminal - Bundle artifact sync in Electron main - Merge remote-tracking branch \'origin/main\' into codex/artifact-sync - Merge remote-tracking branch \'origin/codex/embedded-terminal-page\' into claude/blume-first-run-redesign-0f60da - Add first-run welcome wizard for machines without agent sessions - Fix Electron 43 cross-platform release builds (#648) - Add cross-system artifact sync - Move login setting into System page (#645) - Accept current Gateway ZDR audit evidence (#646) - Fix canary release and align Cloud Improve context (#644) - Add local Blume search for Raycast (#642) - Remove global todo-list integration (#643) - Link Web Lab and Electron deployments in admin cards (#641) - chore: release v1.0.62 - chore: release v1.0.61 - Wire hero subtitle experiment into the landing hero (#639) - Add referral share experiment flow (#604) - Classify rejected Gateway ZDR token order (#636) - Classify rejected Gateway suffix semantics (#631) - Add booking thank-you page (#634) - Fix Terms of Service placeholders (#633) - Classify rejected Gateway suffix structure (#630) - Refine rejected Gateway attempt diagnostics (#629) - Classify rejected Gateway requested clauses (#628) - Diagnose invalid Gateway ZDR suffixes (#627) - Diagnose prefixed Gateway ZDR evidence (#626) - Classify Cloud Gateway ZDR prefix evidence (#625) - Stage Cloud Gateway ZDR grammar diagnostics (#624) - Diagnose Cloud Gateway ZDR evidence (#623) - Accept omitted Gateway provider model identity (#622) - Accept omitted Gateway attempt model identity (#621) - Diagnose Cloud Gateway attempt metadata (#620) - Allow omitted Gateway resolved model metadata (#619) - Classify missing Cloud model metadata safely (#618) - Classify Cloud resolved model shape safely (#617) - Diagnose Cloud resolved model metadata safely (#616) - diagnose(cloud): classify provider metadata drift (#615) - Fix Cloud Gateway attempt metadata verification (#614) - Fix Cloud Gemini ZDR routing through Vertex (#613) - Record live Cloud ZDR certification blocker (#612) - Diagnose Cloud provider policy certification safely (#611) - fix: classify Gateway certification failures safely (#610) - feat: certify Cloud provider privacy route (#609) - docs: record Cloud trusted-main deployment proof (#608) - Fix main LLM candidate deployment (#606) - Fix trusted release environment validation (#605) - Inherit installed account sessions in desktop dev (#602) - Track suggestion activation and run first-enable analysis (#601) - Add Cloud suggestion processing (#603) - Reduce idle desktop resource usage and add dev profiles (#600) - Fix production errors identified in PostHog (#599) - Open inactive agents from detail routes (#596) - Make PR sub-agent review conditional (#597) - Enable social login in desktop dev (#598) - Merge pull request #595 from blumepage/optimize-coderabbit-limit - docs: deduplicate Blume PR review policy - Add login-required PostHog experiment (#593) - chore: release v1.0.60 - Prevent Improve worker failures from quitting Blume (#590) - Stop emitting request lifecycle telemetry for list-ready-conversations (#591) - Merge pull request #583 from blumepage/suggestion-ai-editing - fix(improve): preserve long inline revision edits - fix(improve): preserve revision across namespaces - Merge remote-tracking branch \'origin/main\' into suggestion-ai-editing - fix(improve): rerun after suggestion revision - chore: release v1.0.59 - Add BlurReveal wrapper and blur the usage tab account email (#586) - Scope improve cluster and signal reads to the run\'s agent-set namespace (#584) - test(improve): cover feedback upload eligibility - Merge remote-tracking branch \'origin/main\' into suggestion-ai-editing - Replace native menu bar menu with custom popover (#579) - fix(improve): clear stale inline edit validation - fix(improve): scope revision claims and edit validation - fix(improve): harden suggestion revision boundaries - fix(improve): bound revision context and preserve relations - fix(improve): validate runner revision messages - feat(improve): revise suggestions with AI feedback - Add project tracking exclusions (#578) - Refine shared settings and configurable list styles (#580) - feat(ui-preview): add authenticated Storybook preview - Prettify and syntax-highlight tool-call input/output (#568) - Add Teamtailor careers integration (#563) - fix(release): authenticate versioned web lab (#574) - fix(sidecar-ui): steady the agent log and sequence agent list motion (#570) - test(auth): verify non-admin CI access is denied (#572) - feat(auth): extend Better Auth to every dashboard, and verify sessions via JWKS (#571) - feat(desktop): honor PostHog flag overrides in all build channels (#566) - fix(terminal): address automated review findings - fix(terminal): preserve retries across navigation - fix(terminal): parallelize worker shutdown - Merge remote-tracking branch \'origin/main\' into codex/embedded-terminal-page - fix(terminal): harden lifecycle and output replay - Add GitHub sign-in and account pages (#562) - Add Claude creative preview loop (#561) - feat(desktop): add embedded terminal pages - Feature-flag accounts and shared feature request board (#549) - Fix feedback chat email identity and reply delivery (#560) - feat(desktop): add local PostHog flag controls (#528) - Give category avatars a flat background from one of three picked sets (#553) - Fix footer logo optical alignment (#559) - fix(website): keep landing flower in sync across SSR (#534) - Add setup artifact deletion actions (#537) - add Blume marketing materials skill (#556) - Add selector discovery to Web Lab screenshots (#550) - chore: release v1.0.58 - fix: require Developer ID G2 signing (#548) - Make suggestion diffs toggle from the code area (#535) - Polish artifact tree row alignment (#545) - Show plugin names and harden preview cleanup (#543) - Allow Web Lab Workers to reach release runners (#542) - Collapse tool activity in recent conversations (#538) - Organize project artifacts into expandable folders (#536) - Improve suggestion details and dismissal feedback (#527) - Restore the landing page petal effect (#532) - Self-host Postiz with a native Sanity publishing channel (#530) - feat(brand): one canonical Blume lockup everywhere (#520) - docs(review): bound adversarial PR review loop (#533) - feat(web-lab): add screenshot studio and capture CLI (#526) - Wire landing registration emails to feedback chat (#529) - Expand the setup-audit catalog to v2: plugins, scope, enforcement, parity (#531) - Fix boot identity race, share event bursts, and referral claim telemetry (#507) - fix(desktop): filter shutdown noise from render-process-gone telemetry (#523) - Add the context-engineering setup audit (v1) (#516) - Send feedback chat replies to registered emails (#525) - feat(avatars): gradient category backgrounds instead of a flat wash (#519) - fix(desktop): fail fast with a clear notice when window.api is missing (#522) - Redesign suggestion details and add safe mock suggestions (#496) - fix hanging test (#515) - fix(website): SEO quick wins — complete blume.page → blume.codes migration (#469) - Merge pull request #506 from blumepage/danny/remove-dead-scorer-events - feat(website): add closed-loop blog social analytics (#493) - Merge pull request #505 from blumepage/codex/fix-claude-background-agent-status - chore(website): remove dead instruction-scorer event constants - Fix Claude background agent session status - Merge pull request #502 from blumepage/fix/ipc-offline-network-error-telemetry - Merge pull request #504 from blumepage/danny/repair-instrumentation - Merge pull request #503 from blumepage/danny/improve-quota-retry-guard - fix(desktop): confirm offline IPC failures - Stop leaking route params as super properties; add onboarding step telemetry - Skip improve force-retry on plan-quota and ENOENT failures - fix(desktop): count offline network IPC failures as telemetry, not errors - Merge pull request #501 from blumepage/danny/fix-walkjsonl-stack-overflow - Fix stack overflow in walkJsonl on huge session directories - Merge pull request #500 from blumepage/danny/restore-to-open-confirmation - Show a confirmation after undoing or restoring a suggestion - Remove petals from skeleton loading states (#494) - feat(desktop): surface ready updates in footer (#490) - fix(admin): persist shared-password login (#487) - Add feature-flagged Sanity blog (#443) - Animate agent list changes with calm destination motion (#448) - Remove Autonoma integration (#481) - Remove obsolete preview QA hooks (#485) - Merge pull request #419 from blumepage/codex/macos-updater-announcements - Merge remote-tracking branch \'origin/main\' into codex/ready-pr419 - Merge pull request #442 from blumepage/codex/updater-certification-bootstrap - Fix stem-attached bluebell gravity (#484) - Add Blume MCP continuity integration (#421) - fix: reject announcement redirects - Merge remote-tracking branch \'origin/main\' into codex/ready-pr442 - Merge remote-tracking branch \'origin/main\' into codex/ready-pr419 - Merge pull request #477 from blumepage/codex/fix-wallpaper-downloads - Gate phone sharing on Electron runtime - Align website wallpaper action with browser download - Fix wallpaper exports and nested menu flicker - fix: harden announcement rollout and runner retries - Merge remote-tracking branch \'origin/main\' into codex/ready-pr442 - Merge remote-tracking branch \'origin/main\' into codex/ready-pr419 - Merge remote-tracking branch \'origin/main\' into codex/ready-pr419 - Merge pull request #482 from blumepage/codex/flower-wallpaper-continuity - Merge remote-tracking branch \'origin/main\' into codex/ready-pr442 - Add continuous anchored flower wallpapers - Merge pull request #478 from blumepage/codex/match-dock-icon-flower - Match macOS Dock icon to selected flower - Add shared flower petal rewards (#447) - Fix Claude question sessions shown as running (#444) - Merge pull request #470 from blumepage/danny/dev-format-read-only-file-viewer - Merge pull request #471 from blumepage/danny/fix-improve-pipeline-test-types - Fix typecheck errors in improve pipeline orchestration tests - Add read-only dev-format file reads to the dev explorer - chore: release v1.0.57 - Refine landing journey flower crowns (#457) - Email launch (#459) - Remove scorer tools from website (#456) - Merge pull request #454 from blumepage/danny/fix-improve-codex-multi-message-parse - Merge pull request #455 from blumepage/danny/improve-agent-worker-request-telemetry - Add content-free improve agent worker request telemetry. - Fix codex report parsing failing on prose agent messages - Merge pull request #453 from blumepage/codex/fix-updater-logger-error - fix: preserve native updater errors in logging - Merge pull request #452 from blumepage/danny/agent-setup-tweaking - Restore guarded Autonoma rolling-result summary in AGENTS.md - minor improvements to agent setup based on running blume\'s advice on itself - Fix showcase flower click target (#449) - Fix landing flower avatar backgrounds (#445) - Default launch at login with Settings control (#437) - docs(web-lab): document announcement recovery scenario - fix(ci): isolate certification dispatch inputs - fix(ci): preserve preview policy contract - ci(updater): add isolated macOS certification - docs(updater): cover affected stable Electron baseline - test(web-lab): route recovery seed through worker - test(web-lab): seed recovery announcement deterministically - Merge remote-tracking branch \'origin/main\' into codex/macos-updater-announcements - test(web-lab): seed announcement recovery sessions - Refine Autonoma PR test lifecycle (#439) - Merge remote-tracking branch \'origin/main\' into codex/macos-updater-announcements - Merge remote-tracking branch \'origin/main\' into codex/macos-updater-announcements - Block merges on missing Autonoma evidence (#435) - Fix stable setup discovery and polish shared project UI (#431) - Merge pull request #433 from blumepage/danny/untitled-session-recovery - fix: absorb Claude session-id fallback rows and stop rendering uuid titles - Fix deployment registry Access authentication (#425) - chore: release v1.0.56 - Alias discontinued PR canary feed - Migrate live admin email settings to blume.codes (#381) - Fix canary update version state - fix: close announcement release readiness gaps - fix: authenticate canary main verification (#422) - Merge remote-tracking branch \'origin/main\' into codex/macos-updater-announcements - Add artifact inventory and type-aware detail pages (#420) - Merge remote-tracking branch \'origin/main\' into codex/macos-updater-announcements - feat: redesign incremental improvement processing workflow (#412) - fix(desktop): install Electron runtime during setup - Add release bundle deployment dashboard and manual canary flow (#408) - fix(website): scope Vercel workspace install - Merge origin/main into codex/macos-updater-announcements - feat: add targeted product announcements - Default Web Lab to VPS and filter self-run conversations (#418) - Improve referral flow (#415) - Extract reusable Blume flow package (#411) - Isolate stable and canary desktop releases (#409) - Remove obsolete UI preview apps (#413) - fix(desktop): harden macOS updater migration - Polish onboarding, settings, and setup interactions (#410) - Merge pull request #384 from blumepage/danny/hide-empty-global-artifacts - hide empty global artifacts sections for cleanliness/simplicity - Merge pull request #406 from blumepage/danny/harness-skills - claude display improvement - Add harness-support skills - Minimum fix for the new signal kind model (#403) - docs: map harness feature surface - Refine sidecar navigation and compact layouts (#395) - Better terminal failure feedback (#400) - Refine category flower avatars (#393) - Stabilize active conversation ordering (#392) - Preview project avatars with lighter category backgrounds (#390) - Improvement settings formulation updates (#389) - Refine signal analytics design (#370) - New smart timing model (#388) - Fix Claude usage authentication guidance (#387) - Normalize project avatar sizing and corners (#385) - test(app-core): keep conversation fixture aligned - Provider aware onboarding (#379) - Add dev background process diagnostics (#380) - Fix renderer re-render fan-out and dev profiling (#378) - Connect Web Lab PR previews to Autonoma (#330) - Add entity page components (#382) - Polish category flower heads: uniform size, in-family colors, better bells (#373) - Make signal analytics only use turns from non-controlled agents (#377) - Small agent improval (#374) - Better numbers on analyzed messages (#372) - Add conversation actions menu and cross-harness handoff (#352) - Merge pull request #371 from blumepage/danny/web-lab-snapshots-include-session-file - Include content of session jsonl file in web lab snapshots - Sql migration drop improve data (#366) - Simplify Improve beta banner (#367) - Onboarding agent with signals (#364) - Windows support and planner harness rundir (#361) - Merge pull request #356 from blumepage/claude/avatars-flowers - Merge remote-tracking branch \'origin/main\' into claude/avatars-flowers - Replace @blumepage/dicebear-flowers with @blume/avatars-flowers - Add @blume/avatars-flowers: deterministic flower avatar package - Add signal analytics and cohort comparison (#346) - Merge pull request #354 from blumepage/codex/fix-journey-flower-buttons - fix(website): restore showcase flower selection - Merge pull request #316 from blumepage/codex/blume-admin-panel - Merge pull request #351 from blumepage/codex/redesign-waitlist-email - Redesign landing page download email - Document Railway-hosted Chatwoot topology - Merge pull request #345 from blumepage/codex/resolve-cogsur-round-by-post - Resolve CogSur manual orders by post - Focus edges for selected architecture nodes - Merge pull request #343 from blumepage/codex/repeat-cogsur-manual-orders - Allow repeated CogSur manual orders - Use GitHub logo for Actions node - Deduplicate crossing overpass arcs - Merge pull request #342 from blumepage/codex/fix-cogsur-manual-request - Fix CogSur manual order validation - Fix hybrid vertex crossing jumps - Let CogSur product picker escape dialog - Add manual CogSur comment text list - Generalize architecture layout editing - Fix admin dashboard brand marks - Add manual CogSur external agent orders - Place local external nodes near dependencies - Reduce architecture route overlap - Fix architecture layout ranking - Fix architecture layout fallback - Merge remote-tracking branch \'origin/main\' into codex/blume-admin-panel - Merge pull request #335 from blumepage/codex/fix-cogsur-rendering - Align Cogsur PNG test types - Address Cogsur review feedback - Fix Cogsur media and agent comments - Merge pull request #329 from blumepage/codex/fix-ios-wordmark-clipping - Scope mobile showcase CSS checks - Use SN Pro for mobile showcase controls - Polish mobile showcase controls - Strengthen wordmark sizing regression - Prevent iPhone wordmark clipping - Merge pull request #328 from blumepage/codex/fix-mobile-header - Keep app preview header logo visible - User pain merge new architecture (#301) - Merge pull request #327 from blumepage/codex/restore-agents-preview - Refine website preview presentation - Restore animated Agents preview - Merge pull request #320 from blumepage/codex/fix-claude-parser-identities - Harden Claude auxiliary cleanup - Fix Claude auxiliary session identities - Merge pull request #319 from blumepage/codex/fix-agent-view-flicker - Strengthen reload stability regression - Fix conversation view flicker during ingest - Address admin panel review findings - Merge main into codex/blume-admin-panel - Build Blume admin operations console - Merge pull request #315 from blumepage/codex/fix-privacy-copy - Refine journey privacy language - Fix journey privacy copy - Merge pull request #314 from blumepage/codex/pr-area-labels - Merge pull request #310 from blumepage/codex/global-search - Handle optional Web Lab feedback failures - Automate PR area labels - Merge remote-tracking branch \'origin/main\' into codex/global-search - Handle stale search focus and invalid limits - Merge pull request #311 from blumepage/codex/website-shared-ui - restore landing preview choreography - Merge remote-tracking branch \'origin/main\' into codex/global-search - Harden legacy identity and read-only search - restore landing feedback back navigation - Add keyboard search filter navigation - fix Vercel website build output - Merge remote-tracking branch \'origin/main\' into codex/website-shared-ui - Keep focused transcripts current - configure Vercel monorepo linkage - Replace desktop previews with Web Lab PR previews (#309) - Clarify explicit dev conversation titles - revert journey step typography - fix feedback header and journey typography - fix landing feedback chat mode - Resolve dev labels from checkout paths - Reject orphaned subagent dev labels - fix website review findings - Resolve dev labels from exact Codex tasks - Merge remote-tracking branch \'origin/main\' into codex/global-search - Fix search navigation and runtime isolation - Remove journey copy preview page - Add Blume website with shared product previews - Merge pull request #299 from blumepage/codex/parse-nested-codex-todos - Address adversarial architecture and performance review - Address search review feedback - Cover boot ingest notification bursts - Fix Improve refresh flicker - Add global and contextual search - Coarsen compact activity timestamps - Align runner failure reason boundaries - Fix downstream conversation summary typing - Fix terminal conversation status and compact metadata - Detect Codex null-final failures - Fix project setup file authorization handoff - Address parser parity review findings - Fix canonical parser parity on large and child transcripts - perf: streamline Claude lineage parsing - Merge remote-tracking branch \'origin/main\' into codex/parse-nested-codex-todos - fix: deduplicate cloned Claude conversations - Add configurable onboarding guide (#305) - fix review findings for identity refresh parity - Make architecture compliance explicitly blocking - Align project status bubbles with compact cards - Keep canonical owners for Cursor worktrees - Merge remote-tracking branch \'origin/main\' into codex/parse-nested-codex-todos - Fix optional transcript pagination flags - Paginate long views and fix Web Lab parity - Address project identity review - Unify project worktree lists - Merge pull request #304 from blumepage/codex/upgrade-dicebear-flowers-v2 - Upgrade flower avatars to DiceBear v2 - fix: stabilize canonical project names - fix: address conversation refresh review - fix: align transcript steps and project identity - Merge pull request #302 from blumepage/codex/menu-bar-usage-dropdown - Improve menu bar usage dropdown - fix: keep active conversation details fresh - fix: show Codex todo progress - Merge pull request #286 from blumepage/codex/improve-setup-overview-ui - perf(setup): accelerate project artifact scans - Merge remote-tracking branch \'origin/main\' into codex/improve-setup-overview-ui - feat(setup): redesign project inventory and loading - Merge pull request #297 from blumepage/codex/idle-user-stopped-conversations - fix stopped Claude conversations showing as running - Merge remote-tracking branch \'origin/main\' into codex/improve-setup-overview-ui - Merge pull request #293 from blumepage/codex/fix-dev-conversation-preflight - Merge pull request #295 from blumepage/codex/fix-conversation-state-classification - Merge remote-tracking branch \'origin/main\' into codex/improve-setup-overview-ui - Merge pull request #296 from blumepage/codex/harden-settings-boundary-fixture - Fix setup summary cancellation and workspace identity - Make parser signal supersession source-aware - Surface settings lock worker failures - Guard workspace link parent symlinks - Merge pull request #291 from blumepage/codex/fix-settings-menu-bar-hang - Bound settings adapter regression process - Persist lightweight project setup summaries - Keep active Codex turns running after refresh - Harden workspace package isolation - Merge remote-tracking branch \'origin/main\' into codex/fix-settings-menu-bar-hang - Display home-relative project paths - Fix settings retry at SQLite connection boundary - Refine project hovercard trigger - Fix conversation error state classification - Merge remote-tracking branch \'origin/main\' into codex/improve-setup-overview-ui - Merge pull request #294 from blumepage/codex/shared-flower-unlocks - Share flower unlocks across desktop and Web Lab - Clarify scalable concurrency guidance - Address setup architecture review - Harden settings retry regression coverage - Fix desktop dev conversation preflight - Merge main architecture into setup redesign - Prevent settings writes from blocking Electron - Merge pull request #292 from blumepage/codex/add-blume-architecture-skill - Require desktop performance incident updates - Add Blume architecture skill - Merge pull request #172 from blumepage/claude/wonderful-mendel-cf987f - Fix Web Lab conversation details layout - Restore sidecar UI and conversation parity - Fix macOS conversation watcher deadlock - Address setup review feedback - Restore complete shared conversation search - Restore shared agent routing boundaries - Notify shells when shared settings change - Keep acknowledged conversations idle - Simplify global setup inventory - Restore shared settings navigation parity - Refresh shared Improve views live - Restore shared conversation route parity - Integrate project show more row - Restore native menu bar parity - Share menu bar preferences UI - Restore shared agent card preferences - Revert "Unify the app design language" - Share product UI settings keys - Merge remote-tracking branch \'origin/main\' into claude/wonderful-mendel-cf987f - Unify the app design language - Refine setup harness selector - Show git project metadata in setup header - Add project and worktree setup list - Prevent project preview layout shifts - Fix wordmark font loading in worktrees - Align project setup header - Improve global setup navigation - Simplify setup interface - Fix web-lab acknowledgement and session recovery - Improve setup overview and project identity - chore: release v1.0.54 - Merge pull request #284 from blumepage/codex/fix-posthog-release-race - Make PostHog source map injection idempotent - Update latest main reconciliation status - Merge latest main through shared architecture - Merge pull request #266 from blumepage/codex/running-conversations-page - Document PR 172 recovery readiness - Upload shared Improve lifecycle feedback - Align transcript search case normalization - Share controlled Improve developer surface - Route desktop Improve through controlled agents - Run controlled Improve agents in web runner - Tighten controlled Improve adapter types - Batch transcript search by newest turn - Expose controlled agent task types - Add shared Node controlled agent runtime - Share controlled Improve tool handlers - Address legacy CodeRabbit review findings - Guard shared product host boundaries - Address CodeRabbit follow-up review - Share Improve suggestion display feedback - Adapt desktop SQLite migration driver - Open shared settings in web shell - Restore controlled Improve agent core - Restore conversation refresh protocol coverage - Expand desktop migration upgrade coverage - Unify legacy desktop SQLite storage access - Keep shared settings entry point available - Share conversation title actions across hosts - Merge remote-tracking branch \'origin/main\' into codex/running-conversations-page - Polish conversation transcript and menu settings - Restore shared Improve control plane policy - Restore shared Insights eval tooling - Restore incremental conversation refresh updates - Fix shared path identity and Improve regression coverage - Merge origin/main into shared architecture branch - Clear stale Codex todos on new turns - Unify conversation timelines and cap transcript page payloads - Fix Codex todo refresh for large sessions - Classify conversation state live for deferred Codex transcripts - Move launch at login to settings - Fix conversation refresh contention - Reset Claude task todos on user turns - Merge pull request #280 from blumepage/codex/fix-canary-blocked-feed-metadata-20260712 - Prevent updater download failures from crashing desktop - Fix blocked desktop feed fallbacks - Merge pull request #276 from blumepage/codex/fix-desktop-download-helper-20260712 - Fix stable desktop download fallback - Block accidental internal canary release - Block accidental release in download helpers - Block accidental desktop release 1.0.53 - Revert "chore: release v1.0.53" - chore: release v1.0.53 - Fix web-lab runner response caching - Guard web-lab conversation reloads - Prevent conversation reload starvation - Speed up inactive conversation loading - Add web-lab live projection test hooks - Fix web-lab host reload after session changes - Use Claude session state for running conversations - Use Claude session state for approval waits - Add live tail updates for active transcripts - Fix web-lab conversation state projection - Fix web-lab conversation state projection - Fix conversation refresh performance regression - Fix live recent activity freshness - Fix agents list hydration test mock - Keep recent activity live while agents run - Keep active conversation timestamps fresh - Add granular menu bar content settings - Add browser screenshot troubleshooting skill - Show recent activity chronologically - Default menu bar usage off - Keep conversation activity fresh while parsing - Ignore command-only Claude transcripts - Show relative recent activity times - Refresh agent activity on conversation updates - Address agent settings follow-up review - Preserve provider rename titles in shared ingest - Address agent view settings review - Merge pull request #267 from blumepage/codex/agent-view-config - Add web lab rename title test case - Align compact card status action - Deduplicate agent project context props - Address agent view PR feedback - Add configurable agent card views - Install bubblewrap on web lab VPS - Polish menu bar dropdown and status header - Use real PTY for web lab terminals - Merge branch \'main\' of github.com:blumepage/sidecar-prototype into codex/running-conversations-page - Address CodeRabbit review feedback - Use dedicated web lab runner VPS - Add menu bar usage and conversation details - Hide local runtime in deployed web lab - Name the web lab VPS runtime - Normalize web lab runner label aliases - Recognize web lab runner VPS alias - Label web lab VPS runtime - Embed web lab menu bar logo asset - Fix local web lab runtime controls - Tidy web lab menu bar controls - Add selectable web lab runtimes - Darken web lab menu bar - Share menu bar conversation row rendering - Remove web lab menu labels - Share menu bar tray icon renderer - Share menu bar rendering with web lab - Port batched agents list hydration - feat(web-lab): simulate menu bar status - fix(web-lab): recover stale runner state - fix(sidecar-ui): use tree icon for worktrees - docs: clarify completed todo card expectation - fix(sidecar-ui): collapse completed todo progress - docs: tighten web-lab testing guidance - Batch agents list hydration (#260) - Batch agents list hydration - Fix web-lab terminal control sequencing - Fix web-lab conversation liveness projection - Merge pull request #257 from blumepage/codex/wonderful-mendel-main-sync - Merge wonderful-mendel updates into PR branch - Fix suggestion query regression fixture - Add web-lab parser validation cases - Fix shared architecture review gaps - Show completed todo lists on finished cards - Require conversation refresh worker - Port menu bar conversation row rendering - Mark main sync branch pushed - Track wonderful-mendel parity sync - Move web-lab snapshots into terminal rail - Add web-lab parser validation skill case - Add web-lab TUI snapshot capture - Move web-lab snapshots into terminal rail - Allow feature flags when tracking is disabled - Add web-lab parser validation skill case - Defer local insights eval runner references - Port insights control storage schema - Port improve app-core main parity - Allow feature flags when tracking is blocked (#256) - Allow feature flags when tracking is blocked - Track main parity follow-up tasks - Restore insights control artifacts - Add web-lab TUI snapshot capture - Run conversation refresh ingest in utility worker - Run parser binding off the Electron main process - Bound conversation startup discovery in app core - Render menu bar status badges like main - Delay conversation backfill after boot ingest - Port native menu bar status parity - Port settings subpage analytics parity - Port desktop release hardening parity - Port native shortcut and pinned hit area parity - Gate menu bar status item behind PostHog flag (#255) - Add menu bar status item (#254) - Merge pull request #226 from blumepage/codex/shared-product-migration - Prioritize inactive project labels - Mark PR readiness tracker complete - Tighten PR readiness tracking - Tune conversation title size - Centralize Gelica heading weights - Use medium Gelica conversation titles - Let Gelica heading weights apply - Try bold Gelica conversation titles - Tune conversation title weight and clipping - Center conversation title row content - Align conversation title row - Use medium weight for Gelica headings - Use shared Gelica heading font - Add CodeRabbit architecture review guardrails - Tune conversation title size - Soften conversation title typography - Reuse conversation card header in detail views - Guard duplicate web-lab terminal tabs - Tidy web-lab tab controls and inactive metadata - Add web-lab SQLite DB inspector - Tidy inactive card metadata layout - Refine inactive history card chrome - Fix completed tool activity state - Document bounded web-lab agent tests - Refine inactive card metadata layout - Focus inactive conversation cards on titles - Fix web-lab inactive fixture mutations - Reuse agent card for inactive history - Scope web-lab projects to active session - Fix web-lab project worktree identity - Support terminal control key tokens - Add web-lab terminal controls - Add web-lab VPS preflight and deploy scripts - Fix web-lab conversation card parity - Remove terminal-driven conversation refresh - Align web-lab parser contract with desktop - Fix web-lab Claude conversation ingest - chore: release v1.0.52 - Desktop perf: move transcript parsing off the main process, bound startup scanning (#247) - Fix web-lab parity feature gaps - Sanitize web-lab runner proxy headers - Route web-lab runner requests through Worker - Proxy web-lab runner through Worker - Add Cloudflare web-lab deploy - Onboarding agent in framework (#239) - Fix web-lab runner ingest parity - Fix stable canary baseline release (#237) - Add web-lab visual parity harness - Avoid broad VPS setup snapshots - Fix web-lab VPS conversation ingest - Update Hostinger lab VPS recovery status - Document Hostinger VPS inventory - [codex] Build MCP improvement agent control plane (#225) - Bound VPS runner SSH connect timeout - Align web-lab chrome with Blume theme - Fix web-lab inactive detail parity - Restore rich inactive conversation detail - Allow runner SQLite beside legacy desktop DB - Fix setup project and web-lab parity - Tighten web lab host parity - Update shared migration review guardrails - Guard desktop sqlite legacy storage reads - Align runner and web host review surface - Fix parser identity and apply path review issues - Fix stale parser terminal state projection - Fix Claude parser failure projection - Fix active agent state projection - Fix stale agent visibility and codex project fallback - Address shared migration review comments - Address shared migration review findings - Mark PR readiness checklist complete - Fix parser remap and desktop row guards - Merge wonderful mendel base into migration PR - Track PR merge readiness plan - Mark migration goal complete - Finalize shared migration audit - Add e2e warm deep-link proof path - Mark close trigger pushed in tracker - Add e2e native close trigger - Quarantine legacy conversation parsers - Mark quit IPC guard pushed in tracker - Update migration tracker after quit IPC guard - Guard desktop IPC during native quit - Mark data safety proof pushed in tracker - Update migration tracker after data safety proof - Add desktop migration data preservation test - Mark parser fix pushed in migration tracker - Update migration tracker after Electron smoke - Fix parser compact UTF-8 truncation - Update migration tracker after validation smoke - Update migration tracker after provider parity - Add provider projection parity fixtures - Update migration tracker after parser cleanup - Remove session JSONL fallback parsing - Add Codex live parser-binding fixture - Update canonical parser boot log - Update migration tracker after startup policy slice - Move desktop startup policy to app core - Align migration checklists with current boundaries - Update migration tracker after setup slice - Move desktop setup facade policy to app core - Delete stale Improve service entrypoint - Clarify migration progress tracker - Update migration tracker after Improve projection slices - Route desktop Improve suggestions through shared adapter - Share web Improve projections and progress events - Update migration tracker after settings IPC slice - Move desktop settings IPC policy to app core - Track desktop Improve adapter worker - Track web Improve and settings IPC workers - Update migration tracker after Improve and Claude slices - Preserve Claude task ids in canonical parser - Move runner Improve suggestion actions to app core - Track next shared migration workers - Update migration tracker after Cursor and window slices - Move native window bounds policy to app core - Require canonical parser for Cursor sessions - Remove stale Codex parser telemetry helper - Track native window bounds worker - Track active migration agents - Track Cursor fallback deletion worker - Add Cursor parser binding coverage - Track Cursor parser prerequisite worker - Require canonical parser for Claude sessions - Track Claude Cursor parser findings - Track Claude Cursor parser explorers - Require canonical parser for OMP sessions - Track OMP fallback deletion worker - Add OMP live parser binding coverage - Track OMP parser coverage worker - Require canonical parser for Pi sessions - Move usage provider key policy to app core - Track usage policy worker - Remove Codex TypeScript parser fallback - Track Codex parser fallback cut - Declare desktop sidecar host dependency - Track parser fallback deletion explorer - Wire runner Improve runs through shared signal pipeline - Track runner Improve pipeline worker - Add shared Improve signal pipeline storage - Add OMP parser projection parity fixture - Track active migration worker wave - Add Pi parser projection parity fixture - Track shared migration takeover checklist - Add runner Improve extraction adapter - Add Codex parser projection parity fixture - Mark shared web Improve run PR update - Route web Improve runs through shared use case - Track web Improve shared run worker - Fix web lab Tailwind build dependency - Mark web Improve apply evidence PR update - Mark web Improve apply evidence committed - Enable web Improve apply evidence routes - Mark Improve metadata PR update complete - Track web Improve apply parity worker - Persist shared Improve suggestion metadata - Track web Improve parity worker queue - Mark setup context tracker items complete - Update migration tracker after setup context - Use setup store for Improve setup context - Update migration tracker with sidecar verification - Track next shared-product migration batch - Update migration tracker after conversation refresh cut - Route runner conversation ingest through app-core refresh - Certify desktop native adapter boundaries - Update migration tracker with shared boundary evidence - Update migration tracker after boundary proofs - Certify desktop usage provider boundary - Guard native harness execution boundary - Track next migration worker batch - Update migration tracker after web Improve parity - Route web Improve actions through runner - Move project path identity into shared package - Tighten desktop usage architecture guard - Track parser parity verification - Persist runner session lifecycle metadata - Certify shared setup desktop boundary - Move conversation boot ingest hooks into app core - Move setup IPC error policy into app core - Move IPC registration out of desktop entrypoint - Track native bootstrap migration progress - Move native bootstrap out of desktop entrypoint - Mark latest migration checklist items complete - Update migration takeover checklist - Move Improve IPC policy into app core - Move native deep links out of desktop entrypoint - Default VPS runner storage to SQLite - Move usage IPC policy into app core - Move native lifecycle out of desktop entrypoint - Make Improve helpers renderer-safe - Fix unsupported usage login gating - Move native window controller out of desktop entrypoint - Move non-window IPC registration out of desktop entrypoint - Move Improve IPC registration out of desktop entrypoint - Move settings and DB IPC out of desktop entrypoint - Move usage IPC registration out of desktop entrypoint - Move referral activation gate to app core - Update migration PM target queue - Make Claude canonical parser authoritative - Make Codex canonical parser authoritative - Route Cursor conversations through canonical parser - Move setup browser projection to app core - Move improve sidecar view projection to app core - Move usage report view projection to app core - Move desktop improve facade composition to app core - Move agent conversation view projection to app core - Move runner improve settings to app core - Certify remaining desktop adapters - Move conversation IPC policy to app core - Certify desktop LLM adapter - Certify desktop improve adapter - Move conversation background service to app core - Certify desktop usage adapters - Remove desktop conversation parser test facade - Move desktop setup facade out of main - Move harness self-run matching to projects identity - Tighten desktop main architecture guard - Move desktop identity host to app core - Move desktop install host to app core - Move desktop insights runtime to app core - Move desktop conversation provider host to app core - Move app shell settings policy to app core - Move desktop setup use cases to app core - Move Chatwoot support policy to app core - Move referral client workflow to app core - Consolidate desktop JSONL provider adapters - Keep usage login execution in desktop adapter - Route Claude sessions through canonical parser - Update usage gap checklist for app usage host - Move app usage host lifecycle to app core - Move conversation main runtime to app core - Move legacy override migration policy to app core - Move conversation watch host to app core - Delete thin Improve desktop wrappers - Move Improve harness process runner to app core - Move Blume home JSON store policy to app core - Move LLM gateway policy to app core - Move referral claim policy to app core - Move app usage flush cadence to app core - Move conversation ingest runtime to app core - Inline install native adapters - Inline Improve guidance adapter - Inline Improve setup context adapter - Move Improve settings persistence policy to app core - Move conversation projection types to shared model - Delete unused desktop auto-title wrapper - Move Improve planning guidance into app core - Inline conversation title file adapter - Move desktop main tests to regressions - Inline Improve harness registry adapter - Move Claude keychain service name to app core - Inline install filesystem adapter - Delete install harness wrapper modules - Consolidate local JSONL providers - Move Improve desktop facade into app core - Move harness install runtime into app core - Track ninth-wave desktop migration reductions - Move Improve main use cases into app core - Move cached settings stores into app core - Move Cursor composer state runtime into app core - Track eighth-wave desktop migration reductions - Move local JSONL provider host into app core - Fix Improve run use-case test typing - Move Improve run use cases into app core - Track seventh-wave desktop migration reductions - Move provider usage host orchestration into app core - Move conversation title use cases into app core - Track sixth-wave desktop migration reductions - Move conversation resume dispatch into app core - Move Claude install settings write plan into app core - Fix Improve facade test typing - Track fifth-wave desktop migration reductions - Move provider usage fetch projection into app core - Move Improve main facade into app core - Fix ingest plan test narrowing - Track fourth-wave desktop migration reductions - Move conversation ingest payload planning into app core - Move Improve run composition into app core - Delete desktop usage setup telemetry wrapper - Track third-wave desktop migration reductions - Fix watch runtime event source typing - Move Claude usage auth probe policy into app core - Move Improve harness capture policy into app core - Move conversation watch setup into app core - Track Claude external state runtime migration - Move Claude external state runtime into app core - Track auto-title runtime migration - Move auto-title queue runtime into app core - Track second-wave desktop migration reductions - Move Improve suggestion actions into app core - Move OMP session provider policy into app core - Track settings subpage analytics (#229) - Delete unused desktop usage connect wrapper - Update desktop migration gap checklist - Move provider usage HTTP runtime into app core - Move Cursor session provider policy into app core - Move install and improve apply runtimes into app core - Document larger parallel migration tracks - Move Claude session provider policy into app core - Move Codex session provider policy into app core - Move Improve scheduler runtime into app core - Move session JSONL provider policy into app core - Move Improve view use cases into app core - Move conversation watcher runtime into app core - Fix conversation use case test helper typing - Move Improve pipeline orchestration into app core - Move conversation refresh use cases into app core - Move provider usage runtime orchestration into app core - Delete desktop title regeneration wrapper - Move Cursor usage flow into app core - Move Codex usage flow into app core - Move OMP provider iteration policy into app core - Delete Pi transcript provider shim - Move Improve promote and plan policy into app core - Reuse session JSONL provider for Pi transcripts - Move Claude usage flow into app core - Delete desktop setup browser shims - Move Improve prompt payload mapping into app core - Move Improve signal payload mapping into app core - Move Claude transcript meta policy into app core - Move Improve harness registry into app core - Move conversation request defaults into app core - Move conversation transcript option projection into app core - Move Cursor disk sub-agent prompt projection into app core - Move Electron setup version stamp into setup model - Move Improve extraction failure shaping into app core - Move Codex usage fetch flow into app core - Move Cursor state path planning into app core - Move parser malformed telemetry projection into app core - Move Codex refresh attempt policy into app core - Move Cursor composer cache policy into app core - Move Claude direct refresh policy into app core - Move Improve CLI adapter factory into app core - Move Cursor usage request planning into app core - Move fixture harness result shaping into app core - Reuse setup install state types in app core - Move Claude Keychain read error policy into app core - Move parser harness match validation into binding - Delete Pi parser adapter wrapper - Move Claude credential cache projection into app core - Move Improve scheduler projection into app core - Move app usage window mode projection into app core - Move harness CLI override policy into catalog - Move Claude Keychain credential projection into app core - Move conversation watch index into app core - Move provider login projection into app core - Move deep-link telemetry projection into app core - Reuse shared Improve harness JSON serialization - Move deep-link route parsing into app core - Move Improve evidence projection into app core - Move Improve planning operation projection into app core - Move session JSONL source meta policy into app core - Move harness CLI JSON run policy into app core - Move provider usage auth retry policy into app core - Update desktop main migration checklist - Delete desktop canonical parser projection wrapper - Move Improve view mappers into app core - Update parallel migration integrator workflow - Move Claude Desktop title writeback projection into app core - Move startup install gate into app core - Move Cursor approval config projection into app core - Move provider usage unwrap policy into app core - Move public settings guard into app core - Move provider usage request planning into app core - Move conversation branch projection into app core - Move Improve harness run specs into app core - Move provider login launch planning into app core - Move OMP source planning into app core - Move install state codec into setup model - Document parallel migration integrator workflow - Move app usage runtime tracking into app core - Move Improve clustering reconciliation into app core - Move OMP source version projection into app core - Move Improve planning selection into app core - Move provider parsed conversation projection into app core - Move install copy target projection into harness catalog - Move Improve harness trace shaping into app core - Reuse shared install error outcomes - Move Claude usage projection into app core - Move conversation watch ignore policy into app core - Move Cursor transcript eligibility into app core - Document parallel migration PM cadence - Move fixture harness builders into app core - Move Codex usage projection into app core - Move Cursor usage projection into app core - Move install copy root resolution into harness catalog - Move install copy metadata into harness catalog - Move harness CLI policy into app core - Move terminal launch planning into app core - Move referral request policy into app core - Move identity profile projection into app core - Move usage footer harness metadata into catalog - Move canonical parser adapter into app core - Move Codex auth refresh projection into app core - Move harness runs path identity into shared package - Move conversation read service into app core - Move conversation title actions into app core - Move conversation list projection into app core - Move Claude credential cache policy into app core - Move Claude CLI usage helpers into app core - Move install harness outcome policy into app core - Point insights regression at shared packet builder - Move dev display naming into app core - Move improve picker filtering into app core - Move improve guidance fallback into app core - Guard parser shadow flag removal - Delete desktop improve queue wrapper - Guard deleted desktop product wrappers - Move usage login policy into app core - Move improve packet reader into app core - Move improve retrieval ports into app core - Move parser projection into app core - Route Codex provider through parser binding - Guard desktop db folder boundary - Delete desktop conversation git shim - Route OMP provider through parser binding - Use harness catalog in improve metadata - Move desktop migrations to storage sqlite - Route Pi provider through parser binding - Move git labels and web-lab tabs to shared packages - Document parallel migration agent workflow - Move conversation ingest out of db folder - Move legacy override adapter out of db ingest - Move legacy override parsing to app core - Delete desktop db row types - Move legacy overrides to storage - Delete unused desktop db repositories - Delete desktop improve repository - Move improve cluster mutations to storage - Move improve clustering reads to storage - Move improve promotion cluster reads to storage - Move improve signal writes to storage - Move improve suggestion writes to storage - Move improve duplicate writes to storage - Move improve harness call writes to storage - Move improve run creation to storage - Move improve run updates to storage - Move improve pipeline signal reads to storage - Move improve dedupe reads to storage - Move improve index reads to storage - Move improve duplicate reads to storage - Move improve suggestion state to storage - Move improve run detail reads to storage - Move improve run view reads to storage - Move improve signal list reads to storage - Move improve pipeline lookups to storage - Move improve promotion reads to storage - Move improve candidate cluster reads to storage - Move improve packet reads to storage - Move last activity parsing to app core - Move conversation view fanout to storage - Move conversation action lookups to storage - Route improve scheduler reads through storage - Move conversation row reads to storage - Move conversation existence check to storage - Move desktop project list reads to storage - Move active user turn reads to storage - Move conversation transcript reads to storage - Move improve suggestion views to app core - Delete unused desktop source repository - Move conversation action writes to storage - Move stale conversation aging to storage - Route provider title apply through storage - Move skipped conversation ingest writes to storage - Route desktop conversation replacement through storage - Move conversation persistence policy into domain model - Move ingest row indexing into app core - Move transcript replacement mapping into app core - Move conversation replacement projection into app core - Use app core source cursor projection in ingest - Move skipped ingest projection into app core - Route ingest source checkpoints through storage port - Move Claude summary aggregation into app core - Move OMP parent sub-agent enrichment into app core - Move Cursor summary aggregation into app core - Move Codex summary aggregation into app core - Move session JSONL summary aggregation into app core - Move Improve harness output parsing into app core - Move Improve planning source turns into app core - Move Improve harness adapter selection into app core - Move conversation ingest skip planning into app core - Move Improve view mappers into app core - Move session title append file flow into app core - Move Claude external state discovery into app core - Move Claude external state parsing into app core - Move Claude block projections into app core - Move Cursor block projections into app core - Move session jsonl projections into app core - Move Codex response item projection into app core - Reuse app core setup browser in runner - Wire terminal resize through web runner - Move Cursor disk subagent projection into app core - Reuse shared Cursor parser for subagent prompts - Move Claude session line parsing into app core - Move Cursor session line parsing into app core - Move Codex session line parsing into app core - Move todo replacement planning into app core - Move session JSONL line parsing into app core - Move OMP child subagent projection into app core - Move OMP subagent merge policy into app core - Move provider stop marker policy into app core - Move ingest cursor lookup to sources repository - Move Cursor todo display policy into app core - Move improve setup context into app core - Move install policy into app core - Isolate Cursor composer state reader - Route web transcripts through shared storage - Route Electron setup artifacts through shared storage - Move desktop setup browser into app core - Route web setup browser through runner scanners - Route web improve settings through app core - Move transcript persistence projection to app core - Move conversation persistence policy to app core - Route web harness list through runner storage - Route web usage through runner storage - Share conversation watcher path policy - Move conversation provider path fallbacks to app core - Share conversation provider source types - Route web setup changes through app core - Move setup apply undo to app core - Share setup file access enforcement - Move source cursor freshness to storage port - Move desktop meta storage to shared port - Route desktop settings through storage port - Route settings IPC through storage port - Share global harness setup scan - Share setup project scan composition - Move setup project traversal to setup scanners - Move Improve target allowlist to app core - Move usage credential refresh policy to app core - Share setup browser category listing - Move title generation to app core - Move dev format browsing to setup scanners - Move resume row projection to app core - Share transcript pagination limit policy - Move Codex workspace display to app core - Move conversation child view helpers to app core - Use app core for app usage totals - Share setup dev format path policy - Share setup scan root policy - Share setup path allowlist policy - Share setup category grouping - Move setup entry scanning into shared package - Move Codex provider helpers to app core - Share tool use interruption predicates - Move OMP session helpers to app core - Move Codex lifecycle helpers to app core - Move Claude external state rules to app core - Move Cursor external state parsing to app core - Move title writeback orchestration to app core - Delete desktop conversation cache wrapper - Delete desktop conversation path wrapper - Use shared path helpers in desktop providers - Remove desktop parser shadow path - Move JSONL filesystem helpers into filesystem local - Point desktop transcript text helpers at app core - Move conversation source version checks into app core - Move conversation summary cache into app core - Delete extracted conversation helper wrappers - Move conversation JSON parsing into app core - Move subagent collection into app core - Move user turn derivation into app core - Move conversation todo collection into app core - Move transcript text shaping into app core - Move conversation activity classification into app core - Move project path identity into app core - Move title writeback rules into app core - Move conversation resume actions into app core - Move terminal preference normalization into app core - Move setup browser policy into setup scanners - Move desktop app usage persistence to shared storage - Move runner conversation refresh into app core - Move improve setup notes into setup scanners - Move improve setup discovery specs into setup scanners - Move improve setup conventions into setup scanners - Move improve apply undo into app core - Move retroactive improve scan into app core - Move improve scheduler decisions into app core - Move improve run queue into app core - Move improve settings normalization into app core - Move improve conversation packet builder into app core - Move improve usage capture into app core - Move improve prompt builders into app core - Move usage report orchestration into app core - Move improve parsers into app core - Move improve scoring helpers into app core - Move improve config into app core - Move improve diff patch helper into app core - Move improve session gate into app core - Move app usage service into app core - Add app usage intervals to shared storage - Move app usage interval logic into app core - Move usage setup telemetry into app core - Move usage parsing into app core - Use harness catalog in improve adapters - Use harness catalog in shared UI - Use harness catalog for desktop setup roots - Move setup filename helpers to scanner package - Accept process env in parser resolver - Use shared SQLite storage in runner - Add shared architecture guardrails - Use harness catalog in setup scanner - Move parser parity diff into shared binding - harness-lab: add web-search, subagent, compaction, worktree scenarios - Align setup guidance classification - Extract shared harness parser resolver - Add architecture patterns guide from main - harness-lab: add codex plan-mode + goal-mode scenarios - docs: add architecture patterns guide for new feature work (#205) - format-explorer Cases: resizable panes + cleaner script/JSON layout - harness-case: saved-cases rail (seeded) + fix Step-union approve collapse - format-explorer Cases: compact Case card, rich Expected designer, JSON sidebar - harness lab: case designer lives in format-explorer (the lab UI), not web-lab - Fix pinned compact hit area (#204) - Add Windows/Linux DevTools shortcut for opening the dev window (#201) - web-lab: Case Builder pane + runner /parsed (live parser output) - Update parity plan for Chatwoot main sync - docs: harness-lab parser certification plan (case = harness-independent test) - Merge remote-tracking branch \'origin/main\' into codex/wonderful-mendel-main-parity - Track launch-at-login toggle in PostHog (#199) - chore: release v1.0.51 - Merge pull request #175 from blumepage/codex/chatwoot-feedback - fix: write canary updater metadata before aliases - Update parity plan for daily main sync - Merge remote-tracking branch \'origin/main\' into codex/wonderful-mendel-main-parity - Merge remote-tracking branch \'origin/claude/wonderful-mendel-cf987f\' into codex/wonderful-mendel-main-parity - chore: release v1.0.50 - onboarding: refresh the "Guidance, not just glances" step (#185) - insights: skip conversations with fewer than 3 user messages (#183) - Add deterministic desktop canary versioning (#178) - release: stop signing Windows/Linux installers with the Apple cert (#187) - fix: portal Dialog to body so it isn\'t clipped by transformed ancestors (#184) - Identify harnessrun by identifier ID (#179) - chore: release v1.0.49 - chore: release v1.0.48 - Address remaining Chatwoot review nits - Merge remote-tracking branch \'origin/main\' into codex/chatwoot-feedback - Address Chatwoot review feedback - fix: gate startup scans behind mac updates - Snooze chat email prompt after skip - Attach chat email prompt to composer - fix: pause active conversation scans before mac updates - web-lab terminal: launch PTY at a real size + replay the boot prompt - Show unread count on chat card - Move chat email prompt above composer - Add chat email capture and unread badge - Recent first in retroactive runs (#176) - Add Chatwoot feedback chat - fix: quiet watchers during mac update staging - Make Improve tab controls scroll with suggestions (#174) - chore: mark mac updater staging logs - Update parity plan for latest main sync - Merge remote-tracking branch \'origin/main\' into codex/wonderful-mendel-main-parity - fix: gate mac update restart on native staging - Update wonderful-mendel main parity plan - Merge latest origin/main into wonderful-mendel parity - Refine Improve beta banner layout (#171) - Merge origin/main into wonderful-mendel parity - Reduce conversation refresh CPU usage (#169) - [codex] Add insight run usage and smart plan selection (#170) - web-lab terminal: multi-tab with a + menu (shell by default, claude/codex on demand) - web-lab terminal: size the remote PTY to xterm (fix TUI cursor misalignment) - vps runtime: set TERM on harness PTYs (fix inline/append TUI rendering) - [codex] Fix suggestion detail scrolling and actions (#165) - Merge pull request #164 from blumepage/codex/improve-feedback-pinned-controls - Address CodeRabbit feedback - web-lab: real xterm.js terminal (clean harness-TUI rendering) - [codex] Refine pinned hover conversations - Merge origin/main into improve feedback branch - web-lab: serve entrypoint + CORS + real-home vps mode (run the web-lab on a real VPS) - feat(insights): higher-quality suggestions + retroactive replay scan (#161) - STATUS: Phase 10 exit criteria met (snapshot wired); 159 package tests - runner: expose snapshotWorkspace (Phase 10 "sessions can be snapshotted") - STATUS: Phase 9 vps runtime live-verified; runtime-swap (memory+vps) proven - improve feedback and pinned controls - vps runtime: IdentitiesOnly + dedicated known_hosts (live-verified vs a real VPS) - Flower themes with referral-gated unlocks (#127) - Add @blume/workspace-runtime-vps (SSH-backed) + wire into the runner (Phase 9/12) - Share the canonical parser across desktop + web; add live-session input (Phase 7/9/10) - Make the agents conversation list host-driven (item 42 / state dedup) - Broaden shared shadcn primitives + adopt where hand-rolled (item 36) - web-lab: fixture transcript fallback so any conversation opens - Setup deep links: honor /setup/:source[/entries/:entry] + /setup/project/:id (item 3) - web-lab: render the shared InactiveView via "Show inactive" - Inactive view: single header + rich rows (items 9, 10) - Improve resolved-suggestions sub-page (item 13) + previews use real SidecarApp (item 2) - Pin macOS release signing to pre-26 Xcode (#157) - Remove re-export shims; import directly from @blume/sidecar-ui - Unify the conversation detail: rich transcript shared by both shells (item 11) - Pin macOS release signing runner (#155) - Restore Setup parity: CategorySection, recent projects, harness filter (items 5,6,7,8) - Render suggestion diffs with @pierre/diffs (items 14, 15) - Fix macOS release artifact signing validation (#154) - Restore rich Setup file viewing (items 4, 5) - Harden macOS updater safety before stable (#153) - Host shadcn primitives (button/badge/dialog) in shared UI - Fix Improve suggestions vanishing on desktop + restore version - [codex] Track usage setup telemetry (#152) - Restore real Improve toggle/settings + share the usage footer - Fix canary macOS update metadata aliases - Make macOS repair shim opt-in (#150) - Harden PostHog survey response payloads (#144) - Move keychain instructions into ghost button (#148) - Merge pull request #147 from blumepage/codex/fix-evidence-excerpts - Turn the tab bar into a back bar on sub-pages - Fix evidence excerpt rendering - Render the shared SidecarApp from the desktop; delete the 5 per-route shims - Parameterize SidecarApp as the single full-app composition - Move real Improve + Setup views into shared package - Fix top PostHog errors with safer parsing and recovery (#143) - Shared sidecar UI: one component set across desktop + web-lab - feat(insights): show emerging patterns in the Improve tab - [codex] Fix canary update restart handoff (#142) - Merge pull request #141 from blumepage/claude/usage-terminal-pref-and-dev-states - Merge main into usage-terminal-pref-and-dev-states - feat(usage): link Keychain CTA to the macOS docs page - Merge pull request #140 from blumepage/codex/posthog-staff-opt-out - Make PostHog opt-out setter transactional - feat(dev): add Usage states gallery to the Dev tab - fix(usage): honor the saved terminal preference for provider sign-in - Add staff PostHog opt-out dev page - feat(usage): open Keychain Access for Claude credential grants - chore: release v1.0.47 - Merge pull request #128 from blumepage/olav/bsi-58-insights-cli-path-resolution - fix(insights): resolve harness CLIs via a one-time interactive-shell PATH probe - Open inactive conversations in transcript view - Merge pull request #124 from blumepage/claude/awesome-easley-bc8d52 - Fix: pinned mode floats over other apps\' fullscreen again - Remove em-dashes from user-facing copy - Merge remove-electron-mcp - Remove blume_electron MCP server setup - Merge pull request #116 from blumepage/claude/distracted-murdock-15b3c5 - Improve: robust settings.json detection for the hook warning - Improve: allowlist Claude headless OAuth token in the analysis-child env - Improve: fail loudly when the analysis CLI errors (don\'t show empty results) - Improve: clearer off-state for the Automatic improvements row - Improve: don\'t truncate real edit targets (raise read cap to 64k) - Revert: drop analysis-child tool restriction that broke Claude Code - Improve: louder confirmation for hook/settings.json suggestions - Improve: harden Apply/undo + analysis child from extra review - Improve: alias electron to test stubs in vitest config - Improve: document accepted residual TOCTOU + schema intent - Improve: keep provider CLI auth keys in the analysis child env (#8) - Improve: pipeline/undo/setup hardening from PR review - Improve: accurate privacy/email copy + trim involve-note PII - Improve: renderer-side correctness guards from PR review - Improve: snoozed NULL-timer rows hidden from both lists; artifacts fallback - Improve: harden Apply — path allowlist, app-side base hash, atomic rollback - Merge pull request #101 from blumepage/codex/stabilize-claude-usage-keychain - Merge remote-tracking branch \'origin/main\' into claude/distracted-murdock-15b3c5 - Docs: spec reflects See-evidence on the preview page - Align Codex refresh metadata with CodexBar - Improve: route "More involved" form to the Get involved survey (BSI-51) - Improve: identify the email on "More involved" submit (BSI-51 partial) - Improve: settings/empty-state polish + harness semantics + error capture - Address CodeRabbit usage review - Improve: drop CodeRabbit/Greptile artifacts for now (BSI-48) - Improve: PostHog tracking for the improve feature (BSI-46) - Merge pull request #98 from blumepage/codex/harness-title-menu-posthog - Merge main into harness title menu PR - Improve: empty state matches the no-agents page (BSI-49) - Improve: remove the /blume command for now (BSI-47) - Merge remote-tracking branch \'origin/main\' into claude/distracted-murdock-15b3c5 - Improve: remove dev single-conversation promotion (use real thresholds) - Dev: button designs gallery (20 styles × full variation matrix) - Merge pull request #117 from blumepage/codex/remove-electron-mcp-testing - Improve: collapse the IMPROVE row into a single button - Improve: harnesses-to-improve is opt-out (all on by default) - Improve: fix "Turn on" no-op against an older settings shape - Improve: Configure button + settings page (scopes/harnesses/artifacts/blume) - Merge pull request #118 from blumepage/codex/codex-subagent-parser - Show Codex approval child sessions - Reuse SuggestionCard/Preview for resolved suggestions; full-path diff header - Parse Codex subagent session metadata - Fix resolved-page crash guard, center feedback content, pin involve card - Address follow-up harness title review - Suggestions history + undo, and a "get involved" feedback form - Address harness title review feedback - Merge main into harness title menu PR - Remove Electron MCP testing path - Merge pull request #113 from blumepage/claude/conversation-component-main - Tabs: add top-right bubble badge (count or empty dot) to subheader tabs - Address conversation transcript review feedback - Fix migration schema test expectation - Evidence: show all raw excerpts (user/assistant/tool), not just user messages - Suggestions card: occurrence count as a right-floating tooltip badge - Suggestions: drop em-dashes from copy, move occurrence count to card subheader - Suggestions: show occurrence count on cards + a "See evidence" sub-page - Improve: reframe dialog around privacy, add reusable Dialog, wire the scheduler - Insights planner: offer skill/hook/doc targets so it stops defaulting to rules - Suggestions: scrollable preview, hover-chevron summary, github-light diff - Settings mock for analyzing agents chats - Preview diff: keep 3-line context (collapse rest) instead of full file - Preview diff: generate full-context patches (no "N unmodified lines") - Preview diff: main-thread @pierre/diffs, custom header, expand context - Preview diff: @pierre/diffs with worker highlighter + rose-pine-dawn theme - Suggestions: footer actions, title-only header, themed wrapping diff - Suggestion preview: render diffs with @pierre/diffs (unified/stacked) - Suggestions: rename tab to Improve, fix AGENTS.md type, card design gallery - Merge remote-tracking branch \'origin/main\' into claude/distracted-murdock-15b3c5 - Suggestions: SUGGESTIONS section header + card icons/glyphs, friendlier preview - Compact sidecar subheader tabs - Suggestions: app-aligned compact buttons with icons - Suggestions: agent-card-aligned card + Preview page - Signal pipeline dev page: run/phase traces + exclude Blume\'s own harness runs - Add signal-based suggestions pipeline (V1) - Add conversation transcript component - Remove root lint task - Filter expected child-process-gone telemetry - Stabilize Claude usage OAuth refresh - Update testing guidance - Merge pull request #100 from blumepage/codex/claude-approval-running-state - Merge main into stale approval PR - Project skills & rules (3) (#104) - Windows support (#74) - Stabilize Claude usage keychain reads - Fix stale Claude approval status - Add harness title menu controls - Merge pull request #97 from blumepage/codex/improve-blume-quit - Merge main into quit shutdown PR - Make conversation scanning cancellation-aware - Merge pull request #90 from blumepage/codex/posthog-electron-logging - Harden desktop logging safety. - Publish canary updater metadata aliases - Fix desktop logging test mocks - Merge remote-tracking branch \'origin/main\' into codex/posthog-electron-logging - Improve app quit shutdown - Harden Claude repair terminal flow - Add Pino structured desktop logging - Merge pull request #94 from blumepage/codex/dev-badge-tooltip - Add dev badge conversation details - Harden Claude keychain repair CTA - Repair Claude keychain access from usage CTA - Merge pull request #92 from blumepage/codex/footer-usage-remaining-bars - Address PostHog logging review risks - Tune usage meter neutral color - Merge remote-tracking branch \'origin/main\' into codex/footer-usage-remaining-bars - [codex] Add compact PR validation checks (#91) - Show remaining usage bars and shared footer - Isolate dev Electron user data - Add PostHog logging to Electron main - [codex] Fix pinned window expansion bounds (#88) - Add canary desktop icon - Write updater metadata for canary desktop builds - Fix macOS canary updater metadata generation - Respect no-tag manual canary releases - Allow manual canary release dispatch from main - Add desktop canary update channel - Use static dev app icon asset - Merge pull request #79 from blumepage/codex/fix-binary-artifact-preview - fix: hide repository internals in storage - fix: preview binary artifacts by range - Fix Claude keychain usage, add dynamic connect CTAs, harden repair shim (#76) - Add dev mode app icon banner - Merge pull request #78 from blumepage/codex/fix-harness-lab-prod-deploy - fix: deploy format explorer assets to prod - [codex] fix preview checkbox trigger - Merge pull request #75 from blumepage/codex/format-explorer-redesign - Redesign format explorer workbench - [codex] Make feedback tab always available (#72) - Add harness usage indicators (#71) - fix: harden harness lab runner deploy (#69) - fix: retry harness lab runner ssh deploy (#68) - Shorten generated titles (#66) - Merge pull request #67 from blumepage/codex/harness-lab-runner-rust-hotfix - fix: update harness lab runner rust toolchain - Merge pull request #53 from blumepage/claude/condescending-mcclintock-bbccb7 - Merge remote-tracking branch \'origin/main\' into claude/condescending-mcclintock-bbccb7 - fix: bound draft preview cleanup - fix: complete cursor run calibration - fix: wait for cursor trust transition - fix: classify active cursor trust prompt - fix: start cursor cancelled runs with initial prompt - fix: wait before sending first prompt - fix: send tmux input to active pane - fix: stabilize cursor interactive runs - fix: avoid stale cursor trust prompts - fix: keep cursor in interactive trust flow - fix: launch cursor with trusted auto model - fix: answer cursor workspace trust prompt - fix: detect gemini idle prompt - fix: settle idle state by classification - fix: classify tall terminal prompts - fix: support cursor agent version probes - fix: harden runner artifacts for gemini and omp - fix: add parser lineage and resilient finalization - fix: parse codex plan todos - fix: parse gateway harness session artifacts - chore: release v1.0.46 - Merge pull request #62 from blumepage/codex/macos-repair-shim - fix: classify parser activity after enrichment - fix: parse codex session events - Sign mac repair shim relaunch helper - fix: parse claude task state artifacts - fix: show settings secret status publicly - feat: add versioned harness parser state - Use direct relaunch helper in mac repair shim - Allow stable fallback for missing canary artifacts - feat: improve file preview rendering - Fix macOS repair shim relaunch - feat: improve storage tree previews - feat: finish harness lab explorer and runner - Allow canary desktop version override - Document update canary IP fallback - Allow canary desktop artifact uploads - Add mac update canary routing - Harden macOS repair shim packaging - Add CodeRabbit mac updater review guardrails - Address macOS repair shim review nits - Add macOS updater repair shim - chore: release v1.0.45 - Fix mac updater handoff (#60) - feat: record skipped harness runs - fix: show harness coverage blockers - fix: complete scenario-specific harness coverage - fix: interrupt opencode cancelled runs - fix: detect opencode interrupt state - fix: expose live terminal prefix during runs - fix: detect opencode task progress - feat: add keyed gemini and cursor harnesses - fix: finalize live terminal status - feat: upload live terminal stream - fix: fail runs when upload is blocked - fix: scrub larger harness artifacts - fix: let standard scenario observe idle - fix: timeout and log API uploads - fix: run codex without nested sandbox - fix: retry API snapshot uploads - fix: detect Codex prompt - chore: limit new harnesses to calibrated scenarios - fix: pass user LLM env to gateway harnesses - fix: detect OpenCode footer - fix: detect OpenCode idle prompt - fix: detect OMP idle footer - fix: skip OMP startup setup - fix: capture startup failures for harness runs - chore: release v1.0.44 - Harden desktop PR preview lifecycle (#55) - feat: add gateway-backed harness adapters - Add harness lab PR previews - Usage statistics (#47) - Merge remote-tracking branch \'origin/main\' into claude/condescending-mcclintock-bbccb7 - Add harness lab data service - Merge pull request #48 from blumepage/claude/objective-varahamihira-b050fa - Serialize PR preview port allocation - Retry preview script SSH install - Validate cloudflared before tunnel service setup - Fix desktop preview window layout - Retry Cloudflare quick tunnel startup - Relax preview SSH timeout defaults - Bound PR preview remote steps - Bound PR preview SSH deploys - Support a named Cloudflare tunnel for PR previews - chore: release v1.0.43 - [codex] Track visible app usage by window mode (#46) - Fix PR preview link pointing at api.trycloudflare.com - Dev-mode indicator, sandbox meta.json, and onboarding skip - chore: release v1.0.42 - Onboarding guide (#28) - chore: release v1.0.41 - Fix parser telemetry noise and dev DB isolation - Merge pull request #26 from blumepage/codex/remove-keyscan-from-preview-ssh - ci: use pinned preview ssh host key - chore: release v1.0.40 - Merge pull request #14 from blumepage/codex/bsi-3-feedback-survey-tab - Reset feedback survey thank you state - Prevent comment edits from canceling desktop previews - Remove desktop preview files on PR cleanup - Tighten feedback thank you redirect - Merge remote-tracking branch \'origin/main\' into codex/bsi-3-feedback-survey-tab - Add desktop PR preview workflow - Respect PostHog survey frequency - Add feedback thank you redirect - Show custom feedback thank you - Add feedback route loading state - [codex] Add SQLite busy timeout - Merge remote-tracking branch \'origin/main\' into codex/bsi-3-feedback-survey-tab - Add PostHog feedback survey tab - [codex] Fix desktop Sentry crashes - [codex] Fix PostHog-reported desktop errors - chore: release v1.0.39 - Run Sentry source map upload directly in CI - chore: release v1.0.38 - Fix source map CLI invocation on Windows - chore: release v1.0.37 - Avoid finalizing Sentry release per matrix job - chore: release v1.0.36 - Split desktop release source map scripts - chore: release v1.0.35 - Adjust source map uploads per platform - chore: release v1.0.34 - Allow source map CLI build scripts - chore: release v1.0.33 - Add error tracking source map uploads - Add PostHog app open attribution - Add Sentry crash reporting - chore: release v1.0.32 - Fix main process PostHog config - chore: release v1.0.31 - Track durable desktop app usage - Fade pinned logo during collapse - Refine pinned sidecar transitions - Show login toggle only when disabled - Refine pinned sidecar animation - Checkpoint pinned sidecar mode - Add launch at login setting - Merge pull request #5 from blumepage/app-active-event-posthog - App active event for posthog - chore: release v1.0.30 - Capture app errors in PostHog (#4) - feat(desktop): redesign agent-message toolbox (#3) - Add editable markdown file viewer (#1) - Fix Codex worktree project identity - chore: release v1.0.29 - Add app deep-link handling and dev tester - Add renderer routes and PostHog page tracking - chore: release v1.0.28 - chore: release v1.0.27 - feat: expose desktop download metadata endpoint - chore: release v1.0.26 - ci: annotate desktop update artifact urls - chore: release v1.0.25 - ci: use absolute paths for r2 artifact uploads - chore: release v1.0.24 - ci: publish desktop updates via cloudflare - chore: release v1.0.23 - ci: run release bundle check in bash - chore: release v1.0.22 - ci: wire release env secrets - Show sub-agent results in agent card - Add agent card tool call layout - chore: remove old fixture ignore path - chore: release v1.0.21 - Allow E2E app instances for Electron MCP - chore: release v1.0.20 - Bundle LLM auth in desktop main - chore: release v1.0.19 - Remove user LLM service overrides - chore: release v1.0.18 - chore: release v1.0.17 - Fix Windows release artifact name - chore: release v1.0.16 - Fix Linux release artifact names - chore: release v1.0.15 - Fix macOS release artifact name - chore: release v1.0.14 - Fix desktop release version bump - Document local LLM worker env - Secure LLM service requests - Fix LLM service deploy command - ci: trigger main deploy - Make main release commits create desktop drafts - Fix pnpm setup in release workflow - Merge auto-update release flow - Add desktop auto-update release flow - chore: ignore legacy browser fixture - chore: add turborepo llm service - Add conversation lifecycle regression tests - Align stopped subagent handling across harnesses - Propagate Claude agent approval state - Hide finished subagents - chore: release v1.0.13 - Detect Claude sandbox approval gates - Apply Claude task-file statuses - Resolve Claude task ids from results - Scope Claude todos to user turns - Restore Codex plan todos - Normalize Codex workspace display rows - Preserve stopped and approval states - Fix Codex lifecycle and Claude todo turns - Persist conversation state overrides by user turn - Merge branch \'main\' into HEAD - Polish sidecar UI chrome - Add real data browser harness fixtures - Merge branch \'main\' into HEAD - Add browser visual test harness - Normalize conversations around user turns - chore: release v1.0.12 - build(release): configure mac signing and notarization - test(electron): add project MCP testing skill - style(ui): update harness tile chrome - feat(ui): use shared tooltip labels - fix(conversations): use explicit approval signals - feat(dev): add Dev tab format explorer - Merge branch \'main\' into claude/elastic-elgamal-bc6505 - feat(agents): idle acknowledge flow, context line, and card action polish - chore: release v1.0.11 - Merge branch \'main\' into claude/elastic-elgamal-bc6505 - feat(db): refine todo state and source cursors - feat(db): todo lists as append-only versioned snapshots - feat(db): rename messages → events; FK to runs; run-scoped position; drop ext_json - feat(db): agent_runs per turn + per sub-agent spawn - feat(db): project identity by path; workspace on conversations; last_activity JSON; idle state - chore(rules): scope todo-list rule to multi-step work - chore: drop setup_files stub ahead of canonical artifacts schema - feat: persist conversations + setup-file state in sqlite - fix(dev): wrap electron-vite to sweep stray Electron processes - Merge branch \'claude/crazy-easley-c68941\' into main - Merge branch \'main\' into claude/crazy-easley-c68941 - feat: Setup tab with system harnesses + file viewer + skill navigation - chore: ignore *.tsbuildinfo - feat: sandbox .blume in dev and prevent stuck Dock icons on crash - Merge branch \'claude/naughty-newton-c227be\' into main - feat: install harness hooks + rules from .blume on app start - chore: release v1.0.10 - Merge remote-tracking branch \'origin/main\' into main - Merge branch \'claude/laughing-lovelace-02e93b\' into main - Merge branch \'main\' into claude/laughing-lovelace-02e93b - fix: keep claude-fs to .jsonl + fold TaskCreate/TaskUpdate into todos - chore: release v1.0.9 - ui: seed flower avatar from conversation title - chore: release v1.0.8 - ui: thin the status spinner stroke from 2 to 1.5 - feat: surface git branch (and replace status subtitle with worktree/branch) - ui: shared TopBar + improved Inactive view - feat: dicebear flower avatars next to conversation titles - ui: status badges, status config, and clock-driven live timestamps - perf: refresh dev panel and perf telemetry - feat: conversation provider refinements (cursor, omp, watch) - feat: machine identity, blume-home, and auto-title scaffolding - ui: thin the status spinner stroke from 2 to 1.5 - feat: surface git branch (and replace status subtitle with worktree/branch) - feat: dicebear flower avatars next to conversation titles - ui: status badges, status config, and clock-driven live timestamps - perf: refresh dev panel and perf telemetry - feat: conversation provider refinements (cursor, omp, watch) - feat: machine identity, blume-home, and auto-title scaffolding - chore: release v1.0.7 - fix: classify finished agents by assistant-text-vs-tool-call order - Merge branch \'claude/vigilant-ishizaka-66fdc8\' into main - feat: add LLM infra and conversation title regeneration - chore: release v1.0.6 - perf: cut conversation-list cost with caching + dev panel - analytics: wire up PostHog in renderer - chore: release v1.0.5 - ui: revert status pill back to inline dot + colored text - chore: release v1.0.4 - ci: drop snap target on linux - chore: release v1.0.3 - ui: tone down the agent card dismiss button - ci: unset empty signing env vars so unsigned builds work cleanly - chore: release v1.0.2 - ci: drop pnpm cache on the bump job - chore: release v1.0.1 - Add GitHub Actions release workflow - Iterate on agent cards: badges, OMP subagent grouping, multi-line agent text - Update application name and configuration for Blume - Rebuild sidecar UI per Figma spec with Tailwind/shadcn and live fs watching - Add agent rendering specification and enhance conversation management - Refactor conversation handling and enhance IPC communication - Implement conversation management features with IPC integration - Initial electron-vite quickstart --- extensions/blume-search/.gitignore | 2 + extensions/blume-search/.prettierrc | 8 + extensions/blume-search/CHANGELOG.md | 6 + extensions/blume-search/README.md | 50 + .../blume-search/assets/conversations.svg | 4 + extensions/blume-search/assets/icon.png | Bin 0 -> 38916 bytes extensions/blume-search/assets/messages.svg | 3 + extensions/blume-search/assets/projects.svg | 6 + extensions/blume-search/assets/setup.svg | 11 + .../blume-search/assets/suggestions.svg | 5 + extensions/blume-search/eslint.config.cjs | 8 + extensions/blume-search/package-lock.json | 3007 +++++++++++++++++ extensions/blume-search/package.json | 51 + .../src/blumeSearchClient.test.ts | 117 + .../blume-search/src/blumeSearchClient.ts | 29 + extensions/blume-search/src/helperLaunch.ts | 32 + .../blume-search/src/helperProcessClient.ts | 190 ++ extensions/blume-search/src/protocol.ts | 146 + extensions/blume-search/src/search.tsx | 185 + .../blume-search/src/searchLifecycle.test.ts | 12 + .../blume-search/src/searchLifecycle.ts | 11 + .../blume-search/src/searchModel.test.ts | 47 + extensions/blume-search/src/searchModel.ts | 61 + extensions/blume-search/tsconfig.json | 17 + 24 files changed, 4008 insertions(+) create mode 100644 extensions/blume-search/.gitignore create mode 100644 extensions/blume-search/.prettierrc create mode 100644 extensions/blume-search/CHANGELOG.md create mode 100644 extensions/blume-search/README.md create mode 100644 extensions/blume-search/assets/conversations.svg create mode 100644 extensions/blume-search/assets/icon.png create mode 100644 extensions/blume-search/assets/messages.svg create mode 100644 extensions/blume-search/assets/projects.svg create mode 100644 extensions/blume-search/assets/setup.svg create mode 100644 extensions/blume-search/assets/suggestions.svg create mode 100644 extensions/blume-search/eslint.config.cjs create mode 100644 extensions/blume-search/package-lock.json create mode 100644 extensions/blume-search/package.json create mode 100644 extensions/blume-search/src/blumeSearchClient.test.ts create mode 100644 extensions/blume-search/src/blumeSearchClient.ts create mode 100644 extensions/blume-search/src/helperLaunch.ts create mode 100644 extensions/blume-search/src/helperProcessClient.ts create mode 100644 extensions/blume-search/src/protocol.ts create mode 100644 extensions/blume-search/src/search.tsx create mode 100644 extensions/blume-search/src/searchLifecycle.test.ts create mode 100644 extensions/blume-search/src/searchLifecycle.ts create mode 100644 extensions/blume-search/src/searchModel.test.ts create mode 100644 extensions/blume-search/src/searchModel.ts create mode 100644 extensions/blume-search/tsconfig.json diff --git a/extensions/blume-search/.gitignore b/extensions/blume-search/.gitignore new file mode 100644 index 00000000000..93ece072ece --- /dev/null +++ b/extensions/blume-search/.gitignore @@ -0,0 +1,2 @@ +raycast-env.d.ts +dist/ diff --git a/extensions/blume-search/.prettierrc b/extensions/blume-search/.prettierrc new file mode 100644 index 00000000000..7e5f2930235 --- /dev/null +++ b/extensions/blume-search/.prettierrc @@ -0,0 +1,8 @@ +{ + "bracketSpacing": true, + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "singleQuote": false, + "useTabs": false +} diff --git a/extensions/blume-search/CHANGELOG.md b/extensions/blume-search/CHANGELOG.md new file mode 100644 index 00000000000..732260f850f --- /dev/null +++ b/extensions/blume-search/CHANGELOG.md @@ -0,0 +1,6 @@ +## [Initial Release] - 2026-08-14 + +- Search local Blume projects, conversations, messages, setup artifacts, and suggestions. +- Filter results using Blume's entity icons and colors. +- Open results in stable Blume or Blume Canary. +- Keep all search data local through Blume's bundled read-only search helper. diff --git a/extensions/blume-search/README.md b/extensions/blume-search/README.md new file mode 100644 index 00000000000..f9b7894862b --- /dev/null +++ b/extensions/blume-search/README.md @@ -0,0 +1,50 @@ +# Blume Search for Raycast + +Search the same projects, conversations, messages, setup artifacts, and suggestions as Blume's +in-app search. The extension starts the local search helper shipped inside Blume; the helper uses +Blume's shared search use case and a read-only SQLite adapter. Nothing is sent over the network. + +## Develop locally + +1. Install a Blume build that includes the Raycast search helper and open it once so its database exists. +2. Run `cd apps/raycast && npm ci`. The extension is intentionally excluded from the pnpm + workspace because Raycast Store CI consumes its standalone `package-lock.json`. +3. Run `npm run dev` and open **Search Blume** in Raycast. + +Stable Blume is used by default. To search Blume Canary, choose it under **Blume Application** in +Raycast's extension preferences. One helper process stays alive only while the command is open, +and its database is protected by SQLite read-only and `query_only` enforcement. + +## Store releases + +Raycast Store publishing is review-based: `ray publish` submits or updates a pull request in +`raycast/extensions`, and Raycast deploys the extension after that pull request is merged. + +The repository's **Raycast Extension** workflow validates every extension change using npm, the +same package manager used by Raycast's Store CI. To enable automatic update submissions after a +compatible Blume desktop release is stable: + +1. Sign in with `ray login` and confirm that `ray profile` reports the manifest's registered + Raycast Store handle (`olav_ljosland`). +2. Create a protected `raycast-store` GitHub environment. +3. Add `RAYCAST_TOKEN` and `RAYCAST_GITHUB_TOKEN` secrets to that environment. The GitHub token + must be able to create or update the Raycast extensions pull request. +4. Run the workflow manually with **submit** enabled for the initial Store submission. Optionally + provide the stable desktop tag; otherwise the workflow reads the live Blume stable update feed. + Public Store publication intentionally runs without Raycast's unsupported `--non-interactive` + flag; the environment secrets provide Raycast and GitHub authentication without a login prompt. +5. After the desktop helper has reached stable Blume, set the repository variable + `RAYCAST_AUTO_SUBMIT` to `true`. Later merges that change `apps/raycast`, and later successful + stable desktop promotions, will automatically submit an update for Raycast review. + +Leave `RAYCAST_AUTO_SUBMIT` disabled before the compatible desktop helper is available to stable +users. Both manual and automatic submissions verify that the chosen stable release is on main, +matches the immutable stable-promotion marker and live update feed, contains the helper source, +ready-frame support, and build entry, and publishes the expected macOS updater ZIP. Current helpers +advertise their supported protocol versions before accepting searches. +During the additive rollout, the extension waits briefly for that frame and then falls back to the +previous request-first protocol v1 used by older helper builds; unsupported advertised versions fail +with an update prompt. This compatibility window can be removed in a later extension release after +the ready-frame desktop release is stable, and rolling back the extension remains safe while helpers +continue to accept v1 requests. The workflow never publishes from pull requests or non-default +branches. diff --git a/extensions/blume-search/assets/conversations.svg b/extensions/blume-search/assets/conversations.svg new file mode 100644 index 00000000000..532ff334f16 --- /dev/null +++ b/extensions/blume-search/assets/conversations.svg @@ -0,0 +1,4 @@ + + + + diff --git a/extensions/blume-search/assets/icon.png b/extensions/blume-search/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5618f1acae13e4e90791d049e4763622e1d23e00 GIT binary patch literal 38916 zcmd>kWmj8W)NODtUfe0J#ft^kV#O`EyE_R|+>5k0ltPOYcPlQ%-HR8BJA~xsdEarz zxc}jP$;pSaWyzUquDN%dmWC1@HYGLy0KijGme&CQkP&~80hs8B$4$We69AAst|Bj^ z8<2PUf|a_zlVQv?x;UZ}Y)4J}CC5)` zxRDyU)YZT7^ypH3B8tq&ucb3Cfm@qdKJ^pk8M878k`)HFUPb7rOY*SbI{zFHMIejG@c+ZlB;Y_@0+Yh5stHQLV3Ti^Sa=p)lF}p$@GHEc%+9{$W(Ccu69^0UJ%%Cg zb)p7?UZGiUX2K?rQeo@Ec>zBlD{A`G#_u48n1#kPCUinxsT5 zi8K9CiR2QqN@pM8t4LdD&-QX(b78a+ydwhZuX;Q?ev4l*;ztD3UtZ&{B2__!!gVo? z?2P~x$I|x(D;8~d%M%a2_<_$DVPLu8i|mWW zaQn#aCRWOks}2H}Apcd9z?55O{~SgN9L@}|E>Z*SR{^cPexUn4N$Q>q|IqFf3IkJe z(;&M_ciL4!XJ0_rn`zZ>Ei?kAQ{MidnJ=RqTlkg4((=t0OsFvb#Fcf}icK$h=@U|Y z_co*l=Jwpp&$#HhBk5e|iY(AVrtnhGxb>7zk8A(pfege~Sd~k&zffm51x(GULZWSp zSfil0io__9$X9SS?33sMx?Y?&3>A!;2B~F#O${Akb%(y)SQGHxoJy1Zzcy8*p8Q_T zn2Y!b%T8T;UW&P{&qpzwdx%m0RMBZNYG&=D#nZFtFd=O@I0M~Yp#CgTo$NMJz%cGA zsB}En^)GtdKS~)R7~>=LK9ecKFj34acgnekRrW*DO5_t%^p7~?&eDg49PM>?(G<8t zVItg}_kERNqKTX%PnACvu%{Y6pZA4}E%&TSb4PbZrHbq{O}$dVzCsSv&gl(ch!_){ zm7!w`0^xP-ti>+DMshe0HA&x4T{|{o@Mz@#suFs)U>@2J=O--&VJ*VKLXlQr^A_7u zK-)P5=)@0N&K#B3@j>-4@%q<+3VM&RGi3mOyR+JL=Fk9LpgGLdniAxDNJb37A!PxO z1#M3yY|-IfrRX~A;kH-4?aCM|PU|z>B0a)n*n<`eDLG%uaGWv85G)PNoZJx%!{iFi zUvOBE$#~QOJb-_PQir=AYH^`~U*KWsc667Lkzco(Gnc1OwjP}3275Iz+xUo)a`%PL z@x7#f2&$VK%3EHf(mmCxqe{U8r$W9|L$2|N!8pBN?(I?F7O7#(*pfCX!-{F30G$K- zY1XK!Qk$aGJ79XSjIM}^F@17>p(d(>WQe&XvInh)^g{=VwcGm`2wfoTIe&ATNqd_~ zt-YBN15NN^ycPBskQGI6B}`zOZig&?TCjh0;cw^C<30Nix~T@#k>_Ufqye8Tv@lsr3M4_opTg%iMEGHY4>C~%UA&JA zPwrF#-46}+OkyH=J`g5*y34sNIuF9(KeM z`}1n!C};h@6Z0IHfOT_7Xu!vU^Fz@ed`O}=pY}OdQuPcwo^UqwPp0rBq^HswXR4wU zCJ{NoP`>kseyT5h8_Cwlc4ge~m@t$WZj=u8BEv?DuqST@O!Aep86~|xfR!|@!e&>E zmttMrOSSQ?6Z;AYWW!#IQSB#wYS5Wf7Zcydr9lrrMxKt+-XdhUO#{U+% z6Mp3Pd{2=}niRC)x=&oLZlCSTBF)VZl?XWaBtYcg9~3PFF{sq*rXAXp7P6ZI;Y}@H zzo;vru>kBRmX)G73)yF3#m^a1-G%@umja>VO!_I?M!0$i3nCvv2ha!aB^$+GaEI_E z=u1Wr&Y zhyR6O6f`f^Y)T(7BZeCD3kVQjNKT0_v_=rfj;tt6nwqg8B9b@g#WKFaW#1@X+4laz z$71i@ix}M4`LXO#qXm@vnKnDO=Rdm`4)Imc<4f2M$PBuIs%Kp_%->ok{`Hc-NU}uR z7CeL+yf%lr)Mo42ePi|d@BKEu)P$V8Q7_?f3U2$R%GKkQ-{kl2ej;DIyX&?RVwYB~ zOnB}VCAYa>`eC{0un3jND3I>)MVQ1;bPDcO>R9;Q(KVm4yWMyBS1m>gDJZM({4jt) zmbKSFCd|U`e3Qn|xwItwror*c7M+6ms>9;1>`3YG0t9@^0w-<6a`z*$_N#R#{~_K< zSX>3IbOrlcRsYUGg-URxbYchJg}iCMT{M~N^xx}=AzPRzCez>?s-KAoxeL9eG z2!WbyTKxTfK#L{)HKSS)WlHNzkYgg~j(!6^{}!~)>mrSf*qYQ%qOkxAd&e^%rQQ@{)u>p<{r zBYX$W-g^|W@qP8|2D8Zkv6HEL?+z^s79Z8Eo`&}O-52vavhG9M-HhM#nhH0=?u3X% z)|lyWf3~lWU6o*RENm0sUXFLmOM7$&{#tG8>G;>5@bqs+KdqnbPHE~y5w@3>Vx<1>X7(py z#GgfOxZUMg0ljCv>p{+6{9e7>FQ}gKOy$g5Zy_dEoZ?wV7_hrvl`XKf&fy&C?|$?h zjF*k$B29cPDV)Y-bHj=#` zs{pO_Q-}LYPpiMu!mV)Datdhg;~NE^5k1MtJ_>vMA zVBC9y!(<6xw)fYUr)zdyC2XpH=ni363^szE_ML};cOx@xjJPigE2m4RsMGx@_~h50 zr%0B8E}huDO-sj4Bb&$Fa4U;%!c!XgIxx%sAa!Oi|I+Kgy&#`xZJRv_t)Ay$)mdac zIzTQ{QngOW@^p10a`B4Q%VbaI6=ltX?ZbaV6iY(1Nmj8_$+rXhSeaSK1@2ChSTNVM zu)y0C*4Y}=kLu}meojumUPrs6Sp2t064?Akp1{yh8Q0L*xJkR^nPMs@_-EfTA2-<2 zE}M+?thsl?llrwbIqITYMHW87Z%J5a%;?HosX6p@mZf5-ZaJvH3yH|V-Rr{3kg4Pp zp|nFHsEFxW3?dT~hY)@uA{G=5pyH$rpgO)QENop1fNgYNVq4=5|L4-k6f{cfkR+^v z@Rp%iJYBS9g8z2v|9l@hwRj>#3Yoq^%p=??rlk$Eijb~CcA*y#b?;w?VX&UvMQ*!I z<@~x1cxH_vKyG2}73dy7k0T`F6jmj**dqqi1(IZCy_U|fkFM6`=zKw>NuUBL&?<5O zGmf-;C|R3jnH(ovUuxdSsJ&zD^Z-Ex7@^BRJz7Mv)$VQY@DC+x*6DHeCcy=9U{&BALvkj%fn1HWZ;*xis^Vfr!wj=6qw!VxfzLR zKZP00ag7gu!2^9NK$tP&{3noh(fCvX7rAG#B4jygO-UbDw1gDA;k9<3A@h_bn(W%7 z!~P%Zi|Qm)Kt$x@z^gchNqh^zL9kuaV0ho`r9J+zXJeaj^+=)8ne!V2(jM>+Et}W6 zqet!y%x6{llUvtolb|G9>F;)bgUtjxHywXEf7WUKFW(8g+R5W+h~${FIvJZ22{uQv z;MX_SnL&E1qS2V*2o)i9uFsfr2pBy;5cj5Z6`ilt7zQ#6fO$|WHCP3C>C1B@9;J%5TIFwoYOxTEz|!#j)4M@-zKX z4(0C^YVTsFu{p1qKei-MNUzI3XH`JtXTD|i|Ex#!K_iL3^w)?eQWgh%Vl{FB=H!`6 zabqDNpaVDjZ$6qKfiU5t(X8Gz=4OC6M(I2{AJZ~CrJXa_#FAXG;BZCzi4x(rybo2& zDCLe{=2>{0DXr7BRRM|>Xxl*oM)2k5ey8_}aEE6lM3FnyQC3e|_HwGCKvVpNrgdlM zW!g&)0@ktS2PcjVLCM1Hi_UTv4*(H!c^c|=)_V7aY#!NQ z*GLD`jW6NV5J_~V2{xA(biW_;%bQm!l0G@jmdRJ2&`au)xmh_e&5()To&+Yg7+S=& zkc0M1W8qgPok9vSu)g>rF@|yKr}J9ba^NMd1{WQ$VDDlXjcE_pQZkO4()yQ%o|T4J zXmbrkoYY4hoc;DWq=|v{!r%0J@8jXK5^~m6an4(wG~GATpq;UNkw3@IHA6*9a`a!o z-ZwNf1+lEru|u8EX73wnOtCq`7to8!*{3=?X7bOdMS6G~dO6ve?+S!%B8$S7Y)QA{ zPepq1X$Le5o(Xw6Zm?h0yi4NPOG66C*mN_tT}0z0mTY?OLqy7Ym);oF8a~qPs#PIP z4`Kd1GXcm6*$r00-L&!@zB(3Aw)qj%LsGrM3v6>fuSRs72l4tzKVshfTZwEnmKHGv zBah7D$`BOkeD4=QLMEn9uB^~?e&TUVFL*hW88PbZC6D7KvSwaP9AoZnha-O^kHp>< zxX8eZm(eDPEdeZaUhb5k2_ z7<_Brwn*c$WLFdaKLu;&iq=&S^Oi~#WKe}o=+5}KG6#UEZ-g13uR*^^Hj1t|cBb;h zVth{_;Jo9kmyGV|-Pw9DnOocA>l<-yRGEMwX?vbGVTMs*QH4@)l#siG@OU~2n4FCQ z_+^d|Iw{ zO|ja%599m+4SEWClGOde-hDA0-Z!Rd!Uwk%ZN2L7@9aJB|Nl09}bwvh>Srp_OMCh0M0|7VI>2U*i-$TO9gu<=+jqFWg80 z^}t0g{(_#EpH8#TZ$*;{ACOA;WU~&H8&F%e9%P`i7-2LDzDR|^7Y&$9_x@2;bX8Ez zvP7|yf;44-s^T|ZxslHfXgBRN|5p9b+*<$XON2X!(1v=6gz(Oby|e^fXQgDM$>mZ( zFGk(B|8`CFYqDN;uboGcjSw-?OYGb6BFm_tuAk$q`|RgeEWZnbPT+fN_cF*^R(wE> zs$#-U#4P;;AduB?L{aXM#+6+6>+foPzFWI#?mjFFeOJTU^3W0yVoIWSnQ_p^KT59571_p1=P1P3oHG@oILnrRnxf=Gr8&5eKg)56~!WEo7K7`v=A8oA%H zU5N-%z8zA^Dz7kLx#$x=SE}@;2E7c4n37ufC{|(_iSQxO+eD@1aM3~w@Yln}gFSyM zi0qWLv0l*iTok6^noft6(srW4`EaKlTP|;v;JBKd52)ypkurfvakCu+^TgJz04lw|9v z&tI>Mx6j1x2_*gy<52B;G0hbIkxuH_Y=X|6XKY zy})OlJE$6rq?W+Be{Dg9@DJAi`p0lQyaaWH{P zcjy+KN2OQgwj0_u(rCZs)O7KC12m+02PGKBZ&~na9l?1J!oPJQl?v%yp1ZoI)2AMy z`p|lMAYM0HFr4Cd{*je4;X5kxUf!?&;w^{#-EHV+egDMEVIYv?aU>qe&uuOF+3khx zTQeop9lno$(Y1kJs*_|Pq4|7sRX0l-`|>WCwxGXI>ZWJ+q@yQ35+ln3C&4@%Ea8tO zM-p{*7xpFF|2@E^STEYSrv0@i_n=x#VU$#_vbsKTeHb~zQl}+;nyq~OOzMcEkOMwS z_a$@D!O{JPWiI)&ahL8GiR;uucAnf&vd!Sz+MSCyI4K;u_40up9@DztPBpDI*v6|! z4oK;_FnFj1J#)RvHkPZM2iA%xshLhXlpJ z;nm~X9rJ5KE`#JEC)ps z4iT-g8eXIcfVK@^%&`{ydOmBXF%q7xjUn*5vqT1tyzBqIj~CHvk$RKnYfUY^_ovKW z4t4Z37wslw!4KJb^$9k+l)cs#W_qT2|C4sxNFI{XG$}DFKla#5e_qm%POs+m;7F5k zx3QcSj=ZsnMSTOOIf$HMz`-xEYw2e}I>nI@+KVb zeF)&01CFELxp6W3KH%y*ndid*!-UHwYVNmG2v|gRl{9drd0DstA#}zrTKqK)!NFoE z|DQnloZLrJM@s$l5&Y$yGI+#0wX?hqcnMQGe6b~we*dO5h_9PZ%l#LYR{pm9?Tu}IADAtHq z>6);xkbKf-^0_vfzLx2+oyai#qp90f0VFLA*s2fa!M>8XX-C=nu0TL#lMWbpC~`t$ z{=-*84hrB{oJ(l|+GVGG5psDCr|n!7Ef|7F)Jk8y>3q&IAyhOIIg`Y%-NOqE^Gy{;h8HK*GJyLBdTSjK%(8864pYrGOJcYs0;Ai9F zT%82PX-1s1W<&?(l~&f>I9@RA-kp1DPs6Bo_HM|~(G$NVWkc!`-& zsU~Hg;`^zZ4&iZt<=R%lWv1rtlLrw9c1LG%*j)Wk{S2R~SdwFolrPL}WZb(ne@XBj z#k(Tdy;W&^mgM5%vRu34X1h}V{SmXR=w~UJwIb_()q$XtW=mwmHMyUck~*{-(q!F$ z&>qrkXh^&SVromou#SlA%7&%$#^^LKm7z^|4CNd)B5?=2E#XGTB>b=4fK=N6Y1WD=+js_gt`BGB_aL2F)L_sn(}4H7%M-COYQ! zB&}2%t0V2ALXGgI3O(mmXuaCS23;r}@0mE5M!cn<$Ne1x74Cllwy<%8@Li>T6H7j= z-ibR;D&DHu8PLJ;B;0bAv=*cu{E_y>2?v+{$Ae+c2|XrC zHTm9mU7|h7uZQOnFTOIVXd!Kn7)bFFzOu4SFKF@eO8+#ieoI6;T}k~rf+9)57vQ9z zm&I%kcyO4K0V>FMg*2xif2KR?x9vZ^1*x7eS~Gxdk$$z6Ul4lWrc&j`>>;$i7BbJZ zj7`7i(ucq=9CWN@AURc44X($|AQp8%5PG%WNBzo3Rq}WIMW{+xXGCm+y9TufUUJz* zP8#SQSj%4COTF%Zsg_mia~~6B^w$vGYctB?ILO57R*7C|#}RAh02JkVT*m^3Od07I z)Pr^U8_FZQVE(!XBzfmt{+`pq-RrH#?1!=Y=A9?bn*OAv&4|Bs6sC=?WIP>vRyj@{ zUNSOiwilhidtyW0VdxcB4!t~i)@h6>C7DJ85L4_LK^FFqf$jrsIIx)ed(Z8^o(PDG z+D-VLH6zC>|Lu1mS%vLm!QFn+M`e0%2q+kOhLk_8K^j_5sO17SJBJUXy-p-MiM7a5 z)$-pD#cGNEZHZm#6yhj7vb7>1_x7moUVfcb9AKJaPKIt&nftOj;~k4(V0|zkJrn~w zn^UffsttW!3)ty(yTw@+?jl|?4a563BwTFnT4Y4iUt_lRGxS75Jz0}c#khE?zM*`1<11WTBRL*L)^c?U#| zoPEW1swO5_yKA>J1j zshe(mYrdloB+4U37EwfC!cPwAga`X&qHn#(6noP`2@77#iM#GlS2rNoXUzNrzKElO z(?7ZOtL~NpOY_+#?d12$7NooYk;y}th7S6pcf|{gXHkE^$v_w`bBm;-Fx?zcgEFaU z-k5KpwTcm~Pk-b2hW!HfYZ5OEFljpCKr}stjS3^L_dwc$`ysjnk!1g#=Zye^bN#BS znw{z3SH&A38D4iwH_unRU5#|ZhXZF5d4f%|lx&yiS6H4-=eC3BSMb;vdjrG;>TMN85 zC3WN!6nyo%Egq?ih<-QB3T1sEKB5ZaF2m>_?2^G{#g+g~C^2ctvwyy+-zzE^tERe| zftRSUots+HlK_5)0~bfMxh&AWEjS&&q!1qQgBwWZ%kecrAPQ7uK_c&3PfUd76tYS_ zQC~j~UF@WkdmMQ{%-?}|`&y~{h*g7W5C8Bg1haRjS!55VEsN%%d^!ei&ME*!poT?@ ziFNgzRkrsP$00~Ii{=?PDn!iRe@3Gl&yZE{g1K)N3*)?`rw9YiTs1x&_BWtmE93Ni z##gXR6!iaqFDi!TU4t`IYX@yDtkI*zREc zj+oK!$dMYFL|)0G^|J2EL?oaf7hKISe@YB|`=dJ|R7{IE z4`g8V3r8Y)N+k9ZswL#q$B?e;>^VTedRCI?N!#NSGSSOMBar&z&*qrH=o*f*eaMDG z(K}3sEzl-trz-Y2Pj>4)`q9Te313=dD}3gfh$pB(KJD}ruZnV-BPYWRqoK{kFXYIk zYULoJ-uz}Da^UuJS%B6m{%4lgjy<&t$)EpH_`It$G&bi@0&EN;gge@hXhN^#$Z&#y zqnoGY`v96}+O;UMySo`GWw^AdPfD(& zP}N8z>%o7+?D+3z=Ot0B_ylhl$i1Av**#9e!ybcW*^J{sqMlZhUHQ_PQF*>O00OU9 z<1ovk;*Bwni%a%@p&^vdukQ0wC$Ce#FHd2?eHP92UdrlH+RsJ%3emN`BgL8&#$Gnk z(j&ELSr(z{QBYJZpiIz#6kDtb4Xi`qmbO5&=&}b*`H=X|y3Pf)+`iXh>4Gx!nJ6dU zP)tu{e&AgdN=V};3oSj`Io^PnpBjq{KYFp@((?7<=c{T=x{@VyQw0o@? zUQEES$Ne7?HY9Qes$F0lB%4UUE?7Dr9&nQwxSv_R?XtdAITHlhuMalv;r?&jJkmhA%<*B6bRK0(=z&1tI+XJt7jLbFWlc&eQUASZZ}uVt)&K9@ zc%({h(MVb6xiPkJ^oabzxiHf4v$I9ZMHR%i8DN~0+6>GZN9~(doX*gLFkZ@;f4xW= zg#Mv?GP9^MT73=2{b9i76=0bt8cXmIZRa@ldlhCI*b)ul(_VJtcMrvbeTN(Yuwav) zKAjOw8at}cwu$o&Fb^p}1(0`I-Ec1X=s$T_-swmsf_;Q!eiYHexj`0mUArLbBknpe zjzfS<)u(p5;s%3TECmzv`tL`~eT)c2wE-ll?8-suf z5jmRsT_gY2+Pg>It)Zzft>p1KFli0mSaN(y1G^}(*lIz)W1VfT|fP9+EztC`d z5aw<<`tBe8SXZDx5@UQI9b`lM;+ISxpI06pc)myh@0I%^`hjL;gcb5mlN%Y7j@trI zZbS_l#|KyCGNx|V764}9OZIEn510G5Z1O^_|-=EOMv6@c5x{-NRQ* zlYQ}nh*TipG#dXIRuESwS*RP+eo-#?p zzcrrUHXat1e_n$cByTwCSSCJUjATih;Z#u~RWik^q+3k;KS2aF%{b+L;FqAKvZJk# zRQM^lQELrCo+R1S==)XBsQzq2BFS-^8L^$+; z5(Z-Tokpg((qfh8|AK5G$$iD4=)qxcqtAYkC-W+UC&tkvA)L1-5$5-Oko6&N{sYh4 z=dViArj1PJU$eTbZc4dP>YjX2!mpnB2s+FYGNWx9_4n-P=#xz!O%sD6=w%sfLwJ=4 zVoM8iZd-e~)IyorQ;T>w!bvGUS;@JQ?S0R>Ez_Y_i438|x^WukCB`@w+h##uZ!LM2 za**A|MbDc_%`WXqElE{p3Bkhyvitq>?{KK~#oA(FV#+3Nw8IB$jA1iG|~$ zWIYFZwV2!sb6=j&nK?>nLfpiA=Te45>+FdaSJ73{nbf?$S2;WAI-CD3J`DVOVX#@z z)OAK{kcaf<=Xg1Zc2UC5vyWAGJw#DB32fK^-u|?H9A)B2Rq74}sdqz%>-X`D3sl{W zSi1e?BKKFyibirVC``T`w_~RZ?(`ZQgyDP9(iCni&yu5US<^?8&?v zV>gD4`H^h{_O9#o(5@M##Jyp8m~{A^N&dGo!ZdC~<1|fO>Fgyx5*qbS~2+(^8)!&}m8N`|uk#Ul2A{(X=#x(=+?k!WX#XxtHncgZQr z5dS+p!I^XBmya4OM@!|OBi49w_C&k0PL_BWWez1T8ZrR}{Fq&UOtv9of6{7w6Ee&; z(!qa71YXS+2>pazbS8H#);@&nVi3P)jmP4e@`)z0KSo^CQ&cgy=3|f`AEl^knE7dDrwRFWr0~?5zTCAD=Ia_)aP7Y%u>caZ2dQg#q^29|> zyd!C_>{UcjgwsE}OEYoV^jGD?%2&ABx-#iE3*OSW%yn$0;xejF={}zpupYax;Wn2V z03Uth*qwMaN*@W$Zdy=jM zd5$2kI5T6W4MgZ=iKwkE0Ut|)b&eN>TFoJXG#1lIsdqm_{Tib~r;tXEQDxWUv)qPf zogmR=JX~3~c08PJ3m2?6Y0PL>SLkl0pd9I%9`Bg)>B=^vFowFmT_o~+R0A^51W2D~LK<_5 zytysw;c>-yq`qpEA#hNzaP>udk%@O|idUybR)Z9DgZ^IfM&rI$cKH^5r}6Z9Visj!`7DzauXp#QO)-I;`*xp-4-F4&X<=5>-?MA|Hv~GRL@@v?Ae;z=16Na&YUu;!N`&X1aXqd(XNmY z&}ZU>>C5{-PUtK6rb3fGOMSfFUy=m$d&*B0&AFB?I298a_&8YxJZIZ~8f}(-j9(y8 zPN$?BQg!Z&L)9a|#Q*-DAZPkLxAI$(hn$VqdGkU!2En0Y_nf@b6(W3#dA+NvMJ`64 zwy3%bMx!HWy2u6IA-+NPUJu>(5t({H zjh30p!o(Y?n`?|2G-VXg4Ggjf<3OG(=-PikfvYMPOKA#BrvO5>_FR|>=av^fxRDAv z(uAYy;egAL*;)n8t7qHROTDMT%{u^If7X6yi`521h?$C%Ee}K7>uFcrYnp|n8#ETa z4Dzeh7E|70chce?+eP9sGm)#^@MV^l*4)Vhv^WdA>_7)wZ#*g^q%wnAQQsYol(z)M z!LHKwT{_WKR49GGn#j3S#SP`m1PZV#w*0$a)d3g5PUw4XfBI_&H>wsE4WtKN%!zQC zUS@fKKOWvwO98|C&X-tL$5kdZO-w$@7QO|z^GmmXA4vw__{bXp1i z-5J!rq@%XP{*7-6#kCDjUQ}cs7*=q$AC(m}w>z*SZjOaSO+YB^v1Dbl424S7(Pgs5 zbcg9!gt&J>p-o7Oj!1t`s8rragie;77f}s!R^kzD?_amaDbKJ+8C#~J0VC3CWrVTE zc);|s1WkGUf2c&CzwvGw0W34tj*{}hZj zzr6`K2@cfZP6eL1oqrKG{LV)1O69=X=Il?5xGMj7S7g>>8cV+A#l5w( zsF8QEpvM8Q=bdSS>dh)OulLK!ka$5QZ$#Es3a& znz>y#0R-2>PlBK&vDs_kHNt^%yR@uU8HQ{JqCpw@`2`K@3*eK{%r4y6RU(h~$Re4C zy7%>YO7=GkY|8$~9YC&3^wU#&;Mu2#&$?KRj0~mVE2!yCQ5oE;I7Ldo?YHKUpD_pX z{Cn_|nC%cqs;3c$xh_>(foytX0IVyuzVz3L^h`X>R)t-Mx(3Ii9m0moFZDWGMYV0_ z!WZ^?ry_z;bG>EH6k0@3-}h&X`)#^1?x(j8-!4zdaYU@$90{E_-b7h~P|^f)*hQ`a z3nuHGr90Gd$9nuY{C{J9Rm9^&5GDHN&X=%u za^86u2>1SgeAT%hcw`7-5xA^5ul=+MG?rvT@yik`E(&?i_-pP)?tS3ib$dMI)6u?N z!IU&)_3XZUvqqO8QYu*hftSYrR3Kr+RcG+NJ)b9(I4#AxRh^cz-xuQU3w z?+HawrHJezHe}hqmE&(|4UotuhwT+Nr;^ZKp){hp zKeh_~PJ0u$B6q*u+4X5+AHBBWdOu@Shp~JmlsZ9!4 ziV+o4DL;u&(+p=F^PVDoyI<6gRu5bHOZKr);~UC4xh2HU{yqGkM_gs3vk`v>MyCHRb-nNMNd?TTtMbLcgn713 z32|xJF3Q}I>1Y#$q1d>)V~)JGo_zP>Nkt{<@m+E%>JlXM5`3Ic4u@XAR3#n&aM zph6y0;iFEbZ0DD)R{S&?7Yp~H1r6Z{$#_}EIJw#6OUtxu=>GY{*EcCI=%2r@?~)D~L!)ki3n9{fPx@4-M^2L8Y2pn37AoQH2&FQ2}3tc_#< z{#s{QRM<_*aHYEo_2=BOT4Q6HSpO?S3W$csN6 z3mCNvtkYMV3HQIb*ID$R(yo2sknn-%hurAtvg&>G`WJRoRL&E^IP^iNglgf#e%N4W0GU|mq7F@3#s$&y2QD1jB^Rf6Wc6r(It|QZTVP?PhVFj$t zy}m9|j>yi%^78n&d`K<4D@`I9X_?g*=K(9;U3u^G~5ieTI zF;PzW(LIKSmVpydBX2Fzd=itYh`HWlKfg4^zook<1#8CP;;!9Rm}GFB^%6DhGb||x zrA7bghA402)NCEo)-r|jIeP)~o?=}$BFyzFr{1MPkXEOG>CqIun67xiXr4RT)6f%H zzS^$UrOZ6V^LLZDcBL+#vYEpE0=W~#j;MU8w&!>{GsDbxq)B7~FX3WzaH6OiwdT&; zfG)W5Tq1cTLBH-he~pM$SJQE|ncIH%=ENI^ju$}vtU=J01{3|C4=$%=OHwz;sleJl zI+B3AK(OlJP5PNJhTFg17}kA1itkjE8|{m*(Kj+G?qFt>vEg|Nv=?l_m1+5bQ+$uE z(7@aPlvpOqZ)cE#Yzx;iWasvW|Yhpa!&9(&2p2=kt3x7z*gGfOl%4#ppNm|9pkg5`1|0vD_3U{)p8 ze#0z!3bU_1Z~qCvh`sa?OivgvDWR10&!va$7apBx#ERMhpPqYro8Q!Dc&wM^?PCEO ztZeCA^_ho1HJA4$i@ROI3|zYT3~45scQR}_ZgT{bZ~FfTcofx!Ri>K@zZzRxm^C;g z6a?J8qhVGF(iuGW!~F#DU-p)u$Qh*IQ~IK+36d(;#eS=MLi>uYYP(xAlrF=%GT=eY zfU!mATec(eXL16ZZSqXj4eoo-_AVVvBR3o_wew?%iWW~0T39#Fqvs2pE#CKrmlIv% zM${Co$|<~3X1&%=FW`Io@Dko$%@Xf3=AtnTjk6DE=jg@=3!$dsfL$nKwi6o*!9XZmyiayUd^C)crxBZ@`#; zvQ_Vk=FRHlkZdn{GfVDg?uU5~ADas}m@y*x7C#h#Gd^Ak{@c3kW~;+6Tf`HWw0^Kq zBRWnnSdTm6NIkCxd}f;5T#o&&ecXuQm}QZAC-|3-6@vhoMB#@xfO*DAgPXBtq5#@% z&WYn8rA8YRDTVGxXSq#;hXCXlEWnC~3izgn>V2etr~_%HVzPahD166@`+Sz5txPQr6jm*wLoNLl!e>6<4v(zei3#`RHV-)9Q2+hSp@m!O zVtmTNX`HAa49Xb50<8X0w2*d~>6FSFkNVnGWHyI2wggjK;^RodpRy8uObZEqWIq$Q zX;k)ITEt;- zc$_+l6!4$&^WTX&7+uU+1zd6C{rB8t{bBPJOEb@I`BrstTRTm4vw}N4Prz(twn=Nw zzt*cR)Qfr5xK6<_!oIvCWJW?_V;dCv9?mz&pwMSqRiNtbcm3DQhN|_cq;V_+i2M0G zoi~dM*V0i7Cb#21!r0YgMYXsRI2Vwz$T$p*j{nfX;4tc+W+8`_Yo06Oi$B9PN!NJA zj!N$E`X>V-?5{O6B^n@OBbHh>r?=io7qmtSdz)$EUqrbSTD%6wuKCs?(iZZsqJZnQ) zPbLOwz(r~C&aUmtsq$lZ1%-!Sce=&MQK16Cx1(khu1PBBB7B$E?Gw(6heF*U#^f5XAzgk6YdlH%x5*DV zL$`b&`8;r;YQoU|k&dd#bU9>3J`j0Y!TbvtxgDK$8N+1{YdSYgq zBPynL9B!6Dz6h|(uC6hwbjiO4Y>aJC4xAxSZZi!z)w3%Xu{zySL+~=snqi((w3Pu? zl|hyJ-q|+I*AJp_Bo(eavDC&PvI8rZwi~06tCoU+L->O4!`~F1{*JAdSV_&Ly4|tT zfODE)0zsXSlNfPNpDjC=txW4_?+7XGL+9d6SEzSdi>V`5mh{_acQBA9`YlcVCk~ko z0boZ5ZX{EMJ|(%k29rw1)2-uMYsSMCEjLlzPV$EAiPF{7>M%F2Z6Wpy!bjigt{)kc zp7UQ362CVpF`&M9Ml9^qUu{$pSZX;#-9o-4__48&o??PwO5*mrd+lhfag<_duk{v6 za!-I*`-`r$KIzjpAibrD8A=S*V+iS!SY0k^P>Z8xL{|>x=t$ng6~5B7X%X$tYdnQa zYR&}y)qE+~c@O-<1f9!v%vK17oxLP;B<@QX#Mx~<#rfD(1mXW>0Hq!mian2sBV5oH?bAVXqbl9jJh;n5uH2Mp31?*Hx>hukzvR zT%EoNeiHbIJMasrj)bj1HWBa7C;n7-d!7rg4ALVfiq=qS+8z};uO~|%5KOG@JlfIJ z+YBSP(AjEya`$0?_pEPyj*u39>5Iu9SZNrK)R0ENWTkb^^oCTGChACx`!sud51(D(coVLw9$#NFzvhgGfksBOTH?bV^DH z3P^WJcc(~~NJt0>NH;Uwga3c;<9*@f3@7$pd+)Wr^{sEop|7Xj27UB%?F=r6# zGr@4ZwVusdx_IMe9sqOiipBa$`Pmtz_=IPTl1ujm0kGk{`idrmWV^x8%|-&>{;tHW zYSq9cnL;XhR)wj6jocQgJABV{L*%Y(+KL^VsgDY3i|&T`C+0WS^!$RUdWg{7A$-&uaodf`?UfT?w|rE2 z5uMM>Tzs#H&!YH2uRP8#vJv2NqowZ_sszp5D#{Zv>AMnOTJVeV!B5f43=|W#MDZbN z=`^i!GAVqeQYk^y%O$vZ!gY}bZ=REs5DcvPTf!Cou&y`HuU%xRyx!p zGr!Ws==&wZ|LXOCk6mIf|M8Eo z#NYrN;d{0b)o3p^Y0`?zWUcFDOiiq_ekZ7b+f;;@^HvBWRU3h1I5Yy$Z1?t92RCCL zR|$XMwMOpOXcP`!GCQqc#E)LC>xIfol7W8&JKhpN%bR3Pa9a1HauNrNkVH=}W|!K0 zMZAudiiOdc!P|ZP2}bc`pApS2;7%h*QG;D127A><9{1n|E3SO;{axEX)hrCq67)Mn zea9{NeXE~b+6;7TRgjTL$%0tF%T6xzK+`f}MHSiv%-56x(G+nvY29B@9HO3|ghE>1 zPakMce-e#sm$-;WzurE=z##H4@cicZd`b<1sHvLd6!qh?Yqzkil-qNU^u8uni~w}D z<73R&!g-!U`#r>PKl%^Sa;pJ*3rHe0L3Ns52~nC%OLYtjFQM!&{QBbpSn+Vf^5^II zjXKWJ;}iLf`STi3nYTlG6HMX(Un@z#Y$@eCzS;TXYXAz+;sU6jbN?NqFMx+E~caM_e6Dx(g1|p znerruV8W4Mq?1Z^QFkJ!#Ekyi?T7R1*7Yf zbw8&-&InDTYFHS?{Ry4+A5e(vo;6|=^ubB{-qhBOMM`bq&mFh>YI;!n)xhToXS%C4 zd=Dl?n~1*%Q_Y6@YYd^1XicvfODlqkpt#Z8>g5<1%uAb4c?F865u}|uTw!UWl0EcV#;e^GO-&!N8 z=eEZ1^*C%~$jXLx%<(ro9G7`RUr3y3p_ZD~a0;iCM@j8zkG+SMz^LY-E~@!#NisD$ z&Qbx(*2w@x^(n<-M>`(gwkkX5zDfJ6(^I2YAz5#?4aB7lCi;F$t%>&w>oa`7MnMIR z|LmRT<(v7Aq3`vlI2D}!nl>4+(4RkGdYB=YcSq2fhw&ly-Bgx*;(yoJAO9S_0k{iV2c> zA17LdENejIT0L5BGFQWtWFNXjACWAc(109p+qp#lN&YeTtrB}%blSY!wmzaI3sBOz zP1%PIqALmcaFm+n*12pjnRfdA8(f8ZaYxvBKM~nwb$i$O+~D^$(~Yh0pOT}iR3dlV zel`I&qSY9;q#)jsnis7dqFBYn?8Ub3+b?BGs0w(J&8J*8xZvBCKAZkgwLbX?1j8@Q zhvn*Zbgz&HPzO!)2tM%ks&|GAxTvL)U`=mo% z)engZBYXw=ED#Jc5IYs~=t3(o?DIxK3A-I+(%J%%9RKul*9`eDotuKTS18#j;1n^m zCoi{cqx2r)SyheL;jZ;vSvsj=G-oZdk+XABDoa!eV!{=z3u52WP);?Ws$w8&}FC^Kakzza*zmpM%UKCT7>RHeO zS<|sQMns`8?c;68&#TocBj>*WLt;>dclG*i^${z+W;ARMb%3D9np^YKbyP*Okb9Z%6<+Q` zS0`~6X$*!%@&|up3&bxDU!KPN6$sTAE3!@za=j@XDoWJc<=$nA7`S=E((K!a;1vjP zko~qu8oS%}T4%Z**2F$(p)tOdxxd$pU33$KO{N`Ot}>aZ+$_8d@w;w=K7Sv;L8Caj zHgPmQu9s7wLi~_AB#Ym|G!h3=hcq#w3xBPN3Ee}3Xv0Q_5qZgIC*{O*Nm2HPBwD|S zU|444MJs8LEvPh0!pgM>)bmE}N!itCkK#hqPa}Jc%1Q0Sp)}S@^}guy%7^k;WeBv} zpSY#Tp?G}u%p@S^PscZ>+8(K3>F)gW9?flC>%iZ#!To97?iiC+UE=Q;0`;GVO6dMs z)b6(LvXq5N5YD%+)H)-0z%FGUzynU|Du-t=MgpqdiQ~A&O z?K*U_BPNP=bIa>Z!>lxDl~AhjIXhuJx&%}_E6K^?Xes?$(tMy9>?D(*bfF1oHhEI^ zSGM^m^YEbOM@UNepGehGky-0(^9Q^OA~bVIkh<-`V`*J~wzy~*wgPy;d9TChu|FV5 zRCm&*p=`D9BQ#^FBgR_5*es;3J;!oDWDJ-d)Kf>`q>aB<;FdthnQze#+*s`|U5TRd zr4~I9o`r?G?|7&DL${ICpuWCM(Y7kgH(S|J>rQY{fKvL;?>MZai4$Nrp(i>WRh3YE zv;C2MFB!d?{qZ!3F%S!IH#`F-+irt&r8A~Qnz5Ive$3Lhb{VT&@!AV2dRQIrkQ8Yl z4ZO>Pk_aMoWue zsArcU?PFbUQ9iMKX+Rb=9fAQ~+&(9k>H^eg> zSfewb?VTcJUuIE9wy+eiQ0z8C1BKA?{&pGgxE`~)q&5!9gwYc{v#;nm5>$8lVvicn z{Ok-gV<6~7D_OJE)wCGv45z)h|von-=whTW=5K#WeOs3?+^dRR$#~FO)OH_lt1+??Qbx<7~Uz z`P)AR;2oCIz$B-L!ot0NM%##)yq*P$#T+eiIT8hHl8MtQ2tB@5h=|peS zl&z(XpiE^`ri1=@9j6D!tBZ6_Q8T|$HPokdqW+Rkm8AY!QsHSk${@(l74vD>oF0z5 zH|g_vN4aPmSVX|f`?Pp_0n|c35^|<|KpJb2_vgkViFR?iadRg-c*D6HU$W7bQ$yb| z)N{D=9G)>C8SlyXT$y(R)3+n_2gs9{@GH#`0V)4wGIdwNZH$2Av-2D06&IoT5)M?k zunt6Z0W^TU-0a=6+Qct5H9S8zsEw}Wzn7ES$lD8bpQ!mxv$vb1*`3xDdff3izcckN z4ZBKquf-w{Ss`VPv|Cc$DBmH*So-ALIxsLNC(*e(ZYRxmt{ey=Uw!(Ct%&+Bhq=wq zUGh_>`M9z`zowQ4g_gPwA%LHZS(GWFaNqa1A+2vy@_CQ?A6U!jEuq z%+;4tO4J@#v0eei$G^{ zz3KF@1Le8e$0E7Hl>fWdWPO}E)BYu&Hw4d~Xp16GzJtN1j(B3!^6|HGKcQV& zzlb!iX!a&_oqw7W(yO>T5h$9GFwi!WDwcy-H%C^Zjg#Iniz+>57K}(=e!-9LUMy~~ z$ra(h`CuE+%0m(zA7xV&BZ%myM3MY$&td&%44U<}+LR8o^!l^^)OZ>gZK!`(VqcjS zJL0?5o^@~j!}ElY`oj??ln;L*M0F?!pIOP(#*z=dk<57)B3Lc_>x*q|n{ZUF_z#)p zqvz!P+PyLj@97PcQ)$`SB$?3?_88tGyc%f@f8yytFMeciA#2RD9$3E&nmTsqiQinB zxVI&nafI4e{Xz8S%_13TfPT2Mwo8}=jkK95;SPWlU@!!Xb zJg|NoXLQN>&PD~8EYobPao%HXJLuv-CO_VUn;)ipGI~zwoUCqwIVDzyVb^_D9v5O1 zYF=C46wi2IK6`U9+6;g@R8L270ZGg$pvS{r&hIvxy8I}s@>hd&|9$Jq!P}DzlO{cI zMM~GjZ3c*SC*TsLRub^kSl+*r?a9d46!4b8k?|H-EbKvfo`yQFjF3v8ec0lKO>;AE z*>YhY*Fv8KIxd9Oe1nbG(^BoSHUAMR%O}7Z`C)O%rOpK=$QpXtI4lrqBmS~!s@G97WeqPzbXMra@*J5(yH=y@~hA; zU=s#e1$`T}{*+`ZnxvrqiceVVa+i1ELE}*6A zXLCZI8&J5WYH^duL`|!AryU)V3??d(`51(1%qEK%Hi9=y)UYBZ3NI*V*^WIz?TcM` zt@j7K{qEW?u%p(NYsh}9<###T_)$avECqv9#1GKCzz0$g$UBtX7yU1~vDRxGPBNy& z$ShNpCEo>5+DS;|sPNKuUf?Rtyh;6J-&mZe@u524Os`cH7dg$nLrn`_Mh+r+DTS*A z1Y=s3VKFh7Y0D%haMNfWagF)*+dNY#R`MhVcrMn;Q zzQ;+Xyszf~P>W}Q!K<2d`=@c*CnpYGL-P2CtA8wLF9vxPoA8zS>B4lKd9EUJ!1+W; zIYXq_~m2=q0 z85^D)QNs@v?jY!C3|hmA6Vctim)I(HCjB`2oV_PjUu!8`Zkt&t?2rJpNGr!O=?ZTc z?-exz-wc;PsQ^dQF*hp9)i1H*=FFd3Y{THyBYlGlH%c={c7;yo+6GNv_nI(OzT=E; zJL>=5zW)2KB@=iWQR*j>T);E5&~KL+^0LlCA>VFE6koL7ion8jkYx*!MoA0b(guV} zVd*arAVDfee?_GbT4!|>+TnDq%Rwuqjyd{Q7&+dbQRpMzN&V=nD|$x0xPre#mT$?G?C3iy=K;}HO))E2MF6fr@!gdwO2$&s3KHE zt=6d^SM=;M8H5IYE~(M7I4T*J{!(Y~2Ep@hQRcEn-om%qo%*nroh#JKNT2)mX%T^- z-FW}Pa@;}WiPPu8R2UNIe0mk{olVw$H97{LeQd|?ehVoqtSP#gkyQ*2&fiPiv7A?# zO513Y-6 zaZMb<^3!98f1tr7MyUWpcxh?6lmVMCAVYzTgAqS(gse3CM?aT* zw}NKm+yC6_FQvDGZzIleXg7CdJPyh=V*#pz(}gSL(D$Af#?7~Cl>u@n>YUt~EL}4X z3Pe{$cWO-#WffXArV#Z+f`xO+SR zcsV~go(J3w(`itzQKlDyf<*c2S<>z6VJ-Ip!`4JKa=7CY%k&fO1KMu0D#;{HnN#`8 z-*|+K`)@K6rFatax+3dTE0%og2CXw(q;VD1f~5VgzmGreOv2vzScn~(JGMm`>k{hu zxUr?{6a{l(L=R++Tpky()Ohk7*nlfLIEXl)({AFU7;`b|;?0O=Zf9?tp!bKuA8Fs9 zTOXVJpeXY^iaU)#?LMhc6?HpB@48Rpp%f8Cu34AVsm!mXvTAK1HNf->#7yUmn&2Z~ zU1VxcAKV8p*6^ZvUzNkg}b_T+^i<6~BM(zH8g^*3%&%?-byI!dLe`v9LWF?AW+ zT$C_sd0`mjF`>FjQXN(Ex|iH@yjz?Ms)mDi7%`*}$SXxM9=$1iXYq=Vl(6jY!y8p7 zqSHKbw4%B^+)B0X;s?xKRy`2(N(jE217+t+IUO_?k;016(n(^taM;5n#$7PDBmL}^ zApbQX@qyQM!fE*QTVj@;_~urO!V90#O7X<4VYQ8qCD>-?O>wJ;&`Qj|ji-m_lV6Av zw`NqhI291|;Vl1A1evu%82Q~kvhn*`QON&W%)wY5(`fJ1fc$_P6ETPZSo@hO0xTQLe=7N z&6@IuL*4PdY72~$#YAhCewmWe`b53=+eJegO521Ku*pBEXuKvs+o%WaS$|TVoS1KK z-fLUSeH_t!8@c}1Sl4-cb3{N~XE;HH7pM|@PR=Y}G4EaEulmyH+ytSG5wVC&oihzQ zji$)BU>|D5PH*I)6vGLgNe?A>p?o08hWJH`O4`WH6G4RQuU-Bda@1JUBzr8N>bM!;>vKgPDg+>S02oT+iu~;?BNCC z?RvKLx_(bl6TPO?g5%@xjU&dJRDwOvcSKy+(`iHY9&eMe3+Xq1ZK^c=N*PCA4KdT+ zc!m)tdVy?Q>A6rlx>B75t>hyDfHp%tZw4zWda$nZSt@~N$GI315EXLkl(m~xV+D{b zsny+ad4jA3B)w5b7NmSB1>h`r2D;b8_zj;OzEm?cA%yg zb*z(aWx2XqrEgS@zX9H}=9AWJuMh~CJDJ>+o1_x4Nj1JAo#bKI4s3ht&59hyr-9#} z#f;pK=pBC%lXsTw>aG1Xmiro&^S9~nfj&oYx+|QfJ!z%^k6%hqP+sV;{unO06FxiWnw_ElR z?vt;$`eL@Q8jv|M>8Hv-N{|MAT8PyAC6P00(#?a4wEAn_k?6b*v2hGUjf9cx-X;~l zmfx#Xg$UE6BcNaEimq9h0$_u71l_PUz>Nk^MeYL}4)=b2tOF~Obd9V%$kZdko zTswx47=w+@*ZSLPS$MVetgO3DU6G~wlR;EOgkNd5_Ondgcs+tTQxGq3eXwNTi&uAT zk#e@pwSr@NjwhIxWpKisn-hm~e9#>ngsNLE(B~OH@zDa}+V6mnjTcfnn&gsf3$FIF zO`uw&mfY}d^Hm=L$*q;_0KtBoTk??aat>=;5F?J_9D-yN$T5;OeuK!<=q>@fx_v%> z#j7HG9leMg9C1VJbxn(%)v_N+p=OU@vY!G}{ObY?3adgJA^zgigL+P{T;ML=T3iYtU5%xY zp5I=nmF;j3KcWf+KixGPHzWt~+@5LRGmX=)dJ5u=6=Xp4Ni|eH>%ro(0wS?Y{ESod zHRxHe?X&_^n7IV2y8T|xahcjIX~Y@YO#QIKU@hj}zA|V~fng~#;8r+~Dm`)=1~_yK zkv|u#_mgP0TMo7=fT)clUOPKU4`-Q3-QaPoCGYhHQU2j|l9f|OEs`l!s(cmr;>i&u|U=trZoHM?j2>}xn ziIeedD4_HAodk&S$mFa-Olh;xcZf|kjIWDZuHUfKdKzM-xk@92)s`7zu&066^NC%0 z6UKF2Cs|NRbr>~pKliL)O*vciWD&ON%Q2O1k9wT8@0(U9}Y?gj}kSeVRZ4={U~NRd>-!Dnbg-zdHAFa`F01!tU#Q4T+Yg4jzxFJ$B4l^9KS^uC`9k7YvOu6CP18}i+0^)|!TJm6)s1-)Bf`UW z%M8tsEtVTIX@?TbxE=6R!;BUB=SXzm*}ThEl6voaw-t)K`n{>zezY?6@L_>EmwVBDjZIZ~gUxs&ve z>FmU<2Xh@UyZ~zN*@yn9TG>myx&%fz8xN3wRR01<@U7Cn^;GUThxqiKc)qhSl{gc6 z{cXbBw=7I`%McH-7YQy*Rn5uyI)QbpIvnHrHsxJZXHT%#x+ozSzn;zwS*&_H_%{xp zF$+7gWEi4^?nfW!Bi)=NVyTMfQalsQc~f z{Zs#?VFcQOgFy2&`z0O0X-I1=q+2xiS!{9%(r@BK%cAyZ8u2a)wc}vK?#sIFsDtWE z`IL)ao%5d2;YNADf(`$KWVH@Wv>Z+#0h%{7RtBQ|QhcrAwND+$B+492DqfqOAP&jDmaV8Nt?cCjqEfe?kn>W$yy z$5KU_)9`K|gimS%VUh#UjkO6|=ffutUu;hnB?3@6L=w|>z%$N~sqa;A<&UvoC>|6>MT1_rJ5%%VhU(kZsMndknd*Nfz==sw{)tuHF?o zIyQW*Vf5`lnym>XE4iRGlLGx5dQ5uRq5kvxoPlQQN9Lfm>tV%uLRf-aR$=J^{Qwq? zlE{EqZU@PhrRv4_io_(5g#!0b{43zgTV0b3&+E1n>bRSuk6su~mo6sl?lwKt+~d^0 zf}tLyA^#@cJ%O>%3|$A`QL%fHOgrq7db}|XGpf=u>wqZD^xs$eO1xBakxF5DZpCP& z^=~x$VZpl2!RG7leD*iojJ)UlHEMKMSNAD(W@q`NNFx>Rkb=%GaBBUJ0r@tX2le~M z+dRpXSmGWT4Z_-D$)ZgL#i7$RLjWSKL%s_W4}H-{8j^&83-o9Uo^w;k!WDG;=0RETT6^+Wl(B<=#E|fnz!>pwSSYVm4&07lxYY_%wLuN@m zpIGYX0RdCMJ4$*Hm4+k<=w+q5Z4OXo&D+hDd)l^yeWiIAwBuHJBYIQCwQ;W&OoH+o zht>&U^$HZUO{eKQtpIi1x9vM-2c zg#20Il`rDw^&i6&a{6*e5;yKDocosaCMF&aBJN&wiBGU8!yE01-eJVu94^8U0jWHh z$|mGJZ)k@io-SlNLTc~c;3^~W@KRHYP5Y*6ke_5d+_1VEEn?y|r!u|OoFyhxHSi66 z+;7LEKL_Ay*a+FVDG?1gUV&Ikr=&~abP{id@ za3%Xyot-`TkYZl?LeEE-sKpN3%dVW$6W#S&hk)JXDA$dFpoVl_%saBssYSCKOkTch z?QJ`BON=>ttfdag0_uXR>xtg0t^|HCY8ZSpG88z2x8v!?ZgrX?(%_<^1EsRs zpC2V=ql2T)rU z8cZ6#ciDC$(e>bRGIA~<`2*nxAf7OyQ8s5L8h2$tl5I1r#XuX=Ghju~wQKI#7(umS zLu)rWp}QUeDAS-HIUCZXCcPinV+0kHOwwAd(uU|e|CBR7eaOkEZJX&`^e)YVf^Nd;So>54}QN_NjQ=Mfx$tS1_%JOW!)Gty5AOy-`*)3 z)*XGXqq|Zn&riB;(NvEm(7m-9y@~5v^GS2#R_dkt6DJHFEruL3Dro{MPZ+lW<&l>7VeFB8;p~; zJIclre}3t5WxX0!V{qALe-h+;{Pkw6AUIYb_m0)iDa=G-dbnmt`}47>zVRC>X{K~y zsZfK)(5dSr+twzQ&1aE~tkvDy%s(IDiF-G+DvwqLfaiqkj+}JaO`Sj~78{6?Xx<_G zUcRyTzl+-Hs9dt)D^-ChXKxKFGG>zg;kFEV$8?%u8O64%+Yzr$bj1$vNqgRe;CULVoEt zIPs@D0uwe0^vD(t8759BXiulxFBz$tN0;oRK6vQTdq_xJ)W(^5t2JHP znl4$OBh#EsdjcU{H(R{exf!9NiKHPVV$Sh>2lPk+`T_xB(5W-vDdJiU8efAvowDv7 zh13nMIG=d_o0LB24I5vX|iNQGqj$iJuEx?dQR6sc)tS9Mv0ne z6dPA3@{8;9r|Mb|pB*jEV zg|Nb2+z|XTetAM@#9~CF&`XyemCT|g?O=5SB;FF5C?e6jo5a(_L>N;7rKvQfHlB{? zJn7J`wYlH!Ze6xsT6*WU_pksCm=Jo0+9iv_T zWE}1$0F0pe9*ksu=4tydjBG3`6>no{6z11Tb%Ql}j_JlU^z}YxuwN|*4JDC!Fb@k6 z&!a<)x@0z8HPB*js~kOuwmOWs>vRxqstczU=Z%u@jAT^BlgA4k=^?~(?*8k%idlLG zDTkv8J)uM+hVpmE`9r2gCVj~T?@AS3yw#$pt+(Ih3#~dtE7d6%6c2`&`rN3U{0t$P zI=&-+IG5%{HBH4lJy>K#aF~8Om$a*sicEG^qb1|v&k9is4TzkIQ?D5MbLYJ^csz8! z?vH|u=JFW+!2Zwt$w)TEzHxmkL)f^Q5aAIL|1E!Oa=aDq_Oin~KB9=}p@i$vpHlEN zMfibil8GowMz12YllH^Mz|#Fh9^!drOd8}67Y{!53*<|iL-Cr^ja%Zz0Q~N|Q?-Iz zOf5`BR9~ilkEwy-Yz&Oyu~%1bv{h6O-S{B*YP=nVHj#XPq!k4#N^>jSwL-{B3G65{Axm&br!!;{5w!xUD*DrVWtjWr z!c-{4IJnq0gOl}fM8=q;*OKr_m}^(J8|L9 z;(dC*&);J#=?pzU8Wxc=KPHz;huCzYvk3%D0$K;W_<9wid%2?3H3rZY{9jEDe*wwo zRzvMaVGc>uTcIbRa6vVARE~_gWrYUP^Ro?`@(txYvcCV{6RMH^j2!pXn5C%PQ;AWV)4;#bUmuk%t z(k2v7{#JAN&uyk2uXZXxZx7X`q{+<2p8Vs@P500=eXj&2J$nu3)+9BYomgbJu5C_E zo%1i=yIl3%i}%cgmo{?aK&?Q6GJl_a#d~%(EfO=cWNTs*GqV7k)Hg(gVmLH`lfyhb ze*;kU?pU@P&7IB&2ja78H!~@9Fe{mrV*)5(wBH{sEwvq;jA9a3?|F{y zRV<`YmuZQhUsPUTiK7WA)Ck#KQXmjq)wOiQpZ+G?6qIjX)Ja}DX?&&>s)H0j!*)aj zd>WU9wG+~+m#G+BOpQkI(Iov&QF`N6-WFD&O*3i+eJJ8@g`5YvAion0_HUPs-)Q#!n6U2q?_J(S_bGP5MOLx@G?rhT%(BZRw@!r4 z$7+Eq(Gl-g5mRUR83S>G&k?#K9csFyv4ZDhpt~R;42fgXI?{e&GP><5Dr(Jq8qC@s z22+>q^QFaTJ(I#9<&=$k@IqVM&1p`zyuVVV-{3Ni!B7UR1Zm+9NHiPR57w3NH)b?Z z57XZS)$;wp^)6YxBea*cf56Ik5%;l=Dj0#LYu5xbB?SJ_t2^AW0ljCB$u``mcJD|G zwYI)3lH{6l;CC6v5+fUQwoeF@-VD!(2sRFYf0^8D74x4y7Lo{VofyZ@mC7n*+qjV> zSoP911ikm8T6I<W>mt2<-sBLtAxZ1;vQ=xNrQ_8`U{yuksJCPkqbuR-}k6&A+0Z8Bsr1v!^lF846gE)a@==tNw76d>19IvTUkFe( zX-78HMzWu48zn|&Z^ls7y-Dp=3v$Ph>G*3ydj z=PHunLgN?%Zh0?YGms=aX9V~b@d|QA-%rwYRpN8DPr_F^F5j(8Y35lJCKwOEW7Emg z-FnYah<$Z9(atcX*Evwo`%pt@@(s>4&WBF-aUPhRJ5QM}Qp6!OgfKkmHT=rYz+XyY zVTbOfg@ zR7pnIyC3LIAOl!9T}~SU;#b~o2Ur3X!`+;a&B5HH<|p0xk?dj8i*xJ*>fB-N43n6u zY}+K8kM;-y7rQ5QVR~%D+}*Xsz1`E5`RgjbC@KW}H6C@#c@}<%8Lt>d)AUHD-;X3n z&|=dg67@7|KU}c{qcpF3u-%1qH6grCAj1dFr+;TJIa;sMv{duT;Pz6(!PahsJpykl z?D2-~Fz7-koLMU*m;D?sH&_XKMk;nRhMBe?$SuC-#-8dhE^D29Kq|Txov)AQ;dfLJ z%5m2(<2@`t_Im>N$R}{bH&yRwdAN~sRR^c*ePcWqq)XEO(cjf^hxSa%0788irlkvu zO`#duM@V6p<4nZ6`}3D2MutBDS1$QAvDVZ;P0)tRma)K^!PNsoh9`hDkuoqsD5Y}c zr8y-FA2}aA+nip#PAK@o20eG@tL?G$?|L5=l}M+8RXIBMw|Tl!=m=^e#2)*T49(L& z@WwoP>DoNb$R1w%Sy=osd40gCxx+9J?D75a!;W%PGfzlIE`_mlfx#ogATtx+G18_R6(; zl{L{~%D~5Q-HHE=_B%a*iske77Pi#5qwKgUTp$h~PRQ-~H6N(Rw5R)g1ViIacaF=< zy{&Aan^!zjKhB^kVaf-U-U)SMY(n6d%i1;DQma#T!X3{I!9QVjR9^zUqhasamv?qJ zX|>hXey#Hot;fSRqiQ*!E|811zyW^Sve%+(bC~$(vUd$Ad6$ zIQ>hPkJ4(Nzzk3279{^d#Fx*5>o<3EdowAsZC@5FJDU00Ar0$X=jUFA(1+5r5p~KX zx94>0A=t8(H{v!b6EVAf558V~h`X7hx-KwD^yJ`vLfW60mPrB;elQfWyD&=q&0a)s z(8V^+$!CQi$QBZyX&^k4VHJ^Zsc*P9VoDl!=&n7~@%{qY@Ap>KW~r22ws`=<;8t@MbUW(!`=Yn1cxxV@%#@r%Q?j~gbUw};fS zX?j#JtKY#%#nBcx`dMXm>R(M{3OMIO2x$Trxi(z__A-)o%B~2l%7JkG?>}IXBl3zx zE_t&k48{Ch*vq+{G)gC@H^efkwrx(K2tR)@jaag@3&h)RTA`y}76GXDUw7ZTY*>1) z*YpOr@F(HA2buj*MHLdOe0O}nf;%FqU-mr6F ztCt}u&S0h~hx0YJeP6tx-n2)eX}e6lS@M?%WuzztB?$mo7Kws4U{bMc8);5K*(Kd7 z3U;n0w}%1BHo-sgkA=b@oHW56+6nH3((+3eiHTFVcMvH}`+30#Mj19K5&oH{@&c9D zg~higJm{uIW&|l>9+P%-W#lX7I&9yYyPaQN7zAvou%J+Te!v?W!N@~J|Jiat&T;SG zC6`08Gm%@PQBVD(aJ&QoAar8hH5NlqI}E$hls0zNtJ_&biV*1}AdGJUFG4)OEpehT z?!6>g5y z9&%l`8W$~+FmVwnFB!I_t-|>Lv;NwKFmi5|Y+>gnHw@b>4PDSwn1^eS(#9jmrlAIJ zRhtfrd3WeG-}!dc6oiE*VI%?sDtWaWsgZ~xc!p$GZA-j!_j^B%zA<+iyWin~L3<39 zWF5O>{-<4r$MV74>Wh+-q=Bl+=skS!I>vg7K~ z--IMmlGzlfoB|*+CYJ}ZB=27VQFev>DFFH={rF@Yj@clx2ERB#_Xlod-)iR|4cs1C zUf{;C`^2FIo>h@t zh!7q$a{P?$0Q7J0WbbZgMqE5axI<9bE`uFv+ZOuTt2+peeRtcnPq|VdKY;dUMkh}@ zN(ZOrpNx->08~tH9=CV>;^su7Dk`(mX$WNv7BuJ3_~sMPHSYlYbk{}eme%8u=`BIm zlcY9q?2b#tY=7r590Vk#o-^8oa${ZuqR}0M;o*Z5Hj|J6y&3$ae%v2hriS|#HcgNV zi^EULA+$+Ey{$TEW7p!7lj%ucL;hDEa{ExdMP^bhd4;g}WZL=K^`No&R~Fm)m*(Kr z69H)y209Ax6aG;X7w$QEqi0uT(byO|VaUuwO1RYM#A0Jxl2p9R+8iuB;ulh5AU$%B z&l#k12WQPv4SOviH(y~nKBvR~0Cb&H`?q1Sp(*lW5FqLqA8oXa*Ysm88ok#Vd(?sx z)N}qj3bw>R)V1|lw3ApfCN#5K*>!faj5F+8^)%88tWRft&E(Wl$%uNH&xvY$%$*?m zC}!zBgVpLk53r52<$cg99K_5Gh=fZQy!;JMs0c#SZ~iyf;yawCryxCjJ9B#rVv#0i zIgM@Le)_}zF1{@JaMM4c0Hz^vT8W6``jNnH2~bA-m`V9-@UIxrg!*6h)T89BD1i0R z4!@9V<0fI%DE!3C()Az%25hp zv=VztVVwOSEwF!lhW#Ydd9u5zZm}-!wivxAJ=_t8XYQC@iq4KjC}WJ z%c=C`#~E5^jX=G5EwB^lJsAx%Ft|BU^NrSrVy?LDO~(U8?OwE#b|BdiKilx zh$Q(s76J>3l`o2kiD4Fdq9Oc)18R}XL^Tk$73Uum{y+*C!s-8m&z_aH^tdDyll>;n zzzr7%`o)@FAv1?pIz0W42?5%rewKxs9a5Mx&MblFH3^`hSLy%n5=s~&Mc%C4)<%~$ zI~NN#H6Ym=5BWE{P6&s-dlzkj?uUp&*>9FQ?0~>MJRbGmwJ@nHM!~uU=<>wuQlsSy zpk*2i_}oh@(?MW?R6(>Tz*&}HWU;vX6D?9nz+*qiO?HD&ie=bHf9FE7LhtD}Xn!v? zqd*yXXB+rgziVM+s4v0n|6*F9T)oc_#WQdlO#G$lVbAYnRzf+AAE5I_`Iq>BdJ`t_ zj!C+576IlMvUNBP=ua$u)dU8vPh_}s!00|rE_sVh@HR@O{eniBP6Lu8DjC*|J$Bv9??K9`fIc2Dja{_+(|&SP3j2%GoM@B_|vDFu+V1V{i#^uqrw z2JQIMBx|y!*Dn1f5@!cl0L`cRw;6=p0<=y5q^N(x*#9nX{2Vwg>2ni14(u0N4Tgv`~QloU~7K5uSvF3cSPrb9n?f_=Xa`F9N^W z?i+}IT}c+hHSptGUzRwgZaO~DTv>$_A%>s)ojla@GlrDZcGrsbp`962!_Id9S7 z(!q;8BR{gSAn6A%KCQU5)|t(6$tsn-(cHWoP-habXbq?F(->{P(o}Rj?Pwdy!t14Y zk0*IhWLINr-i@d8{A_45K!OYS2}3AP!~pSAE5^#p1^?S%MtqRL3Im1xaZKI+S$J|5}jz?qd}7^K$!XP9s|QvzV}b}Ay|?| z20N)*e0vtCpuh~q)fg&P{fcJx_&l0{)ma?{u$XNp3v`k zD$LE)Z^_U1t+WuK46_i@{LYUuA_0@vaN&3vUjk1M@Zh!Q5l=lo@eSq69=U+&f2WC3 zdytT0`;Eb^>N#5P$Oro;6Edu9Z2iBVNoWGbJVoOjA9li=< z@h5Ui`H18{iQSb5|I^)-|3mpj{~@FhvVRnkG})I*6Jto0J{7IXI*OXIN46|uOJ$c2 zgEUhqQYKr7VaC#o>`Ga(3^FELgR#x}d>`Mwf5mrxn4j+RdhT=2Iq!4sx#ymDMa%R{ zhHCnBcyK;G?fcLfa7oHM4;5=9v^<%69=2#e@hbWbfEUGMMF3k>iMYN|Xe$3~^+gOU zcJZ&k7sPzB&WLASS2wi2*##9wr%v|_J1;1Et`4?3{4o|*=}sAAngwXcn`{fjMAkZs zgGFAK+%z#6=dR!IReHk!?5;xoy~3jA5$C4->*_RsJ2dFdZT)Ycp^+fn>C?-eT~NcI zUCpI_vHu?9_tiN6kRPm)*cRSLXjzX&sGYddk5#~~7Ls_Qw7710_|Z3Yz}v`<`R}1z zrCuiQJGeTo&5EA=49QjK9$r5a;W~bQV92JDi+CyrvE;ur->mOrtx66tB#Dltr-{Ng ze^fI-gUu%k)_)fN%k7$ab6Isn$l}x5x3h4ik++WC$X$Y}XN;g4)u1Ata+la9@YT3& zx0tD@4l?3)ezEzCfeX0j!772z196O=D_U~T7tE-Api+K$_{fm5!HLeMk-4)eCP<&| z9A?pR4qB_|*@&X2>eVSq4l@VJ&scxZGaF%Vs0IQQh}DUocRx|uYw9Yl)H8|rwktNU z3+(VdY}4c(4Lx&dU~Zi(Gx>kKxr$i2<=^2Yl+25_UKdSW5LdK!1!~;U%Xp}0qnWSVeRuc&z|$_q1?m6wu0M~xj}1v#>?946nIUk zGV$2EBD8X`pxPJ23*H!=%U(;P{-ZHhXVw=!7^DH3?qjQ)@qg)zHEyRqSf)zJ#p3XS z_kZF8S_>K-(|GX|3(#<1uB2MlnS8lXh734r(!GSXx&pCx6exQy=v4}4QEffdKxLH= z;(%?0M4EV`Y4)-1 z8>AarkP=6M={Xl-4xL=LYL@*ZHgz@@eCvvVO%C9sBt|?`dE?+X-{gw01=N_(8j6cR z`rw&8KWZG!kHMzs5ib$q2NyQB)yu12hJ|57g0veQ?d=6I!DTTSrEW|=AADWb-dKst z0w>4{&Bir8#GKc2$Z+fm$V!}s+U6Pd+M%WZhcO3qWN0M)N{|AYk|ZI^eF#xbEy2Y+ z_#`f>yrj``R?a^wUi0&Jl3D-_-KapZROl>uNKe09O_cj)Zhsw6PzXqxEjK5b za!sy?c|6`Sr3Q8BIz|5ZiqJ{sN}4vsoHRc!f7_|}6=+-siXI68YN8-dT<+leoPH*^ z@96CSUiY7ILV`;`(=oD$rZ5-eqT%qJ_AfgvHf*{hjgJ6DhZ zz499{@2rVxDrDKjlUz0l2NHlJd&qw-{vD?!4eHlx(GyGSBu_u-lL3%zKk0QP)7Y&y z^e@9Y@D;?PLn0nKs;3T)m*QjV58A4@JGqf-mt3M3HHOt+c6ih>I$r_@X)F{n z+jq|G{t(8yhK&*7#Z**%>nz==28J%fN9Q0#K#i*nd2$mK5C90P%P=M9_@g zWJDD#55$QFr+WQiZ8ROs_9sVhYzjBgy3qR^rKHx(dLEU4_Vc4v|8UkVD9jW6rW3-4 zaKD0IEG7ecg|}8r1WCFNErbv{hKE0wce_W?6J&WjvoZ)*d@mQd)kR9B?YuouoR8KF z%{rUXbw)9YJLM2O}N5UdaAvUasuIC6^<+)WDepGQ~JN6^a`C!#g7#`Sf0fSIzt z^5mQv0y^l-iaUd^!MVC{C<+984JW#)zop@cfbQ}Swcew(e!6CT%;Z;-Y!F0X4t68Rc=SbC z^4FsF#+8-ZVGFkyI77<)M<^2jtp0L@OvD;(aX>q?Krf{4$6>M9PD$01@vZVth5B_t z(CbAl*I6GxRTcIG*>pL%Y4Me~RB#7f61SG6@@d1_Q|lW11Pr#)F*0&~qd%^#AjAla z$ugN?OicClUN6`)TIyhRfjzoJ*aZ?G=(ay%0e`oF{h8O*rHypWLoSCcj%9I(4mUto zP-vBcoMWk)-yfzPtv-U8R86NYPcEm|Zej#ovWMjdE&DV?Vs^S$^)_FLj9oTBU&AEv``DSRG@jq>2n{e zJ}ebB=o9d1LzVo?gzq`B*bW2gB()&{*+yH>cB+KGczdpqX^a6I$m`pmv!7{C-?v9z zLBW_M@V}Fvh+4)NU+KLByG--VF?Q_z`E3Fd%ny(O-!65jSPL7aWi;f5xlY(jXh)6# zh<%6{E^(!!^d@swDMUhN_Yu^+EHJEZbUqQp@dV2bdm63d$prvAmnuuu<;lVWzu8072IIUmefVmmh&0Q2Y>u5%OC zf1&|)PUOrH|EW5hR8^%C_Tj~SQ=cnk?$!jHd2mcKu;+o&8BP#ZCRb#fMUT`h>6c1J<;`-gDEy)ZO*mV03 z?~|sc%CgosK3&a}s*-NvMpNtB(^dOKn!uCK)gG5Rb18?3wTzisMz4MLa|ZonXN6$k z9x2Q_P=r5YW{q)2%HV<2F@6*9qNX8~I{i)S!>9S=#!IEY^#n8p6EoAKw#Z#1DuW)0 zrT%hoNGpPwZ>*1`=yOmM*R^#7w+*qT5^f>S?jK?Jwh2w{ySY^K(y*@hmGp0Y-i#`7 zxitliI4?2~BlYt+Ayn?iyR$-XCDjsB_qG|I7etp2^-1nG`%QE5ZiTuxu6A|-q@2=c z0P65sFlvSsLsS;lgwXRY!{6g;2AGeCOvWgF5InttCza+q5u)2SS|JVB?SMF_tOj_` zB}oN3|44Agc8}^x?kv4~*3aeZo#UjV)yxmn;}o5S%{MrpK518TgvB|XP{zdmu?GwI zQlYI^C-_q=43@`hv)zL}-Rap=d5;jmoNZP7g^F;J&P2bPBFW1cg3coCa_`}kRSIKg zPz>#`ec`gR&--^_KP#i#t&B0QJbkl(u4^>k$hEJwZ7%-xhm0x9UZ!A@=|ta?*b|~1 zKOvrGvg8z1^C~)-iZeCels0TrRK|V0JaGBpIdSo0g6s^+J1~zV*t8@W$$hnmbaq`G zbi}0Pz3B1JkG{i^!vJD^1n&Dm`KN~;GcyWN;@s`~Zwe3`2aGHoqS*tN*mbMZ9ZUs8 z)XYOT34t&HvfS$)eY#Xl(3{8^QVu~Di>&ID*n`=6%k@oOGiEZtbjdy@5U@n|GYY)% z$@wGsk7|(-WYRLPi=>57+{MKKWAsJ`bb&gFDIpUpW+r`t-I_uoRW)p6sdr^6$a~8C z8d+Q{TZu-72$t;z@rv$;WOE|0^x)v&P`_KpmdTwaq6UWM8~wG~`lv}#ELf8ocUW*0 z<&zQhiF9<6Sb~k32dn6eFUsz~2GseF=9&~p;CIVL^m>7_w2vp!38OKDAH5m-;qygb z&Oa50=;x9Cuow7mjgE2rJZsTc5$Ps;F?nzq!qu1O9MI1H0JqdVP|k-{SmVFi?HdC^ zBIeqNjFxZ#3Z>l;b}WaSGpw-C^3uJz$>Zwn3$50t!35GTnsF;R^4f&z#`-M@>I=jd z3??_e=Ev1xbt|lbBCe13C!2L8(`dAcLv`F$AWGk&U^e)gTQE!Y z+N(~Jgq1LUv*N%%=Ks}5a+=|=tGoq}^6B6uxxj#G3Gt1IAKGlj1n09cqr>-}ZF$Xc zd24|v>Q&JhGV#{vMmN)=&0yoziPfZ?r*hxSqTnJ)>Q<+|u&w^xEN`}ZA-R544`pd& zmwa^pTQSy3k*y$1Y$gduS9+>pRRgP)S7dN7mzN$=E74l7#r((61OFap z#dgtz$w&nxFWt8P5Bw69{fDtLrXp9t+npWM4{#gFCFX~2-zuC!f`+b0_L>CuyTJ?E zypPYnUNG1EP{`z{@FOqQ?A>P`zO|uoHlXk6$BJ6fsJ`Pf7cvtq5F#QmiYx74;QhoJ zt63fn?_w}pKc=lzsqJopilQq#htgFwnqrOz&ou$NE#@Qm1&Zs9(^)FfM?Vvzg%kL9 zT7*1KD>e8=^O?9!y{5HG4!)1jf1c0WM#?^w{jy8CZwZ)Xu!*Wq0{asVPvf?Je=Q>U zh^xzO^~Ysqim4jTW~tz;tNcc55y`LaTzGLo4vnREERr|5(y?&_g>auYV}RUaID;6? zNp^^yzfA7OuQf*LZnt>%XnP|1Fn~=6GwFG+DU1LNCGH-=CY0EU!m4FUHWrX#AjVax zPi7;k%SiV;1S?u1U`HUK48Dm#Uid1WOXhcj`v + + diff --git a/extensions/blume-search/assets/projects.svg b/extensions/blume-search/assets/projects.svg new file mode 100644 index 00000000000..d5133bbe9e3 --- /dev/null +++ b/extensions/blume-search/assets/projects.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/extensions/blume-search/assets/setup.svg b/extensions/blume-search/assets/setup.svg new file mode 100644 index 00000000000..5829e977fdf --- /dev/null +++ b/extensions/blume-search/assets/setup.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/extensions/blume-search/assets/suggestions.svg b/extensions/blume-search/assets/suggestions.svg new file mode 100644 index 00000000000..8187694601c --- /dev/null +++ b/extensions/blume-search/assets/suggestions.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/extensions/blume-search/eslint.config.cjs b/extensions/blume-search/eslint.config.cjs new file mode 100644 index 00000000000..a0199bd923a --- /dev/null +++ b/extensions/blume-search/eslint.config.cjs @@ -0,0 +1,8 @@ +const raycastConfig = require("@raycast/eslint-config"); + +module.exports = [ + { + files: ["src/**/*.{js,jsx,ts,tsx}"], + }, + ...raycastConfig.flat(), +]; diff --git a/extensions/blume-search/package-lock.json b/extensions/blume-search/package-lock.json new file mode 100644 index 00000000000..bc236524e7d --- /dev/null +++ b/extensions/blume-search/package-lock.json @@ -0,0 +1,3007 @@ +{ + "name": "blume-search", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "blume-search", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "@raycast/api": "^1.104.23", + "react": "19.0.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.1.1", + "@types/node": "^22.19.1", + "@types/react": "^19.2.7", + "eslint": "^9.39.4", + "typescript": "^5.9.3" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "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": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "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.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "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": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha512-l2Ul9PrHsPCKcEY/ac7VgFj9D80C7S68sOKc618SyHDPK36s1XcFebXY0iTzUVn4Yq+YbwvSnDmCz9yxjX+QrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "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": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "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.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/ansi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz", + "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.3.2.tgz", + "integrity": "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.21", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz", + "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz", + "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "cli-width": "^4.1.0", + "mute-stream": "^2.0.0", + "signal-exit": "^4.1.0", + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.23", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.23.tgz", + "integrity": "sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/external-editor": "^1.0.3", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.23.tgz", + "integrity": "sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", + "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", + "license": "MIT", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz", + "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.3.1.tgz", + "integrity": "sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.23.tgz", + "integrity": "sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.23", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.23.tgz", + "integrity": "sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.10.1", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.10.1.tgz", + "integrity": "sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg==", + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.3.2", + "@inquirer/confirm": "^5.1.21", + "@inquirer/editor": "^4.2.23", + "@inquirer/expand": "^4.0.23", + "@inquirer/input": "^4.3.1", + "@inquirer/number": "^3.0.23", + "@inquirer/password": "^4.0.23", + "@inquirer/rawlist": "^4.1.11", + "@inquirer/search": "^3.2.2", + "@inquirer/select": "^4.4.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.11.tgz", + "integrity": "sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.2.2.tgz", + "integrity": "sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.4.2.tgz", + "integrity": "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w==", + "license": "MIT", + "dependencies": { + "@inquirer/ansi": "^1.0.2", + "@inquirer/core": "^10.3.2", + "@inquirer/figures": "^1.0.15", + "@inquirer/type": "^3.0.10", + "yoctocolors-cjs": "^2.1.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz", + "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@oclif/core": { + "version": "4.13.3", + "resolved": "https://registry.npmjs.org/@oclif/core/-/core-4.13.3.tgz", + "integrity": "sha512-wBp2igI2KVwq2ZmpnfmGtOROo7aXZIr3OEtAS16g1wHFBqyEuswL+9K50NJWJvlpAmxd+4dVj/ycawXESU3wQQ==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.3.2", + "ansis": "^3.17.0", + "clean-stack": "^3.0.1", + "cli-spinners": "^2.9.2", + "debug": "^4.4.3", + "ejs": "^3.1.10", + "get-package-type": "^0.1.0", + "indent-string": "^4.0.0", + "is-wsl": "^2.2.0", + "lilconfig": "^3.1.3", + "minimatch": "^10.2.5", + "semver": "^7.8.1", + "string-width": "^4.2.3", + "supports-color": "^8", + "tinyglobby": "^0.2.17", + "widest-line": "^3.1.0", + "wordwrap": "^1.0.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-autocomplete": { + "version": "3.2.56", + "resolved": "https://registry.npmjs.org/@oclif/plugin-autocomplete/-/plugin-autocomplete-3.2.56.tgz", + "integrity": "sha512-P96b6RZvQatlJ6pX6sgIFOQhgX2tFVhgSfw53GT/MajecCQNFGVqagJKo2CfcPsacDpuFuPRT6zji8h1oaqtrA==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4", + "ansis": "^3.16.0", + "debug": "^4.4.1", + "ejs": "^3.1.10" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-help": { + "version": "6.2.58", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.2.58.tgz", + "integrity": "sha512-DAYMXZrTWRMLTbpX+rT+ibAmKrZ6IVNGn+fgAGjMoeNlqlSY94eJHocgmqChMwsdWp3H3x+jFmPJiYQt/ifr3Q==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@oclif/plugin-not-found": { + "version": "3.2.93", + "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-3.2.93.tgz", + "integrity": "sha512-KBizxn+kgTPWLUCo/vDz/oDdEA5Ll5H6x0jJhl05B56yHwgQp46ZxwXmtBsxvvgrmMqJEtFUw2Qrq+nTHWWv4g==", + "license": "MIT", + "dependencies": { + "@inquirer/prompts": "^7.10.1", + "@oclif/core": "^4.13.3", + "ansis": "^3.17.0", + "fast-levenshtein": "^3.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@raycast/api": { + "version": "1.104.24", + "resolved": "https://registry.npmjs.org/@raycast/api/-/api-1.104.24.tgz", + "integrity": "sha512-Jppfyi1T7wcGXZFxpzXuvNAKUPQ+BQkKC0N3rJBz1epp/z22SH9aLA23YZRk/ickGwEm6DI/7OY7Jin8dD53Sg==", + "license": "MIT", + "dependencies": { + "@oclif/core": "^4.8.4", + "@oclif/plugin-autocomplete": "^3.2.40", + "@oclif/plugin-help": "^6.2.37", + "@oclif/plugin-not-found": "^3.2.74", + "@types/node": "22.19.17", + "@types/react": "19.0.10", + "esbuild": "^0.27.3", + "react": "19.0.0" + }, + "bin": { + "ray": "bin/run.js" + }, + "engines": { + "node": ">=22.22.2" + }, + "peerDependencies": { + "@types/node": "22.19.17", + "@types/react": "19.0.10", + "react-devtools": "6.1.1" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@types/react": { + "optional": true + }, + "react-devtools": { + "optional": true + } + } + }, + "node_modules/@raycast/api/node_modules/@types/node": { + "version": "22.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", + "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@raycast/api/node_modules/@types/react": { + "version": "19.0.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.10.tgz", + "integrity": "sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@raycast/eslint-config": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@raycast/eslint-config/-/eslint-config-2.2.0.tgz", + "integrity": "sha512-uS/UDvM+3HfABgYhLYnIv0y+IVu+rGiZZIMwQsO5EGrcf2/TX/yioTzfezAQqhdszW4ViCuHbv8BddIagDKZvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.39.4", + "@raycast/eslint-plugin": "^2.2.0", + "eslint-config-prettier": "^10.1.8", + "globals": "^17.7.0", + "typescript-eslint": "^8.62.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "prettier": ">=2", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@raycast/eslint-plugin": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@raycast/eslint-plugin/-/eslint-plugin-2.2.0.tgz", + "integrity": "sha512-ixO3PoRAEAZZcSQeRPvvDS/vs09D47tXdyXrs7hctoxxPtweXgJ6I24kjCD5GuuuQS5hGTiuL+Uy6hIg6a/a4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.62.0" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/react": { + "version": "19.2.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.18.tgz", + "integrity": "sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.67.0.tgz", + "integrity": "sha512-Un7Heoyj65NREbKAyIrFxeM143NZpExWmy1Nep4DLeQOeLlTeumPjoNKnBrU5D5moWXbPJgRa5Uwcdu0faVNGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/type-utils": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.67.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.67.0.tgz", + "integrity": "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.67.0.tgz", + "integrity": "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.67.0", + "@typescript-eslint/types": "^8.67.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.67.0.tgz", + "integrity": "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.67.0.tgz", + "integrity": "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.67.0.tgz", + "integrity": "sha512-aVWDXbRmdXO9siTfX4ditQI1T9+zVcNazT48EJCD0v40/9RIFoUgZ05CmGEq9H2gixRpjUn/iplwvlcvutJW/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.67.0.tgz", + "integrity": "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.67.0.tgz", + "integrity": "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.67.0", + "@typescript-eslint/tsconfig-utils": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/visitor-keys": "8.67.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.67.0.tgz", + "integrity": "sha512-U9D1FdwEWBwok3hxxSdhclMb0twvt9QnjIQ0VfQ1AiX2epnpSgv2ubVDsayOFyY8K6FX+AQ7E0FKWVG3iKsj1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.67.0", + "@typescript-eslint/types": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.67.0.tgz", + "integrity": "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.67.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chardet": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", + "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "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", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@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", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", + "license": "MIT", + "dependencies": { + "fastest-levenshtein": "^1.0.7" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.11.0.tgz", + "integrity": "sha512-Z2I8hM+PbJDXQDq3Icgpzv+mPdwr68iZUU9d5WW4FuXfDUQfkZaZuvjMv42/5crNyw154+9+VWXbYrUgDXbxNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.3.tgz", + "integrity": "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.6", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.6.tgz", + "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", + "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.67.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.67.0.tgz", + "integrity": "sha512-S2udFs8tCKEKffuJ4TB1idGUZiXdCPGi3IPBGWXarbLQ5UPXORV8QEVzJ4gCRduURMb5EkpNCdjbk0eDIuI8Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.67.0", + "@typescript-eslint/parser": "8.67.0", + "@typescript-eslint/typescript-estree": "8.67.0", + "@typescript-eslint/utils": "8.67.0" + }, + "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 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", + "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/extensions/blume-search/package.json b/extensions/blume-search/package.json new file mode 100644 index 00000000000..cb56cb27763 --- /dev/null +++ b/extensions/blume-search/package.json @@ -0,0 +1,51 @@ +{ + "name": "blume-search", + "title": "Blume Search", + "description": "Search projects, conversations, messages, setup, and suggestions in Blume.", + "icon": "icon.png", + "author": "olav_ljosland", + "access": "public", + "platforms": ["macOS"], + "categories": ["Productivity"], + "license": "MIT", + "private": true, + "version": "1.0.0", + "type": "module", + "scripts": { + "build": "ray build -e dist", + "dev": "ray develop", + "lint": "ray lint --non-interactive", + "publish": "ray publish", + "test": "node --experimental-strip-types --test src/*.test.ts", + "typecheck": "tsc --noEmit" + }, + "commands": [ + { + "name": "search", + "title": "Search Blume", + "description": "Search everything indexed by Blume and open a result in the app.", + "mode": "view", + "keywords": ["projects", "messages", "artifacts", "conversations"] + } + ], + "preferences": [ + { + "name": "application", + "type": "appPicker", + "required": false, + "title": "Blume Application", + "description": "Optionally choose Blume Canary instead of the stable Blume installation." + } + ], + "dependencies": { + "@raycast/api": "^1.104.23", + "react": "19.0.0" + }, + "devDependencies": { + "@raycast/eslint-config": "^2.1.1", + "@types/node": "^22.19.1", + "@types/react": "^19.2.7", + "eslint": "^9.39.4", + "typescript": "^5.9.3" + } +} diff --git a/extensions/blume-search/src/blumeSearchClient.test.ts b/extensions/blume-search/src/blumeSearchClient.test.ts new file mode 100644 index 00000000000..05c835ebe34 --- /dev/null +++ b/extensions/blume-search/src/blumeSearchClient.test.ts @@ -0,0 +1,117 @@ +import assert from "node:assert/strict"; +import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import test from "node:test"; + +import { BlumeSearchClient } from "./helperProcessClient.ts"; +import { helperLaunchForApplication } from "./helperLaunch.ts"; + +test("Raycast launches the helper shipped inside Blume with its bundled Node runtime", () => { + const directory = mkdtempSync(join(tmpdir(), "blume-raycast-app-")); + const applicationPath = join(directory, "Blume.app"); + const executable = join(applicationPath, "Contents", "MacOS", "Blume"); + const helper = join(applicationPath, "Contents", "Resources", "app.asar", "out", "main", "raycastSearch.js"); + mkdirSync(join(applicationPath, "Contents", "MacOS"), { recursive: true }); + mkdirSync(join(applicationPath, "Contents", "Resources", "app.asar", "out", "main"), { + recursive: true, + }); + writeFileSync(executable, ""); + writeFileSync(helper, ""); + try { + const launch = helperLaunchForApplication({ + name: "Blume", + path: applicationPath, + bundleId: "page.blume.sidecar", + }); + assert.equal(launch.command, executable); + assert.deepEqual(launch.args, [helper]); + assert.equal(launch.env.ELECTRON_RUN_AS_NODE, "1"); + } finally { + rmSync(directory, { recursive: true, force: true }); + } +}); + +test("Raycast reports an outdated Blume app without the helper", () => { + const directory = mkdtempSync(join(tmpdir(), "blume-raycast-old-app-")); + try { + assert.throws( + () => + helperLaunchForApplication({ + name: "Blume", + path: join(directory, "Blume.app"), + bundleId: "page.blume.sidecar", + }), + /does not include Raycast search yet/, + ); + } finally { + rmSync(directory, { recursive: true, force: true }); + } +}); + +test("Raycast preserves a helper failure that happens before the first search", async () => { + const client = new BlumeSearchClient({ + command: join(tmpdir(), "missing-blume-search-helper"), + args: [], + env: process.env, + }); + await assert.rejects(client.ready(), /ENOENT|spawn/); + await assert.rejects(client.search({ query: "project", categories: ["projects"] }), /ENOENT|spawn/); +}); + +test("Raycast rejects a malformed helper response through the controlled error path", async () => { + const directory = mkdtempSync(join(tmpdir(), "blume-raycast-invalid-response-")); + const script = join(directory, "helper.mjs"); + writeFileSync( + script, + `process.stdout.write(JSON.stringify({ version: 1, type: "ready", supportedVersions: [1] }) + "\\n");\nprocess.stdin.once("data", () => process.stdout.write("null\\n"));\n`, + ); + const client = new BlumeSearchClient({ command: process.execPath, args: [script], env: process.env }); + try { + await client.ready(); + await assert.rejects(client.search({ query: "project", categories: ["projects"] }), /invalid response/); + } finally { + client.dispose(); + rmSync(directory, { recursive: true, force: true }); + } +}); + +test("Raycast falls back to the additive legacy v1 helper protocol", async () => { + const directory = mkdtempSync(join(tmpdir(), "blume-raycast-legacy-helper-")); + const script = join(directory, "helper.mjs"); + writeFileSync( + script, + `process.stdin.once("data", (chunk) => { const request = JSON.parse(String(chunk)); process.stdout.write(JSON.stringify({ version: 1, type: "search-result", id: request.id, ok: true, page: { results: [], truncated: false } }) + "\\n"); });\n`, + ); + const client = new BlumeSearchClient({ command: process.execPath, args: [script], env: process.env }); + try { + await client.ready(); + assert.deepEqual(await client.search({ query: "project", categories: ["projects"] }), { + results: [], + truncated: false, + }); + } finally { + client.dispose(); + rmSync(directory, { recursive: true, force: true }); + } +}); + +test("Raycast rejects oversized requests before writing to the helper", async () => { + const directory = mkdtempSync(join(tmpdir(), "blume-raycast-request-limit-")); + const script = join(directory, "helper.mjs"); + writeFileSync( + script, + `process.stdout.write(JSON.stringify({ version: 1, type: "ready", supportedVersions: [1] }) + "\\n"); setTimeout(() => {}, 10_000);\n`, + ); + const client = new BlumeSearchClient({ command: process.execPath, args: [script], env: process.env }); + try { + await client.ready(); + await assert.rejects( + client.search({ query: "x".repeat(9 * 1024), categories: ["projects"] }), + /request is too large/, + ); + } finally { + client.dispose(); + rmSync(directory, { recursive: true, force: true }); + } +}); diff --git a/extensions/blume-search/src/blumeSearchClient.ts b/extensions/blume-search/src/blumeSearchClient.ts new file mode 100644 index 00000000000..dcd2fea2128 --- /dev/null +++ b/extensions/blume-search/src/blumeSearchClient.ts @@ -0,0 +1,29 @@ +import { getApplications, type Application } from "@raycast/api"; + +import { BlumeSearchClient } from "./helperProcessClient.ts"; +import { helperLaunchForApplication } from "./helperLaunch.ts"; + +export { helperLaunchForApplication } from "./helperLaunch.ts"; +export { BlumeSearchClient, SearchSupersededError } from "./helperProcessClient.ts"; +export type { SearchInput } from "./helperProcessClient.ts"; + +const BLUME_BUNDLE_IDS = ["page.blume.sidecar", "page.blume.sidecar.canary"]; +export async function resolveBlumeApplication(preferred?: Application): Promise { + if (preferred) return preferred; + const applications = await getApplications(); + const blume = applications + .filter((application) => (application.bundleId ? BLUME_BUNDLE_IDS.includes(application.bundleId) : false)) + .sort( + (left, right) => BLUME_BUNDLE_IDS.indexOf(left.bundleId ?? "") - BLUME_BUNDLE_IDS.indexOf(right.bundleId ?? ""), + )[0]; + if (!blume) throw new Error("Install or update Blume before using Blume Search."); + return blume; +} + +export async function createBlumeSearchClient(preferred?: Application): Promise { + const application = await resolveBlumeApplication(preferred); + const protocol = application.bundleId === "page.blume.sidecar.canary" ? "blume-canary" : "blume"; + const client = new BlumeSearchClient(helperLaunchForApplication(application), protocol); + await client.ready(); + return client; +} diff --git a/extensions/blume-search/src/helperLaunch.ts b/extensions/blume-search/src/helperLaunch.ts new file mode 100644 index 00000000000..aa1392fa863 --- /dev/null +++ b/extensions/blume-search/src/helperLaunch.ts @@ -0,0 +1,32 @@ +import { existsSync } from "node:fs"; +import { basename, join } from "node:path"; + +export interface InstalledApplication { + name: string; + path: string; + bundleId?: string; +} + +export interface BlumeHelperLaunch { + command: string; + args: string[]; + env: NodeJS.ProcessEnv; +} + +export function helperLaunchForApplication(application: InstalledApplication): BlumeHelperLaunch { + const resources = join(application.path, "Contents", "Resources"); + const helper = join(resources, "app.asar", "out", "main", "raycastSearch.js"); + const executableNames = Array.from( + new Set([application.name, basename(application.path, ".app"), "Blume", "Blume Canary"]), + ); + const command = executableNames.map((name) => join(application.path, "Contents", "MacOS", name)).find(existsSync); + + if (!command || !existsSync(helper)) { + throw new Error(`${application.name} does not include Raycast search yet. Update Blume and try again.`); + } + return { + command, + args: [helper], + env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" }, + }; +} diff --git a/extensions/blume-search/src/helperProcessClient.ts b/extensions/blume-search/src/helperProcessClient.ts new file mode 100644 index 00000000000..d4cbae1e451 --- /dev/null +++ b/extensions/blume-search/src/helperProcessClient.ts @@ -0,0 +1,190 @@ +import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process"; + +import type { BlumeHelperLaunch } from "./helperLaunch.ts"; +import { + parseSearchResponse, + RAYCAST_SEARCH_MAX_REQUEST_BYTES, + RAYCAST_SEARCH_PROTOCOL_VERSION, + type GlobalSearchCategory, + type GlobalSearchPage, + type SearchRequest, +} from "./protocol.ts"; + +const RESPONSE_TIMEOUT_MS = 5_000; +const READY_HANDSHAKE_GRACE_MS = 500; +const MAX_RESPONSE_BUFFER_BYTES = 2 * 1024 * 1024; + +export interface SearchInput { + query: string; + categories: GlobalSearchCategory[]; +} + +interface PendingSearch { + id: number; + resolve(page: GlobalSearchPage): void; + reject(error: Error): void; + timeout: ReturnType; +} + +export class SearchSupersededError extends Error { + constructor() { + super("Search superseded"); + this.name = "SearchSupersededError"; + } +} + +export class BlumeSearchClient { + readonly deepLinkProtocol: "blume" | "blume-canary"; + private readonly child: ChildProcessWithoutNullStreams; + private nextId = 1; + private pending: PendingSearch | null = null; + private stdoutBuffer = ""; + private stderrBuffer = ""; + private disposed = false; + private terminalError: Error | null = null; + private readonly readyPromise: Promise; + private resolveReady!: () => void; + private rejectReady!: (error: Error) => void; + private readySettled = false; + private readyTimer: ReturnType | null = null; + + constructor(launch: BlumeHelperLaunch, deepLinkProtocol: "blume" | "blume-canary" = "blume") { + this.deepLinkProtocol = deepLinkProtocol; + this.readyPromise = new Promise((resolve, reject) => { + this.resolveReady = resolve; + this.rejectReady = reject; + }); + this.child = spawn(launch.command, launch.args, { + env: launch.env, + stdio: ["pipe", "pipe", "pipe"], + }); + this.child.stdout.setEncoding("utf8"); + this.child.stderr.setEncoding("utf8"); + this.child.stdout.on("data", (chunk: string) => this.receive(chunk)); + this.child.stderr.on("data", (chunk: string) => { + this.stderrBuffer = `${this.stderrBuffer}${chunk}`.slice(-2_000); + }); + this.child.stdin.on("error", (error) => { + if (!this.disposed) this.fail(error); + }); + this.child.once("error", (error) => this.fail(error)); + this.child.once("exit", (code) => { + if (this.disposed) return; + const detail = this.stderrBuffer.trim(); + this.fail(new Error(detail || `Blume search helper exited${code === null ? "" : ` with code ${code}`}.`)); + }); + this.readyTimer = setTimeout(() => { + if (this.readySettled) return; + // Helpers released before the additive ready frame still speak protocol v1 and wait for a request. + this.readySettled = true; + this.resolveReady(); + }, READY_HANDSHAKE_GRACE_MS); + this.readyTimer.unref?.(); + } + + ready(): Promise { + return this.readyPromise; + } + + search(input: SearchInput): Promise { + if (this.disposed) return Promise.reject(this.terminalError ?? new Error("Blume search helper is closed.")); + if (this.pending) this.settle(this.pending, { error: new SearchSupersededError() }); + const id = this.nextId++; + const request: SearchRequest = { + version: RAYCAST_SEARCH_PROTOCOL_VERSION, + type: "search", + id, + query: input.query, + categories: input.categories, + }; + const serializedRequest = JSON.stringify(request); + if (Buffer.byteLength(serializedRequest, "utf8") > RAYCAST_SEARCH_MAX_REQUEST_BYTES) { + return Promise.reject(new Error("Blume search request is too large.")); + } + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => { + if (this.pending?.id !== id) return; + this.fail(new Error("Blume search timed out.")); + }, RESPONSE_TIMEOUT_MS); + this.pending = { id, resolve, reject, timeout }; + this.child.stdin.write(`${serializedRequest}\n`, (error) => { + if (error && this.pending?.id === id) this.fail(error); + }); + }); + } + + dispose(): void { + if (this.disposed) return; + if (!this.readySettled) { + this.readySettled = true; + if (this.readyTimer) clearTimeout(this.readyTimer); + this.readyTimer = null; + this.rejectReady(new Error("Blume search helper was closed before it started.")); + } + this.disposed = true; + if (this.pending) this.settle(this.pending, { error: new Error("Search closed.") }); + this.child.stdin.end(); + this.child.kill(); + } + + private receive(chunk: string): void { + this.stdoutBuffer += chunk; + let newline = this.stdoutBuffer.indexOf("\n"); + while (newline >= 0) { + const line = this.stdoutBuffer.slice(0, newline); + this.stdoutBuffer = this.stdoutBuffer.slice(newline + 1); + this.receiveLine(line); + newline = this.stdoutBuffer.indexOf("\n"); + } + if (Buffer.byteLength(this.stdoutBuffer, "utf8") > MAX_RESPONSE_BUFFER_BYTES) { + this.fail(new Error("Blume search returned too much data.")); + } + } + + private receiveLine(line: string): void { + let response; + try { + response = parseSearchResponse(line); + } catch { + this.fail(new Error("Blume search returned an invalid response.")); + return; + } + if (response.type === "ready") { + if (this.readySettled) return; + if (!response.supportedVersions.includes(RAYCAST_SEARCH_PROTOCOL_VERSION)) { + this.fail(new Error("Update Blume or this extension to a compatible search version.")); + return; + } + this.readySettled = true; + if (this.readyTimer) clearTimeout(this.readyTimer); + this.readyTimer = null; + this.resolveReady(); + return; + } + if (!this.pending || response.id !== this.pending.id) return; + if (response.ok) this.settle(this.pending, { page: response.page }); + else this.settle(this.pending, { error: new Error(response.error) }); + } + + private settle(pending: PendingSearch, outcome: { page: GlobalSearchPage } | { error: Error }): void { + clearTimeout(pending.timeout); + if (this.pending === pending) this.pending = null; + if ("page" in outcome) pending.resolve(outcome.page); + else pending.reject(outcome.error); + } + + private fail(error: Error): void { + this.terminalError = error; + if (!this.readySettled) { + this.readySettled = true; + if (this.readyTimer) clearTimeout(this.readyTimer); + this.readyTimer = null; + this.rejectReady(error); + } + if (this.pending) this.settle(this.pending, { error }); + if (!this.disposed) { + this.disposed = true; + this.child.kill(); + } + } +} diff --git a/extensions/blume-search/src/protocol.ts b/extensions/blume-search/src/protocol.ts new file mode 100644 index 00000000000..d6d1c0eda7f --- /dev/null +++ b/extensions/blume-search/src/protocol.ts @@ -0,0 +1,146 @@ +export const GLOBAL_SEARCH_CATEGORIES = ["conversations", "messages", "projects", "setup", "suggestions"] as const; +export const RAYCAST_SEARCH_PROTOCOL_VERSION = 1 as const; +export const RAYCAST_SEARCH_MAX_REQUEST_BYTES = 8 * 1024; + +export type GlobalSearchCategory = (typeof GLOBAL_SEARCH_CATEGORIES)[number]; + +interface GlobalSearchResultBase { + id: string; + category: GlobalSearchCategory; + title: string; + subtitle: string | null; + excerpt: string | null; + rank: number; + updatedAt: number; +} + +export interface GlobalMessageSearchResult extends GlobalSearchResultBase { + category: "messages"; + conversationRef: string; + conversationId: string; + transcriptMatchKey: string; + matchLabel: "User" | "Assistant" | "Tool result" | "Tool" | "Tasks updated"; + turnPosition: number | null; + focusEventId: number | null; + focusToolCallId: number | null; +} + +export interface GlobalConversationSearchResult extends GlobalSearchResultBase { + category: "conversations"; + conversationRef: string; + conversationId: string; + projectId: string | null; + workspaceLocationId: string | null; + harnessId: string; +} + +export interface GlobalProjectSearchResult extends GlobalSearchResultBase { + category: "projects"; + projectId: string; + root: string; +} + +export interface GlobalSetupSearchResult extends GlobalSearchResultBase { + category: "setup"; + artifactId: string; + projectId: string | null; + harnessId: string; + sourcePath: string | null; +} + +export interface GlobalSuggestionSearchResult extends GlobalSearchResultBase { + category: "suggestions"; + suggestionId: string; + status: string; +} + +export type GlobalSearchResult = + | GlobalConversationSearchResult + | GlobalMessageSearchResult + | GlobalProjectSearchResult + | GlobalSetupSearchResult + | GlobalSuggestionSearchResult; + +export interface GlobalSearchPage { + results: GlobalSearchResult[]; + truncated: boolean; +} + +export interface SearchRequest { + version: 1; + type: "search"; + id: number; + query: string; + categories: GlobalSearchCategory[]; +} + +export type SearchResponse = + | { version: 1; type: "ready"; supportedVersions: number[] } + | { version: 1; type: "search-result"; id: number; ok: true; page: GlobalSearchPage } + | { version: 1; type: "search-result"; id: number; ok: false; error: string }; + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null; +} + +function isSearchResult(value: unknown): value is GlobalSearchResult { + if (!isRecord(value) || !GLOBAL_SEARCH_CATEGORIES.includes(value.category as GlobalSearchCategory)) return false; + if ( + typeof value.id !== "string" || + typeof value.title !== "string" || + (value.subtitle !== null && typeof value.subtitle !== "string") || + (value.excerpt !== null && typeof value.excerpt !== "string") || + typeof value.rank !== "number" || + typeof value.updatedAt !== "number" + ) { + return false; + } + switch (value.category) { + case "conversations": + return typeof value.conversationRef === "string" && typeof value.conversationId === "string"; + case "messages": + return ( + typeof value.conversationRef === "string" && + typeof value.conversationId === "string" && + typeof value.transcriptMatchKey === "string" + ); + case "projects": + return typeof value.projectId === "string" && typeof value.root === "string"; + case "setup": + return typeof value.artifactId === "string"; + case "suggestions": + return typeof value.suggestionId === "string"; + default: + return false; + } +} + +export function parseSearchResponse(line: string): SearchResponse { + const value: unknown = JSON.parse(line); + if (!isRecord(value) || value.version !== RAYCAST_SEARCH_PROTOCOL_VERSION) { + throw new TypeError("Invalid Blume search response"); + } + if ( + value.type === "ready" && + Array.isArray(value.supportedVersions) && + value.supportedVersions.every((version) => Number.isSafeInteger(version)) + ) { + return value as SearchResponse; + } + if (value.type !== "search-result" || !Number.isSafeInteger(value.id) || typeof value.ok !== "boolean") { + throw new TypeError("Invalid Blume search response"); + } + if (value.ok) { + if ( + !isRecord(value.page) || + typeof value.page.truncated !== "boolean" || + !Array.isArray(value.page.results) || + !value.page.results.every(isSearchResult) + ) { + throw new TypeError("Invalid Blume search response"); + } + } else if (typeof value.error !== "string") { + throw new TypeError("Invalid Blume search response"); + } + return value as SearchResponse; +} diff --git a/extensions/blume-search/src/search.tsx b/extensions/blume-search/src/search.tsx new file mode 100644 index 00000000000..739ebaab25a --- /dev/null +++ b/extensions/blume-search/src/search.tsx @@ -0,0 +1,185 @@ +import { + Action, + ActionPanel, + Color, + getPreferenceValues, + Icon, + List, + openExtensionPreferences, + type Application, +} from "@raycast/api"; +import { useEffect, useRef, useState } from "react"; + +import { createBlumeSearchClient, SearchSupersededError, type BlumeSearchClient } from "./blumeSearchClient.ts"; +import { searchStateForApplicationChange, type SearchState } from "./searchLifecycle.ts"; +import { + ALL_SEARCH_CATEGORIES, + blumeDeepLinkForResult, + categoriesForFilter, + resultSubtitle, + SEARCH_CATEGORY_ICONS, + SEARCH_CATEGORY_LABELS, + type SearchCategoryFilter, +} from "./searchModel.ts"; + +interface Preferences { + application?: Application; +} + +export default function SearchBlume(): React.JSX.Element { + const preferences = getPreferenceValues(); + const clientRef = useRef(null); + const [clientReady, setClientReady] = useState(false); + const [deepLinkProtocol, setDeepLinkProtocol] = useState<"blume" | "blume-canary">("blume"); + const [query, setQuery] = useState(""); + const [filter, setFilter] = useState("all"); + const [state, setState] = useState({ + results: [], + isLoading: true, + error: null, + }); + + useEffect(() => { + let active = true; + setClientReady(false); + setState(searchStateForApplicationChange()); + void createBlumeSearchClient(preferences.application) + .then((client) => { + if (!active) { + client.dispose(); + return; + } + clientRef.current = client; + setDeepLinkProtocol(client.deepLinkProtocol); + setClientReady(true); + setState((previous) => ({ ...previous, isLoading: false, error: null })); + }) + .catch((error: unknown) => { + if (!active) return; + setState({ + results: [], + isLoading: false, + error: error instanceof Error ? error.message : "Could not start Blume search.", + }); + }); + return () => { + active = false; + clientRef.current?.dispose(); + clientRef.current = null; + }; + }, [preferences.application]); + + useEffect(() => { + let current = true; + const normalizedQuery = query.trim(); + const client = clientRef.current; + if (normalizedQuery.length < 2 || !clientReady || !client) { + if (clientReady) setState({ results: [], isLoading: false, error: null }); + return () => { + current = false; + }; + } + + setState((previous) => ({ ...previous, isLoading: true, error: null })); + void client + .search({ query: normalizedQuery, categories: categoriesForFilter(filter) }) + .then((page) => { + if (current) setState({ results: page.results, isLoading: false, error: null }); + }) + .catch((error: unknown) => { + if (!current || error instanceof SearchSupersededError) return; + setState({ + results: [], + isLoading: false, + error: error instanceof Error ? error.message : "Blume search failed.", + }); + }); + + return () => { + current = false; + }; + }, [clientReady, filter, query]); + + const emptyTitle = state.error + ? "Blume Search Is Unavailable" + : query.trim().length < 2 + ? "Search Blume" + : "No Results"; + const emptyDescription = + state.error ?? + (query.trim().length < 2 + ? "Type at least two characters to search projects, conversations, messages, setup, and suggestions." + : "Try another query or search all categories."); + + return ( + setFilter(value as SearchCategoryFilter)} + storeValue + > + + {ALL_SEARCH_CATEGORIES.map((category) => ( + + ))} + + } + > + {state.results.length === 0 ? ( + + + + ) : undefined + } + /> + ) : ( + state.results.map((result) => ( + 0 ? [{ date: new Date(result.updatedAt) }] : []), + ]} + actions={ + + + + + } + /> + )) + )} + + ); +} diff --git a/extensions/blume-search/src/searchLifecycle.test.ts b/extensions/blume-search/src/searchLifecycle.test.ts new file mode 100644 index 00000000000..eb361dafb4f --- /dev/null +++ b/extensions/blume-search/src/searchLifecycle.test.ts @@ -0,0 +1,12 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import { searchStateForApplicationChange } from "./searchLifecycle.ts"; + +test("switching Blume applications clears stale results and returns to loading", () => { + assert.deepEqual(searchStateForApplicationChange(), { + results: [], + isLoading: true, + error: null, + }); +}); diff --git a/extensions/blume-search/src/searchLifecycle.ts b/extensions/blume-search/src/searchLifecycle.ts new file mode 100644 index 00000000000..290af964534 --- /dev/null +++ b/extensions/blume-search/src/searchLifecycle.ts @@ -0,0 +1,11 @@ +import type { GlobalSearchResult } from "./protocol.ts"; + +export interface SearchState { + results: GlobalSearchResult[]; + isLoading: boolean; + error: string | null; +} + +export function searchStateForApplicationChange(): SearchState { + return { results: [], isLoading: true, error: null }; +} diff --git a/extensions/blume-search/src/searchModel.test.ts b/extensions/blume-search/src/searchModel.test.ts new file mode 100644 index 00000000000..1e5097dc625 --- /dev/null +++ b/extensions/blume-search/src/searchModel.test.ts @@ -0,0 +1,47 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +import type { GlobalSearchResult } from "./protocol.ts"; + +import { ALL_SEARCH_CATEGORIES, blumeDeepLinkForResult, categoriesForFilter, resultSubtitle } from "./searchModel.ts"; + +test("Raycast searches every category through the shared global-search contract", () => { + assert.deepEqual(categoriesForFilter("all"), ALL_SEARCH_CATEGORIES); + assert.deepEqual(categoriesForFilter("messages"), ["messages"]); +}); + +test("search results map to the existing Blume deep-link routes", () => { + const conversation: GlobalSearchResult = { + id: "conversation-1", + category: "conversations", + title: "Search architecture", + subtitle: "Blume", + excerpt: null, + rank: 0, + updatedAt: 1, + conversationRef: "codex/project/thread", + conversationId: "conversation-1", + projectId: "project-1", + workspaceLocationId: null, + harnessId: "codex", + }; + const conversationLink = blumeDeepLinkForResult(conversation); + assert.equal(conversationLink, "blume://agents/codex%2Fproject%2Fthread"); + assert.equal(blumeDeepLinkForResult(conversation, "blume-canary"), "blume-canary://agents/codex%2Fproject%2Fthread"); + + const setup: GlobalSearchResult = { + id: "setup-1", + category: "setup", + title: "Review skill", + subtitle: null, + excerpt: "Review every change", + rank: 0, + updatedAt: 1, + artifactId: "setup-1", + projectId: "project-1", + harnessId: "codex", + sourcePath: "/code/.agents/skills/review/SKILL.md", + }; + assert.equal(blumeDeepLinkForResult(setup), "blume://setup/codex/entries/SKILL.md"); + assert.equal(resultSubtitle(setup), "Review every change"); +}); diff --git a/extensions/blume-search/src/searchModel.ts b/extensions/blume-search/src/searchModel.ts new file mode 100644 index 00000000000..6f4dd10875e --- /dev/null +++ b/extensions/blume-search/src/searchModel.ts @@ -0,0 +1,61 @@ +import { basename } from "node:path"; + +import { GLOBAL_SEARCH_CATEGORIES, type GlobalSearchCategory, type GlobalSearchResult } from "./protocol.ts"; + +export const ALL_SEARCH_CATEGORIES = [...GLOBAL_SEARCH_CATEGORIES]; +export type SearchCategoryFilter = "all" | GlobalSearchCategory; + +export const SEARCH_CATEGORY_LABELS: Record = { + conversations: "Conversations", + messages: "Messages", + projects: "Projects", + setup: "Setup", + suggestions: "Suggestions", +}; + +export const SEARCH_CATEGORY_ICONS: Record = { + conversations: "conversations.svg", + messages: "messages.svg", + projects: "projects.svg", + setup: "setup.svg", + suggestions: "suggestions.svg", +}; + +export function categoriesForFilter(filter: SearchCategoryFilter): GlobalSearchCategory[] { + return filter === "all" ? [...ALL_SEARCH_CATEGORIES] : [filter]; +} + +function segment(value: string): string { + return encodeURIComponent(value); +} + +/** Maps the shared search DTO to routes already owned by the Blume app. */ +export function blumeDeepLinkForResult( + result: GlobalSearchResult, + protocol: "blume" | "blume-canary" = "blume", +): string { + switch (result.category) { + case "conversations": + case "messages": + return `${protocol}://agents/${segment(result.conversationRef)}`; + case "projects": + return `${protocol}://setup/project/${segment(result.projectId)}`; + case "suggestions": + return `${protocol}://suggestions/${segment(result.suggestionId)}`; + case "setup": { + const entryName = result.sourcePath ? basename(result.sourcePath) : null; + if (entryName) { + return `${protocol}://setup/${segment(result.harnessId)}/entries/${segment(entryName)}`; + } + if (result.projectId) return `${protocol}://setup/project/${segment(result.projectId)}`; + return `${protocol}://setup/${segment(result.harnessId)}`; + } + } +} + +export function resultSubtitle(result: GlobalSearchResult): string | undefined { + const parts = [result.subtitle, result.excerpt] + .map((part) => part?.replace(/\s+/g, " ").trim()) + .filter((part): part is string => Boolean(part)); + return parts.length > 0 ? Array.from(new Set(parts)).join(" · ") : undefined; +} diff --git a/extensions/blume-search/tsconfig.json b/extensions/blume-search/tsconfig.json new file mode 100644 index 00000000000..2b3a748c8a5 --- /dev/null +++ b/extensions/blume-search/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ES2022"], + "jsx": "react-jsx", + "strict": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "types": ["node", "react"] + }, + "include": ["src", "raycast-env.d.ts"] +}