diff --git a/.github/workflows/close-stale-prs.yml b/.github/workflows/close-stale-prs.yml new file mode 100644 index 0000000000..787ee02e62 --- /dev/null +++ b/.github/workflows/close-stale-prs.yml @@ -0,0 +1,83 @@ +name: Close stale PRs + +on: + workflow_dispatch: + inputs: + dryRun: + description: "Log actions without closing PRs" + type: boolean + default: false + schedule: + - cron: "0 6 * * *" + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + close-stale-prs: + runs-on: ubuntu-latest + steps: + - name: Close inactive PRs + uses: actions/github-script@v8 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const DAYS_INACTIVE = 60 + const cutoff = new Date(Date.now() - DAYS_INACTIVE * 24 * 60 * 60 * 1000) + const { owner, repo } = context.repo + const dryRun = context.payload.inputs?.dryRun === "true" + const stalePrs = [] + + core.info(`Dry run mode: ${dryRun}`) + + const prs = await github.paginate(github.rest.pulls.list, { + owner, + repo, + state: "open", + per_page: 100, + sort: "updated", + direction: "asc", + }) + + for (const pr of prs) { + const lastUpdated = new Date(pr.updated_at) + if (lastUpdated > cutoff) { + core.info(`PR ${pr.number} is fresh`) + continue + } + + stalePrs.push(pr) + } + + if (!stalePrs.length) { + core.info("No stale pull requests found.") + return + } + + for (const pr of stalePrs) { + const issue_number = pr.number + const closeComment = `Closing this pull request because it has had no updates for more than ${DAYS_INACTIVE} days. If you plan to continue working on it, feel free to reopen or open a new PR.` + + if (dryRun) { + core.info(`[dry-run] Would close PR #${issue_number} from ${pr.user.login}`) + continue + } + + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body: closeComment, + }) + + await github.rest.pulls.update({ + owner, + repo, + pull_number: issue_number, + state: "closed", + }) + + core.info(`Closed PR #${issue_number} from ${pr.user.login}`) + } diff --git a/.opencode/command/ai-deps.md b/.opencode/command/ai-deps.md index 4d23c76a4d..83783d5b9b 100644 --- a/.opencode/command/ai-deps.md +++ b/.opencode/command/ai-deps.md @@ -7,7 +7,7 @@ Please read @package.json and @packages/opencode/package.json. Your job is to look into AI SDK dependencies, figure out if they have versions that can be upgraded (minor or patch versions ONLY no major ignore major changes). I want a report of every dependency and the version that can be upgraded to. -What would be even better is if you can give me links to the changelog for each dependency, or at least some reference info so I can see what bugs were fixed or new features were added. +What would be even better is if you can give me brief summary of the changes for each dep and a link to the changelog for each dependency, or at least some reference info so I can see what bugs were fixed or new features were added. Consider using subagents for each dep to save your context window. diff --git a/.opencode/command/learn.md b/.opencode/command/learn.md new file mode 100644 index 0000000000..fe4965a588 --- /dev/null +++ b/.opencode/command/learn.md @@ -0,0 +1,42 @@ +--- +description: Extract non-obvious learnings from session to AGENTS.md files to build codebase understanding +--- + +Analyze this session and extract non-obvious learnings to add to AGENTS.md files. + +AGENTS.md files can exist at any directory level, not just the project root. When an agent reads a file, any AGENTS.md in parent directories are automatically loaded into the context of the tool read. Place learnings as close to the relevant code as possible: + +- Project-wide learnings → root AGENTS.md +- Package/module-specific → packages/foo/AGENTS.md +- Feature-specific → src/auth/AGENTS.md + +What counts as a learning (non-obvious discoveries only): + +- Hidden relationships between files or modules +- Execution paths that differ from how code appears +- Non-obvious configuration, env vars, or flags +- Debugging breakthroughs when error messages were misleading +- API/tool quirks and workarounds +- Build/test commands not in README +- Architectural decisions and constraints +- Files that must change together + +What NOT to include: + +- Obvious facts from documentation +- Standard language/framework behavior +- Things already in an AGENTS.md +- Verbose explanations +- Session-specific details + +Process: + +1. Review session for discoveries, errors that took multiple attempts, unexpected connections +2. Determine scope - what directory does each learning apply to? +3. Read existing AGENTS.md files at relevant levels +4. Create or update AGENTS.md at the appropriate level +5. Keep entries to 1-3 lines per insight + +After updating, summarize which AGENTS.md files were created/updated and how many learnings per file. + +$ARGUMENTS diff --git a/AGENTS.md b/AGENTS.md index 36a9181bbc..483d99f11d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,6 +14,7 @@ Kilo CLI is an open source AI coding agent that generates code from natural lang - Avoid using the `any` type - Prefer single word variable names where possible - Use Bun APIs when possible, like `Bun.file()` +- Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity ### Avoid let statements diff --git a/STATS.md b/STATS.md deleted file mode 100644 index a8be315651..0000000000 --- a/STATS.md +++ /dev/null @@ -1,213 +0,0 @@ -# Download Stats - -| Date | GitHub Downloads | npm Downloads | Total | -| ---------- | -------------------- | -------------------- | -------------------- | -| 2025-06-29 | 18,789 (+0) | 39,420 (+0) | 58,209 (+0) | -| 2025-06-30 | 20,127 (+1,338) | 41,059 (+1,639) | 61,186 (+2,977) | -| 2025-07-01 | 22,108 (+1,981) | 43,745 (+2,686) | 65,853 (+4,667) | -| 2025-07-02 | 24,814 (+2,706) | 46,168 (+2,423) | 70,982 (+5,129) | -| 2025-07-03 | 27,834 (+3,020) | 49,955 (+3,787) | 77,789 (+6,807) | -| 2025-07-04 | 30,608 (+2,774) | 54,758 (+4,803) | 85,366 (+7,577) | -| 2025-07-05 | 32,524 (+1,916) | 58,371 (+3,613) | 90,895 (+5,529) | -| 2025-07-06 | 33,766 (+1,242) | 59,694 (+1,323) | 93,460 (+2,565) | -| 2025-07-08 | 38,052 (+4,286) | 64,468 (+4,774) | 102,520 (+9,060) | -| 2025-07-09 | 40,924 (+2,872) | 67,935 (+3,467) | 108,859 (+6,339) | -| 2025-07-10 | 43,796 (+2,872) | 71,402 (+3,467) | 115,198 (+6,339) | -| 2025-07-11 | 46,982 (+3,186) | 77,462 (+6,060) | 124,444 (+9,246) | -| 2025-07-12 | 49,302 (+2,320) | 82,177 (+4,715) | 131,479 (+7,035) | -| 2025-07-13 | 50,803 (+1,501) | 86,394 (+4,217) | 137,197 (+5,718) | -| 2025-07-14 | 53,283 (+2,480) | 87,860 (+1,466) | 141,143 (+3,946) | -| 2025-07-15 | 57,590 (+4,307) | 91,036 (+3,176) | 148,626 (+7,483) | -| 2025-07-16 | 62,313 (+4,723) | 95,258 (+4,222) | 157,571 (+8,945) | -| 2025-07-17 | 66,684 (+4,371) | 100,048 (+4,790) | 166,732 (+9,161) | -| 2025-07-18 | 70,379 (+3,695) | 102,587 (+2,539) | 172,966 (+6,234) | -| 2025-07-19 | 73,497 (+3,117) | 105,904 (+3,317) | 179,401 (+6,434) | -| 2025-07-20 | 76,453 (+2,956) | 109,044 (+3,140) | 185,497 (+6,096) | -| 2025-07-21 | 80,197 (+3,744) | 113,537 (+4,493) | 193,734 (+8,237) | -| 2025-07-22 | 84,251 (+4,054) | 118,073 (+4,536) | 202,324 (+8,590) | -| 2025-07-23 | 88,589 (+4,338) | 121,436 (+3,363) | 210,025 (+7,701) | -| 2025-07-24 | 92,469 (+3,880) | 124,091 (+2,655) | 216,560 (+6,535) | -| 2025-07-25 | 96,417 (+3,948) | 126,985 (+2,894) | 223,402 (+6,842) | -| 2025-07-26 | 100,646 (+4,229) | 131,411 (+4,426) | 232,057 (+8,655) | -| 2025-07-27 | 102,644 (+1,998) | 134,736 (+3,325) | 237,380 (+5,323) | -| 2025-07-28 | 105,446 (+2,802) | 136,016 (+1,280) | 241,462 (+4,082) | -| 2025-07-29 | 108,998 (+3,552) | 137,542 (+1,526) | 246,540 (+5,078) | -| 2025-07-30 | 113,544 (+4,546) | 140,317 (+2,775) | 253,861 (+7,321) | -| 2025-07-31 | 118,339 (+4,795) | 143,344 (+3,027) | 261,683 (+7,822) | -| 2025-08-01 | 123,539 (+5,200) | 146,680 (+3,336) | 270,219 (+8,536) | -| 2025-08-02 | 127,864 (+4,325) | 149,236 (+2,556) | 277,100 (+6,881) | -| 2025-08-03 | 131,397 (+3,533) | 150,451 (+1,215) | 281,848 (+4,748) | -| 2025-08-04 | 136,266 (+4,869) | 153,260 (+2,809) | 289,526 (+7,678) | -| 2025-08-05 | 141,596 (+5,330) | 155,752 (+2,492) | 297,348 (+7,822) | -| 2025-08-06 | 147,067 (+5,471) | 158,309 (+2,557) | 305,376 (+8,028) | -| 2025-08-07 | 152,591 (+5,524) | 160,889 (+2,580) | 313,480 (+8,104) | -| 2025-08-08 | 158,187 (+5,596) | 163,448 (+2,559) | 321,635 (+8,155) | -| 2025-08-09 | 162,770 (+4,583) | 165,721 (+2,273) | 328,491 (+6,856) | -| 2025-08-10 | 165,695 (+2,925) | 167,109 (+1,388) | 332,804 (+4,313) | -| 2025-08-11 | 169,297 (+3,602) | 167,953 (+844) | 337,250 (+4,446) | -| 2025-08-12 | 176,307 (+7,010) | 171,876 (+3,923) | 348,183 (+10,933) | -| 2025-08-13 | 182,997 (+6,690) | 177,182 (+5,306) | 360,179 (+11,996) | -| 2025-08-14 | 189,063 (+6,066) | 179,741 (+2,559) | 368,804 (+8,625) | -| 2025-08-15 | 193,608 (+4,545) | 181,792 (+2,051) | 375,400 (+6,596) | -| 2025-08-16 | 198,118 (+4,510) | 184,558 (+2,766) | 382,676 (+7,276) | -| 2025-08-17 | 201,299 (+3,181) | 186,269 (+1,711) | 387,568 (+4,892) | -| 2025-08-18 | 204,559 (+3,260) | 187,399 (+1,130) | 391,958 (+4,390) | -| 2025-08-19 | 209,814 (+5,255) | 189,668 (+2,269) | 399,482 (+7,524) | -| 2025-08-20 | 214,497 (+4,683) | 191,481 (+1,813) | 405,978 (+6,496) | -| 2025-08-21 | 220,465 (+5,968) | 194,784 (+3,303) | 415,249 (+9,271) | -| 2025-08-22 | 225,899 (+5,434) | 197,204 (+2,420) | 423,103 (+7,854) | -| 2025-08-23 | 229,005 (+3,106) | 199,238 (+2,034) | 428,243 (+5,140) | -| 2025-08-24 | 232,098 (+3,093) | 201,157 (+1,919) | 433,255 (+5,012) | -| 2025-08-25 | 236,607 (+4,509) | 202,650 (+1,493) | 439,257 (+6,002) | -| 2025-08-26 | 242,783 (+6,176) | 205,242 (+2,592) | 448,025 (+8,768) | -| 2025-08-27 | 248,409 (+5,626) | 205,242 (+0) | 453,651 (+5,626) | -| 2025-08-28 | 252,796 (+4,387) | 205,242 (+0) | 458,038 (+4,387) | -| 2025-08-29 | 256,045 (+3,249) | 211,075 (+5,833) | 467,120 (+9,082) | -| 2025-08-30 | 258,863 (+2,818) | 212,397 (+1,322) | 471,260 (+4,140) | -| 2025-08-31 | 262,004 (+3,141) | 213,944 (+1,547) | 475,948 (+4,688) | -| 2025-09-01 | 265,359 (+3,355) | 215,115 (+1,171) | 480,474 (+4,526) | -| 2025-09-02 | 270,483 (+5,124) | 217,075 (+1,960) | 487,558 (+7,084) | -| 2025-09-03 | 274,793 (+4,310) | 219,755 (+2,680) | 494,548 (+6,990) | -| 2025-09-04 | 280,430 (+5,637) | 222,103 (+2,348) | 502,533 (+7,985) | -| 2025-09-05 | 283,769 (+3,339) | 223,793 (+1,690) | 507,562 (+5,029) | -| 2025-09-06 | 286,245 (+2,476) | 225,036 (+1,243) | 511,281 (+3,719) | -| 2025-09-07 | 288,623 (+2,378) | 225,866 (+830) | 514,489 (+3,208) | -| 2025-09-08 | 293,341 (+4,718) | 227,073 (+1,207) | 520,414 (+5,925) | -| 2025-09-09 | 300,036 (+6,695) | 229,788 (+2,715) | 529,824 (+9,410) | -| 2025-09-10 | 307,287 (+7,251) | 233,435 (+3,647) | 540,722 (+10,898) | -| 2025-09-11 | 314,083 (+6,796) | 237,356 (+3,921) | 551,439 (+10,717) | -| 2025-09-12 | 321,046 (+6,963) | 240,728 (+3,372) | 561,774 (+10,335) | -| 2025-09-13 | 324,894 (+3,848) | 245,539 (+4,811) | 570,433 (+8,659) | -| 2025-09-14 | 328,876 (+3,982) | 248,245 (+2,706) | 577,121 (+6,688) | -| 2025-09-15 | 334,201 (+5,325) | 250,983 (+2,738) | 585,184 (+8,063) | -| 2025-09-16 | 342,609 (+8,408) | 255,264 (+4,281) | 597,873 (+12,689) | -| 2025-09-17 | 351,117 (+8,508) | 260,970 (+5,706) | 612,087 (+14,214) | -| 2025-09-18 | 358,717 (+7,600) | 266,922 (+5,952) | 625,639 (+13,552) | -| 2025-09-19 | 365,401 (+6,684) | 271,859 (+4,937) | 637,260 (+11,621) | -| 2025-09-20 | 372,092 (+6,691) | 276,917 (+5,058) | 649,009 (+11,749) | -| 2025-09-21 | 377,079 (+4,987) | 280,261 (+3,344) | 657,340 (+8,331) | -| 2025-09-22 | 382,492 (+5,413) | 284,009 (+3,748) | 666,501 (+9,161) | -| 2025-09-23 | 387,008 (+4,516) | 289,129 (+5,120) | 676,137 (+9,636) | -| 2025-09-24 | 393,325 (+6,317) | 294,927 (+5,798) | 688,252 (+12,115) | -| 2025-09-25 | 398,879 (+5,554) | 301,663 (+6,736) | 700,542 (+12,290) | -| 2025-09-26 | 404,334 (+5,455) | 306,713 (+5,050) | 711,047 (+10,505) | -| 2025-09-27 | 411,618 (+7,284) | 317,763 (+11,050) | 729,381 (+18,334) | -| 2025-09-28 | 414,910 (+3,292) | 322,522 (+4,759) | 737,432 (+8,051) | -| 2025-09-29 | 419,919 (+5,009) | 328,033 (+5,511) | 747,952 (+10,520) | -| 2025-09-30 | 427,991 (+8,072) | 336,472 (+8,439) | 764,463 (+16,511) | -| 2025-10-01 | 433,591 (+5,600) | 341,742 (+5,270) | 775,333 (+10,870) | -| 2025-10-02 | 440,852 (+7,261) | 348,099 (+6,357) | 788,951 (+13,618) | -| 2025-10-03 | 446,829 (+5,977) | 359,937 (+11,838) | 806,766 (+17,815) | -| 2025-10-04 | 452,561 (+5,732) | 370,386 (+10,449) | 822,947 (+16,181) | -| 2025-10-05 | 455,559 (+2,998) | 374,745 (+4,359) | 830,304 (+7,357) | -| 2025-10-06 | 460,927 (+5,368) | 379,489 (+4,744) | 840,416 (+10,112) | -| 2025-10-07 | 467,336 (+6,409) | 385,438 (+5,949) | 852,774 (+12,358) | -| 2025-10-08 | 474,643 (+7,307) | 394,139 (+8,701) | 868,782 (+16,008) | -| 2025-10-09 | 479,203 (+4,560) | 400,526 (+6,387) | 879,729 (+10,947) | -| 2025-10-10 | 484,374 (+5,171) | 406,015 (+5,489) | 890,389 (+10,660) | -| 2025-10-11 | 488,427 (+4,053) | 414,699 (+8,684) | 903,126 (+12,737) | -| 2025-10-12 | 492,125 (+3,698) | 418,745 (+4,046) | 910,870 (+7,744) | -| 2025-10-14 | 505,130 (+13,005) | 429,286 (+10,541) | 934,416 (+23,546) | -| 2025-10-15 | 512,717 (+7,587) | 439,290 (+10,004) | 952,007 (+17,591) | -| 2025-10-16 | 517,719 (+5,002) | 447,137 (+7,847) | 964,856 (+12,849) | -| 2025-10-17 | 526,239 (+8,520) | 457,467 (+10,330) | 983,706 (+18,850) | -| 2025-10-18 | 531,564 (+5,325) | 465,272 (+7,805) | 996,836 (+13,130) | -| 2025-10-19 | 536,209 (+4,645) | 469,078 (+3,806) | 1,005,287 (+8,451) | -| 2025-10-20 | 541,264 (+5,055) | 472,952 (+3,874) | 1,014,216 (+8,929) | -| 2025-10-21 | 548,721 (+7,457) | 479,703 (+6,751) | 1,028,424 (+14,208) | -| 2025-10-22 | 557,949 (+9,228) | 491,395 (+11,692) | 1,049,344 (+20,920) | -| 2025-10-23 | 564,716 (+6,767) | 498,736 (+7,341) | 1,063,452 (+14,108) | -| 2025-10-24 | 572,692 (+7,976) | 506,905 (+8,169) | 1,079,597 (+16,145) | -| 2025-10-25 | 578,927 (+6,235) | 516,129 (+9,224) | 1,095,056 (+15,459) | -| 2025-10-26 | 584,409 (+5,482) | 521,179 (+5,050) | 1,105,588 (+10,532) | -| 2025-10-27 | 589,999 (+5,590) | 526,001 (+4,822) | 1,116,000 (+10,412) | -| 2025-10-28 | 595,776 (+5,777) | 532,438 (+6,437) | 1,128,214 (+12,214) | -| 2025-10-29 | 606,259 (+10,483) | 542,064 (+9,626) | 1,148,323 (+20,109) | -| 2025-10-30 | 613,746 (+7,487) | 542,064 (+0) | 1,155,810 (+7,487) | -| 2025-10-30 | 617,846 (+4,100) | 555,026 (+12,962) | 1,172,872 (+17,062) | -| 2025-10-31 | 626,612 (+8,766) | 564,579 (+9,553) | 1,191,191 (+18,319) | -| 2025-11-01 | 636,100 (+9,488) | 581,806 (+17,227) | 1,217,906 (+26,715) | -| 2025-11-02 | 644,067 (+7,967) | 590,004 (+8,198) | 1,234,071 (+16,165) | -| 2025-11-03 | 653,130 (+9,063) | 597,139 (+7,135) | 1,250,269 (+16,198) | -| 2025-11-04 | 663,912 (+10,782) | 608,056 (+10,917) | 1,271,968 (+21,699) | -| 2025-11-05 | 675,074 (+11,162) | 619,690 (+11,634) | 1,294,764 (+22,796) | -| 2025-11-06 | 686,252 (+11,178) | 630,885 (+11,195) | 1,317,137 (+22,373) | -| 2025-11-07 | 696,646 (+10,394) | 642,146 (+11,261) | 1,338,792 (+21,655) | -| 2025-11-08 | 706,035 (+9,389) | 653,489 (+11,343) | 1,359,524 (+20,732) | -| 2025-11-09 | 713,462 (+7,427) | 660,459 (+6,970) | 1,373,921 (+14,397) | -| 2025-11-10 | 722,288 (+8,826) | 668,225 (+7,766) | 1,390,513 (+16,592) | -| 2025-11-11 | 729,769 (+7,481) | 677,501 (+9,276) | 1,407,270 (+16,757) | -| 2025-11-12 | 740,180 (+10,411) | 686,454 (+8,953) | 1,426,634 (+19,364) | -| 2025-11-13 | 749,905 (+9,725) | 696,157 (+9,703) | 1,446,062 (+19,428) | -| 2025-11-14 | 759,928 (+10,023) | 705,237 (+9,080) | 1,465,165 (+19,103) | -| 2025-11-15 | 765,955 (+6,027) | 712,870 (+7,633) | 1,478,825 (+13,660) | -| 2025-11-16 | 771,069 (+5,114) | 716,596 (+3,726) | 1,487,665 (+8,840) | -| 2025-11-17 | 780,161 (+9,092) | 723,339 (+6,743) | 1,503,500 (+15,835) | -| 2025-11-18 | 791,563 (+11,402) | 732,544 (+9,205) | 1,524,107 (+20,607) | -| 2025-11-19 | 804,409 (+12,846) | 747,624 (+15,080) | 1,552,033 (+27,926) | -| 2025-11-20 | 814,620 (+10,211) | 757,907 (+10,283) | 1,572,527 (+20,494) | -| 2025-11-21 | 826,309 (+11,689) | 769,307 (+11,400) | 1,595,616 (+23,089) | -| 2025-11-22 | 837,269 (+10,960) | 780,996 (+11,689) | 1,618,265 (+22,649) | -| 2025-11-23 | 846,609 (+9,340) | 795,069 (+14,073) | 1,641,678 (+23,413) | -| 2025-11-24 | 856,733 (+10,124) | 804,033 (+8,964) | 1,660,766 (+19,088) | -| 2025-11-25 | 869,423 (+12,690) | 817,339 (+13,306) | 1,686,762 (+25,996) | -| 2025-11-26 | 881,414 (+11,991) | 832,518 (+15,179) | 1,713,932 (+27,170) | -| 2025-11-27 | 893,960 (+12,546) | 846,180 (+13,662) | 1,740,140 (+26,208) | -| 2025-11-28 | 901,741 (+7,781) | 856,482 (+10,302) | 1,758,223 (+18,083) | -| 2025-11-29 | 908,689 (+6,948) | 863,361 (+6,879) | 1,772,050 (+13,827) | -| 2025-11-30 | 916,116 (+7,427) | 870,194 (+6,833) | 1,786,310 (+14,260) | -| 2025-12-01 | 925,898 (+9,782) | 876,500 (+6,306) | 1,802,398 (+16,088) | -| 2025-12-02 | 939,250 (+13,352) | 890,919 (+14,419) | 1,830,169 (+27,771) | -| 2025-12-03 | 952,249 (+12,999) | 903,713 (+12,794) | 1,855,962 (+25,793) | -| 2025-12-04 | 965,611 (+13,362) | 916,471 (+12,758) | 1,882,082 (+26,120) | -| 2025-12-05 | 977,996 (+12,385) | 930,616 (+14,145) | 1,908,612 (+26,530) | -| 2025-12-06 | 987,884 (+9,888) | 943,773 (+13,157) | 1,931,657 (+23,045) | -| 2025-12-07 | 994,046 (+6,162) | 951,425 (+7,652) | 1,945,471 (+13,814) | -| 2025-12-08 | 1,000,898 (+6,852) | 957,149 (+5,724) | 1,958,047 (+12,576) | -| 2025-12-09 | 1,011,488 (+10,590) | 973,922 (+16,773) | 1,985,410 (+27,363) | -| 2025-12-10 | 1,025,891 (+14,403) | 991,708 (+17,786) | 2,017,599 (+32,189) | -| 2025-12-11 | 1,045,110 (+19,219) | 1,010,559 (+18,851) | 2,055,669 (+38,070) | -| 2025-12-12 | 1,061,340 (+16,230) | 1,030,838 (+20,279) | 2,092,178 (+36,509) | -| 2025-12-13 | 1,073,561 (+12,221) | 1,044,608 (+13,770) | 2,118,169 (+25,991) | -| 2025-12-14 | 1,082,042 (+8,481) | 1,052,425 (+7,817) | 2,134,467 (+16,298) | -| 2025-12-15 | 1,093,632 (+11,590) | 1,059,078 (+6,653) | 2,152,710 (+18,243) | -| 2025-12-16 | 1,120,477 (+26,845) | 1,078,022 (+18,944) | 2,198,499 (+45,789) | -| 2025-12-17 | 1,151,067 (+30,590) | 1,097,661 (+19,639) | 2,248,728 (+50,229) | -| 2025-12-18 | 1,178,658 (+27,591) | 1,113,418 (+15,757) | 2,292,076 (+43,348) | -| 2025-12-19 | 1,203,485 (+24,827) | 1,129,698 (+16,280) | 2,333,183 (+41,107) | -| 2025-12-20 | 1,223,000 (+19,515) | 1,146,258 (+16,560) | 2,369,258 (+36,075) | -| 2025-12-21 | 1,242,675 (+19,675) | 1,158,909 (+12,651) | 2,401,584 (+32,326) | -| 2025-12-22 | 1,262,522 (+19,847) | 1,169,121 (+10,212) | 2,431,643 (+30,059) | -| 2025-12-23 | 1,286,548 (+24,026) | 1,186,439 (+17,318) | 2,472,987 (+41,344) | -| 2025-12-24 | 1,309,323 (+22,775) | 1,203,767 (+17,328) | 2,513,090 (+40,103) | -| 2025-12-25 | 1,333,032 (+23,709) | 1,217,283 (+13,516) | 2,550,315 (+37,225) | -| 2025-12-26 | 1,352,411 (+19,379) | 1,227,615 (+10,332) | 2,580,026 (+29,711) | -| 2025-12-27 | 1,371,771 (+19,360) | 1,238,236 (+10,621) | 2,610,007 (+29,981) | -| 2025-12-28 | 1,390,388 (+18,617) | 1,245,690 (+7,454) | 2,636,078 (+26,071) | -| 2025-12-29 | 1,415,560 (+25,172) | 1,257,101 (+11,411) | 2,672,661 (+36,583) | -| 2025-12-30 | 1,445,450 (+29,890) | 1,272,689 (+15,588) | 2,718,139 (+45,478) | -| 2025-12-31 | 1,479,598 (+34,148) | 1,293,235 (+20,546) | 2,772,833 (+54,694) | -| 2026-01-01 | 1,508,883 (+29,285) | 1,309,874 (+16,639) | 2,818,757 (+45,924) | -| 2026-01-02 | 1,563,474 (+54,591) | 1,320,959 (+11,085) | 2,884,433 (+65,676) | -| 2026-01-03 | 1,618,065 (+54,591) | 1,331,914 (+10,955) | 2,949,979 (+65,546) | -| 2026-01-04 | 1,672,656 (+39,702) | 1,339,883 (+7,969) | 3,012,539 (+62,560) | -| 2026-01-05 | 1,738,171 (+65,515) | 1,353,043 (+13,160) | 3,091,214 (+78,675) | -| 2026-01-06 | 1,960,988 (+222,817) | 1,377,377 (+24,334) | 3,338,365 (+247,151) | -| 2026-01-07 | 2,123,239 (+162,251) | 1,398,648 (+21,271) | 3,521,887 (+183,522) | -| 2026-01-08 | 2,272,630 (+149,391) | 1,432,480 (+33,832) | 3,705,110 (+183,223) | -| 2026-01-09 | 2,443,565 (+170,935) | 1,469,451 (+36,971) | 3,913,016 (+207,906) | -| 2026-01-10 | 2,632,023 (+188,458) | 1,503,670 (+34,219) | 4,135,693 (+222,677) | -| 2026-01-11 | 2,836,394 (+204,371) | 1,530,479 (+26,809) | 4,366,873 (+231,180) | -| 2026-01-12 | 3,053,594 (+217,200) | 1,553,671 (+23,192) | 4,607,265 (+240,392) | -| 2026-01-13 | 3,297,078 (+243,484) | 1,595,062 (+41,391) | 4,892,140 (+284,875) | -| 2026-01-14 | 3,568,928 (+271,850) | 1,645,362 (+50,300) | 5,214,290 (+322,150) | -| 2026-01-16 | 4,121,550 (+552,622) | 1,754,418 (+109,056) | 5,875,968 (+661,678) | -| 2026-01-17 | 4,389,558 (+268,008) | 1,805,315 (+50,897) | 6,194,873 (+318,905) | -| 2026-01-18 | 4,627,623 (+238,065) | 1,839,171 (+33,856) | 6,466,794 (+271,921) | -| 2026-01-19 | 4,861,108 (+233,485) | 1,863,112 (+23,941) | 6,724,220 (+257,426) | -| 2026-01-20 | 5,128,999 (+267,891) | 1,903,665 (+40,553) | 7,032,664 (+308,444) | -| 2026-01-21 | 5,444,842 (+315,843) | 1,962,531 (+58,866) | 7,407,373 (+374,709) | -| 2026-01-22 | 5,766,340 (+321,498) | 2,029,487 (+66,956) | 7,795,827 (+388,454) | -| 2026-01-23 | 6,096,236 (+329,896) | 2,096,235 (+66,748) | 8,192,471 (+396,644) | -| 2026-01-24 | 6,371,019 (+274,783) | 2,156,870 (+60,635) | 8,527,889 (+335,418) | -| 2026-01-25 | 6,639,082 (+268,063) | 2,187,853 (+30,983) | 8,826,935 (+299,046) | diff --git a/bun.lock b/bun.lock index 58ff5a5511..453b22de0f 100644 --- a/bun.lock +++ b/bun.lock @@ -3,7 +3,7 @@ "configVersion": 1, "workspaces": { "": { - "name": "opencode", + "name": "@kilocode/cli", "dependencies": { "@aws-sdk/client-s3": "3.933.0", "@kilocode/plugin": "workspace:*", @@ -24,7 +24,7 @@ }, "packages/app": { "name": "@opencode-ai/app", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -74,7 +74,7 @@ }, "packages/console/app": { "name": "@opencode-ai/console-app", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@cloudflare/vite-plugin": "1.15.2", "@ibm/plex": "6.4.1", @@ -108,7 +108,7 @@ }, "packages/console/core": { "name": "@opencode-ai/console-core", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@aws-sdk/client-sts": "3.782.0", "@jsx-email/render": "1.1.1", @@ -135,7 +135,7 @@ }, "packages/console/function": { "name": "@opencode-ai/console-function", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@ai-sdk/anthropic": "2.0.0", "@ai-sdk/openai": "2.0.2", @@ -159,7 +159,7 @@ }, "packages/console/mail": { "name": "@opencode-ai/console-mail", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", @@ -183,10 +183,11 @@ }, "packages/desktop": { "name": "@opencode-ai/desktop", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@opencode-ai/app": "workspace:*", "@opencode-ai/ui": "workspace:*", + "@solid-primitives/i18n": "2.2.1", "@solid-primitives/storage": "catalog:", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", @@ -212,7 +213,7 @@ }, "packages/enterprise": { "name": "@opencode-ai/enterprise", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@opencode-ai/ui": "workspace:*", "@opencode-ai/util": "workspace:*", @@ -241,7 +242,7 @@ }, "packages/function": { "name": "@opencode-ai/function", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@octokit/auth-app": "8.0.1", "@octokit/rest": "catalog:", @@ -268,8 +269,8 @@ "zod": "catalog:", }, "devDependencies": { - "@opentui/core": "0.1.74", - "@opentui/solid": "0.1.74", + "@opentui/core": "0.1.75", + "@opentui/solid": "0.1.75", "@tsconfig/node22": "catalog:", "@types/node": "catalog:", "@typescript/native-preview": "catalog:", @@ -309,7 +310,7 @@ }, "packages/opencode": { "name": "@kilocode/cli", - "version": "1.1.36", + "version": "1.1.42", "bin": { "kilo": "./bin/kilo", }, @@ -351,8 +352,8 @@ "@opencode-ai/script": "workspace:*", "@opencode-ai/util": "workspace:*", "@openrouter/ai-sdk-provider": "1.5.2", - "@opentui/core": "0.1.74", - "@opentui/solid": "0.1.74", + "@opentui/core": "0.1.75", + "@opentui/solid": "0.1.75", "@parcel/watcher": "2.5.1", "@pierre/diffs": "catalog:", "@solid-primitives/event-bus": "1.1.2", @@ -415,7 +416,7 @@ }, "packages/plugin": { "name": "@kilocode/plugin", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@kilocode/sdk": "workspace:*", "zod": "catalog:", @@ -435,7 +436,7 @@ }, "packages/sdk/js": { "name": "@kilocode/sdk", - "version": "1.1.36", + "version": "1.1.42", "devDependencies": { "@hey-api/openapi-ts": "0.90.10", "@tsconfig/node22": "catalog:", @@ -446,7 +447,7 @@ }, "packages/slack": { "name": "@opencode-ai/slack", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@kilocode/sdk": "workspace:*", "@slack/bolt": "^3.17.1", @@ -459,7 +460,7 @@ }, "packages/ui": { "name": "@opencode-ai/ui", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@kilocode/sdk": "workspace:*", "@kobalte/core": "catalog:", @@ -501,7 +502,7 @@ }, "packages/util": { "name": "@opencode-ai/util", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "zod": "catalog:", }, @@ -512,7 +513,7 @@ }, "packages/web": { "name": "@opencode-ai/web", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@astrojs/cloudflare": "12.6.3", "@astrojs/markdown-remark": "6.3.1", @@ -604,7 +605,7 @@ "@actions/github": ["@actions/github@6.0.1", "", { "dependencies": { "@actions/http-client": "^2.2.0", "@octokit/core": "^5.0.1", "@octokit/plugin-paginate-rest": "^9.2.2", "@octokit/plugin-rest-endpoint-methods": "^10.4.0", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "undici": "^5.28.5" } }, "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw=="], - "@actions/http-client": ["@actions/http-client@3.0.0", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.28.5" } }, "sha512-1s3tXAfVMSz9a4ZEBkXXRQD4QhY3+GAsWSbaYpeknPOKEeyRiU3lH+bHiLMZdo2x/fIeQ/hscL1wCkDLVM2DZQ=="], + "@actions/http-client": ["@actions/http-client@3.0.2", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^6.23.0" } }, "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA=="], "@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="], @@ -666,11 +667,11 @@ "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="], - "@astrojs/mdx": ["@astrojs/mdx@4.3.12", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.9", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-pL3CVPtuQrPnDhWjy7zqbOibNyPaxP4VpQS8T8spwKqKzauJ4yoKyNkVTD8jrP7EAJHmBhZ7PTmUGZqOpKKp8g=="], + "@astrojs/mdx": ["@astrojs/mdx@4.3.13", "", { "dependencies": { "@astrojs/markdown-remark": "6.3.10", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.15.0", "es-module-lexer": "^1.7.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.0.0", "vfile": "^6.0.3" }, "peerDependencies": { "astro": "^5.0.0" } }, "sha512-IHDHVKz0JfKBy3//52JSiyWv089b7GVSChIXLrlUOoTLWowG3wr2/8hkaEgEyd/vysvNQvGk+QhysXpJW5ve6Q=="], "@astrojs/prism": ["@astrojs/prism@3.2.0", "", { "dependencies": { "prismjs": "^1.29.0" } }, "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw=="], - "@astrojs/sitemap": ["@astrojs/sitemap@3.6.0", "", { "dependencies": { "sitemap": "^8.0.0", "stream-replace-string": "^2.0.0", "zod": "^3.25.76" } }, "sha512-4aHkvcOZBWJigRmMIAJwRQXBS+ayoP5z40OklTXYXhUDhwusz+DyDl+nSshY6y9DvkVEavwNcFO8FD81iGhXjg=="], + "@astrojs/sitemap": ["@astrojs/sitemap@3.7.0", "", { "dependencies": { "sitemap": "^8.0.2", "stream-replace-string": "^2.0.0", "zod": "^3.25.76" } }, "sha512-+qxjUrz6Jcgh+D5VE1gKUJTA3pSthuPHe6Ao5JCxok794Lewx8hBFaWHtOnN0ntb2lfOf7gvOi9TefUswQ/ZVA=="], "@astrojs/solid-js": ["@astrojs/solid-js@5.1.0", "", { "dependencies": { "vite": "^6.3.5", "vite-plugin-solid": "^2.11.6" }, "peerDependencies": { "solid-devtools": "^0.30.1", "solid-js": "^1.8.5" }, "optionalPeers": ["solid-devtools"] }, "sha512-VmPHOU9k7m6HHCT2Y1mNzifilUnttlowBM36frGcfj5wERJE9Ci0QtWJbzdf6AlcoIirb7xVw+ByupU011Di9w=="], @@ -750,7 +751,7 @@ "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.930.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" } }, "sha512-M2oEKBzzNAYr136RRc6uqw3aWlwCxqTP1Lawps9E1d2abRPvl1p1ztQmmXp1Ak4rv8eByIZ+yQyKQ3zPdRG5dw=="], - "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.893.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg=="], + "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.4", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog=="], "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.930.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@smithy/types": "^4.9.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-q6lCRm6UAe+e1LguM5E4EqM9brQlDem4XDcQ87NzEvlTW6GzmNCO0w1jS0XgCFXQHjDxjdlNFX+5sRbHijwklg=="], @@ -758,7 +759,7 @@ "@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.930.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA=="], - "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.1", "", {}, "sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww=="], + "@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.3", "", {}, "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw=="], "@azure/abort-controller": ["@azure/abort-controller@2.1.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA=="], @@ -784,37 +785,37 @@ "@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="], - "@azure/storage-blob": ["@azure/storage-blob@12.29.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.1.1", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-7ktyY0rfTM0vo7HvtK6E3UvYnI9qfd6Oz6z/+92VhGRveWng3kJwMKeUpqmW/NmwcDNbxHpSlldG+vsUnRFnBg=="], + "@azure/storage-blob": ["@azure/storage-blob@12.30.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.2.0", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-peDCR8blSqhsAKDbpSP/o55S4sheNwSrblvCaHUZ5xUI73XA7ieUGGwrONgD/Fng0EoDe1VOa3fAQ7+WGB3Ocg=="], - "@azure/storage-common": ["@azure/storage-common@12.1.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-eIOH1pqFwI6UmVNnDQvmFeSg0XppuzDLFeUNO/Xht7ODAzRLgGDh7h550pSxoA+lPDxBl1+D2m/KG3jWzCUjTg=="], + "@azure/storage-common": ["@azure/storage-common@12.2.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-YZLxiJ3vBAAnFbG3TFuAMUlxZRexjQX5JDQxOkFGb6e2TpoxH3xyHI6idsMe/QrWtj41U/KoqBxlayzhS+LlwA=="], - "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + "@babel/code-frame": ["@babel/code-frame@7.28.6", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q=="], - "@babel/compat-data": ["@babel/compat-data@7.28.5", "", {}, "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA=="], + "@babel/compat-data": ["@babel/compat-data@7.28.6", "", {}, "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg=="], "@babel/core": ["@babel/core@7.28.4", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.4", "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.4", "@babel/types": "^7.28.4", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA=="], - "@babel/generator": ["@babel/generator@7.28.5", "", { "dependencies": { "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ=="], + "@babel/generator": ["@babel/generator@7.28.6", "", { "dependencies": { "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw=="], "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="], + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], - "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ=="], + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="], "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="], - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="], + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], - "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.27.1", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.27.1", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA=="], + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="], "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], @@ -824,35 +825,35 @@ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], - "@babel/helpers": ["@babel/helpers@7.28.4", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.4" } }, "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w=="], + "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], - "@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], + "@babel/parser": ["@babel/parser@7.28.6", "", { "dependencies": { "@babel/types": "^7.28.6" }, "bin": "./bin/babel-parser.js" }, "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ=="], - "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w=="], + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="], - "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ=="], + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="], - "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.27.1", "", { "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw=="], + "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], - "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA=="], + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="], "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="], - "@babel/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + "@babel/runtime": ["@babel/runtime@7.28.6", "", {}, "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA=="], - "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], - "@babel/traverse": ["@babel/traverse@7.28.5", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.5", "@babel/template": "^7.27.2", "@babel/types": "^7.28.5", "debug": "^4.3.1" } }, "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ=="], + "@babel/traverse": ["@babel/traverse@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/types": "^7.28.6", "debug": "^4.3.1" } }, "sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg=="], - "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + "@babel/types": ["@babel/types@7.28.6", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.10.1", "", {}, "sha512-ckS3+vyJb5qGpEYv/s1OebUHDi/xSNtfgw1wqKZo7MR9F2z+qXr0q5XagafAG/9O0QPVIUfST0smluYSTpYFkg=="], + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.11.0", "", {}, "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ=="], - "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.10.1", "", { "dependencies": { "@bufbuild/protobuf": "2.10.1", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-imB8dKEjrOnG5+XqVS+CeYn924WGLU/g3wogKhk11XtX9y9NJ7432OS6h24asuBbLrQcPdEZ6QkfM7KeOCeeyQ=="], + "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.11.0", "", { "dependencies": { "@bufbuild/protobuf": "2.11.0", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-lyZVNFUHArIOt4W0+dwYBe5GBwbKzbOy8ObaloEqsw9Mmiwv2O48TwddDoHN4itylC+BaEGqFdI1W8WQt2vWJQ=="], "@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="], @@ -890,9 +891,9 @@ "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], - "@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], + "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], - "@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], + "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], @@ -904,73 +905,73 @@ "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - "@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.4", "", { "os": "android", "cpu": "arm64" }, "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A=="], + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - "@esbuild/android-x64": ["@esbuild/android-x64@0.25.4", "", { "os": "android", "cpu": "x64" }, "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ=="], + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g=="], + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A=="], + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ=="], + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ=="], + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.4", "", { "os": "linux", "cpu": "arm" }, "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ=="], + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ=="], + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ=="], + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA=="], + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg=="], + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag=="], + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA=="], + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g=="], + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA=="], + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.4", "", { "os": "none", "cpu": "arm64" }, "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ=="], + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.4", "", { "os": "none", "cpu": "x64" }, "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw=="], + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A=="], + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@expressive-code/core": ["@expressive-code/core@0.41.3", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-9qzohqU7O0+JwMEEgQhnBPOw5DtsQRBXhW++5fvEywsuX44vCGGof1SL5OvPElvNgaWZ4pFZAFSlkNOkGyLwSQ=="], + "@expressive-code/core": ["@expressive-code/core@0.41.6", "", { "dependencies": { "@ctrl/tinycolor": "^4.0.4", "hast-util-select": "^6.0.2", "hast-util-to-html": "^9.0.1", "hast-util-to-text": "^4.0.1", "hastscript": "^9.0.0", "postcss": "^8.4.38", "postcss-nested": "^6.0.1", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1" } }, "sha512-FvJQP+hG0jWi/FLBSmvHInDqWR7jNANp9PUDjdMqSshHb0y7sxx3vHuoOr6SgXjWw+MGLqorZyPQ0aAlHEok6g=="], - "@expressive-code/plugin-frames": ["@expressive-code/plugin-frames@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3" } }, "sha512-rFQtmf/3N2CK3Cq/uERweMTYZnBu+CwxBdHuOftEmfA9iBE7gTVvwpbh82P9ZxkPLvc40UMhYt7uNuAZexycRQ=="], + "@expressive-code/plugin-frames": ["@expressive-code/plugin-frames@0.41.6", "", { "dependencies": { "@expressive-code/core": "^0.41.6" } }, "sha512-d+hkSYXIQot6fmYnOmWAM+7TNWRv/dhfjMsNq+mIZz8Tb4mPHOcgcfZeEM5dV9TDL0ioQNvtcqQNuzA1sRPjxg=="], - "@expressive-code/plugin-shiki": ["@expressive-code/plugin-shiki@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3", "shiki": "^3.2.2" } }, "sha512-RlTARoopzhFJIOVHLGvuXJ8DCEme/hjV+ZnRJBIxzxsKVpGPW4Oshqg9xGhWTYdHstTsxO663s0cdBLzZj9TQA=="], + "@expressive-code/plugin-shiki": ["@expressive-code/plugin-shiki@0.41.6", "", { "dependencies": { "@expressive-code/core": "^0.41.6", "shiki": "^3.2.2" } }, "sha512-Y6zmKBmsIUtWTzdefqlzm/h9Zz0Rc4gNdt2GTIH7fhHH2I9+lDYCa27BDwuBhjqcos6uK81Aca9dLUC4wzN+ng=="], - "@expressive-code/plugin-text-markers": ["@expressive-code/plugin-text-markers@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3" } }, "sha512-SN8tkIzDpA0HLAscEYD2IVrfLiid6qEdE9QLlGVSxO1KEw7qYvjpbNBQjUjMr5/jvTJ7ys6zysU2vLPHE0sb2g=="], + "@expressive-code/plugin-text-markers": ["@expressive-code/plugin-text-markers@0.41.6", "", { "dependencies": { "@expressive-code/core": "^0.41.6" } }, "sha512-PBFa1wGyYzRExMDzBmAWC6/kdfG1oLn4pLpBeTfIRrALPjcGA/59HP3e7q9J0Smk4pC7U+lWkA2LHR8FYV8U7Q=="], "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], - "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], + "@floating-ui/core": ["@floating-ui/core@1.7.4", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg=="], - "@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="], + "@floating-ui/dom": ["@floating-ui/dom@1.7.5", "", { "dependencies": { "@floating-ui/core": "^1.7.4", "@floating-ui/utils": "^0.2.10" } }, "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg=="], - "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="], + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.7", "", { "dependencies": { "@floating-ui/dom": "^1.7.5" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-0tLRojf/1Go2JgEVm+3Frg9A3IW8bJgKgdO0BN5RkF//ufuz2joZM63Npau2ff3J6lUVYgDSNzNkR+aH3IVfjg=="], "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], @@ -992,7 +993,7 @@ "@hey-api/types": ["@hey-api/types@0.1.2", "", {}, "sha512-uNNtiVAWL7XNrV/tFXx7GLY9lwaaDazx1173cGW3+UEaw4RUPsHEmiB4DSpcjNxMIcrctfz2sGKLnVx5PBG2RA=="], - "@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="], + "@hono/node-server": ["@hono/node-server@1.19.9", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw=="], "@hono/standard-validator": ["@hono/standard-validator@0.1.5", "", { "peerDependencies": { "@standard-schema/spec": "1.0.0", "hono": ">=3.9.0" } }, "sha512-EIyZPPwkyLn6XKwFj5NBEWHXhXbgmnVh2ceIFo5GO7gKI9WmzTjPDKnppQB0KrqKeAkq3kpoW4SIbu5X1dgx3w=="], @@ -1000,7 +1001,7 @@ "@ibm/plex": ["@ibm/plex@6.4.1", "", { "dependencies": { "@ibm/telemetry-js": "^1.5.1" } }, "sha512-fnsipQywHt3zWvsnlyYKMikcVI7E2fEwpiPnIHFqlbByXVfQfANAAeJk1IV4mNnxhppUIDlhU0TzwYwL++Rn2g=="], - "@ibm/telemetry-js": ["@ibm/telemetry-js@1.10.2", "", { "bin": { "ibmtelemetry": "dist/collect.js" } }, "sha512-F8+/NNUwtm8BuFz18O9KPvIFTFDo8GUSoyhPxPjEpk7nEyEzWGfhIiEPhL00B2NdHRLDSljh3AiCfSnL/tutiQ=="], + "@ibm/telemetry-js": ["@ibm/telemetry-js@1.11.0", "", { "bin": { "ibmtelemetry": "dist/collect.js" } }, "sha512-RO/9j+URJnSfseWg9ZkEX9p+a3Ousd33DBU7rOafoZB08RqdzxFVYJ2/iM50dkBuD0o7WX7GYt1sLbNgCoE+pA=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], @@ -1040,12 +1041,10 @@ "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], - "@internationalized/date": ["@internationalized/date@3.10.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-oxDR/NTEJ1k+UFVQElaNIk65E/Z83HK1z1WI3lQyhTtnNg4R5oVXaPzK3jcpKG8UHKDVuDQHzn+wsxSz8RP3aw=="], + "@internationalized/date": ["@internationalized/date@3.10.1", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA=="], "@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="], - "@ioredis/commands": ["@ioredis/commands@1.4.0", "", {}, "sha512-aFT2yemJJo+TZCmieA7qnYGQooOS7QfNmYrzGtsYd3g9j5iDP8AimYYAesf79ohjbLG12XxC4nG5DyEnC88AsQ=="], - "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], "@isaacs/brace-expansion": ["@isaacs/brace-expansion@5.0.0", "", { "dependencies": { "@isaacs/balanced-match": "^4.0.1" } }, "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA=="], @@ -1202,7 +1201,7 @@ "@motionone/utils": ["@motionone/utils@10.18.0", "", { "dependencies": { "@motionone/types": "^10.17.1", "hey-listen": "^1.0.8", "tslib": "^2.3.1" } }, "sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -1304,21 +1303,21 @@ "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], - "@opentui/core": ["@opentui/core@0.1.74", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.74", "@opentui/core-darwin-x64": "0.1.74", "@opentui/core-linux-arm64": "0.1.74", "@opentui/core-linux-x64": "0.1.74", "@opentui/core-win32-arm64": "0.1.74", "@opentui/core-win32-x64": "0.1.74", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-g4W16ymv12JdgZ+9B4t7mpIICvzWy2+eHERfmDf80ALduOQCUedKQdULcBFhVCYUXIkDRtIy6CID5thMAah3FA=="], + "@opentui/core": ["@opentui/core@0.1.75", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.75", "@opentui/core-darwin-x64": "0.1.75", "@opentui/core-linux-arm64": "0.1.75", "@opentui/core-linux-x64": "0.1.75", "@opentui/core-win32-arm64": "0.1.75", "@opentui/core-win32-x64": "0.1.75", "bun-webgpu": "0.1.4", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-8ARRZxSG+BXkJmEVtM2DQ4se7DAF1ZCKD07d+AklgTr2mxCzmdxxPbOwRzboSQ6FM7qGuTVPVbV4O2W9DpUmoA=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.74", "", { "os": "darwin", "cpu": "arm64" }, "sha512-rfmlDLtm/u17CnuhJgCxPeYMvOST+A2MOdVOk46IurtHO849bdYqK6iudKNlFRs1FOrymgSKF9GlWBHAOKeRjg=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.75", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gGaGZjkFpqcXJk6321JzhRl66pM2VxBlI470L8W4DQUW4S6iDT1R9L7awSzGB4Cn9toUl7DTV8BemaXZYXV4SA=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.74", "", { "os": "darwin", "cpu": "x64" }, "sha512-WAD8orsDV0ZdW/5GwjOOB4FY96772xbkz+rcV7WRzEFUVaqoBaC04IuqYzS9d5s+cjkbT5Cpj47hrVYkkVQKng=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.75", "", { "os": "darwin", "cpu": "x64" }, "sha512-tPlvqQI0whZ76amHydpJs5kN+QeWAIcFbI8RAtlAo9baj2EbxTDC+JGwgb9Fnt0/YQx831humbtaNDhV2Jt1bw=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.74", "", { "os": "linux", "cpu": "arm64" }, "sha512-lgmHzrzLy4e+rgBS+lhtsMLLgIMLbtLNMm6EzVPyYVDlLDGjM7+ulXMem7AtpaRrWrUUl4REiG9BoQUsCFDwYA=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.75", "", { "os": "linux", "cpu": "arm64" }, "sha512-nVxIQ4Hqf84uBergDpWiVzU6pzpjy6tqBHRQpySxZ2flkJ/U6/aMEizVrQ1jcgIdxZtvqWDETZhzxhG0yDx+cw=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.74", "", { "os": "linux", "cpu": "x64" }, "sha512-8Mn2WbdBQ29xCThuPZezjDhd1N3+fXwKkGvCBOdTI0le6h2A/vCNbfUVjwfr/EGZSRXxCG+Yapol34BAULGpOA=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.75", "", { "os": "linux", "cpu": "x64" }, "sha512-1CnApef4kxA+ORyLfbuCLgZfEjp4wr3HjFnt7FAfOb73kIZH82cb7JYixeqRyy9eOcKfKqxLmBYy3o8IDkc4Rg=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.74", "", { "os": "win32", "cpu": "arm64" }, "sha512-dvYUXz03avnI6ZluyLp00HPmR0UT/IE/6QS97XBsgJlUTtpnbKkBtB5jD1NHwWkElaRj1Qv2QP36ngFoJqbl9g=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.75", "", { "os": "win32", "cpu": "arm64" }, "sha512-j0UB95nmkYGNzmOrs6GqaddO1S90R0YC6IhbKnbKBdjchFPNVLz9JpexAs6MBDXPZwdKAywMxtwG2h3aTJtxng=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.74", "", { "os": "win32", "cpu": "x64" }, "sha512-3wfWXaAKOIlDQz6ZZIESf2M+YGZ7uFHijjTEM8w/STRlLw8Y6+QyGYi1myHSM4d6RSO+/s2EMDxvjDf899W9vQ=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.75", "", { "os": "win32", "cpu": "x64" }, "sha512-ESpVZVGewe3JkB2TwrG3VRbkxT909iPdtvgNT7xTCIYH2VB4jqZomJfvERPTE0tvqAZJm19mHECzJFI8asSJgQ=="], - "@opentui/solid": ["@opentui/solid@0.1.74", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.74", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-Vz82cI8T9YeJjGsVg4ULp6ral4N+xyt1j9A6Tbu3aaQgEKiB74LW03EXREehfjPr1irOFxtKfWPbx5NKH0Upag=="], + "@opentui/solid": ["@opentui/solid@0.1.75", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.75", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.9", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.9" } }, "sha512-WjKsZIfrm29znfRlcD9w3uUn/+uvoy2MmeoDwTvg1YOa0OjCTCmjZ43L9imp0m9S4HmVU8ma6o2bR4COzcyDdg=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -1442,11 +1441,11 @@ "@playwright/test": ["@playwright/test@1.57.0", "", { "dependencies": { "playwright": "1.57.0" }, "bin": { "playwright": "cli.js" } }, "sha512-6TyEnHgd6SArQO8UO2OMTxshln3QMWBtPGrOCgs3wVEmQmwyuNtB10IZMfmYDE0riwNR1cu4q+pPcxMVtaG3TA=="], - "@poppinss/colors": ["@poppinss/colors@4.1.5", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-FvdDqtcRCtz6hThExcFOgW0cWX+xwSMWcRuQe5ZEb2m7cVQOAVZOIMt+/v9RxGiD9/OY16qJBXK4CVKWAPalBw=="], + "@poppinss/colors": ["@poppinss/colors@4.1.6", "", { "dependencies": { "kleur": "^4.1.5" } }, "sha512-H9xkIdFswbS8n1d6vmRd8+c10t2Qe+rZITbbDHHkQixH5+2x1FDGmi/0K+WgWiqQFKPSlIYB7jlH6Kpfn6Fleg=="], "@poppinss/dumper": ["@poppinss/dumper@0.6.5", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@sindresorhus/is": "^7.0.2", "supports-color": "^10.0.0" } }, "sha512-NBdYIb90J7LfOI32dOewKI1r7wnkiH6m920puQ3qHUeZkxNkQiFnXVWoE6YtFSv6QOiPPf7ys6i+HWWecDz7sw=="], - "@poppinss/exception": ["@poppinss/exception@1.2.2", "", {}, "sha512-m7bpKCD4QMlFCjA/nKTs23fuvoVFoA83brRKmObCUNmi/9tVu8Ve3w4YQAnJu4q3Tjf5fr685HYIC/IA2zHRSg=="], + "@poppinss/exception": ["@poppinss/exception@1.2.3", "", {}, "sha512-dCED+QRChTVatE9ibtoaxc+WkdzOSjYTKi/+uacHWIsfodVfpsueo3+DKpgU5Px8qXjgmXkSvhXvSCz3fnP9lw=="], "@protobuf-ts/plugin": ["@protobuf-ts/plugin@2.11.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.4.0", "@bufbuild/protoplugin": "^2.4.0", "@protobuf-ts/protoc": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", "@protobuf-ts/runtime-rpc": "^2.11.1", "typescript": "^3.9" }, "bin": { "protoc-gen-ts": "bin/protoc-gen-ts", "protoc-gen-dump": "bin/protoc-gen-dump" } }, "sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A=="], @@ -1524,53 +1523,59 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.0", "", { "os": "android", "cpu": "arm" }, "sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.0", "", { "os": "android", "cpu": "arm64" }, "sha512-sa4LyseLLXr1onr97StkU1Nb7fWcg6niokTwEVNOO7awaKaoRObQ54+V/hrF/BP1noMEaaAW6Fg2d/CfLiq3Mg=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/NNIj9A7yLjKdmkx5dC2XQ9DmjIECpGpwHoGmA5E1AhU0fuICSqSWScPhN1yLCkEdkCwJIDu2xIeLPs60MNIVg=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-xoh8abqgPrPYPr7pTYipqnUi1V3em56JzE/HgDgitTqZBZ3yKCWI+7KUkceM6tNweyUKYru1UMi7FC060RyKwA=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-PCkMh7fNahWSbA0OTUQ2OpYHpjZZr0hPr8lId8twD7a7SeWrvT3xJVyza+dQwXSSq4yEQTMoXgNOfMCsn8584g=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1j3stGx+qbhXql4OCDZhnK7b01s6rBKNybfsX+TNrEe9JNq4DLi1yGiR1xW+nL+FNVvI4D02PUnl6gJ/2y6WJA=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.0", "", { "os": "linux", "cpu": "arm" }, "sha512-eyrr5W08Ms9uM0mLcKfM/Uzx7hjhz2bcjv8P2uynfj0yU8GGPdz8iYrBPhiLOZqahoAMB8ZiolRZPbbU2MAi6Q=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.0", "", { "os": "linux", "cpu": "arm" }, "sha512-Xds90ITXJCNyX9pDhqf85MKWUI4lqjiPAipJ8OLp8xqI2Ehk+TCVhF9rvOoN8xTbcafow3QOThkNnrM33uCFQA=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Xws2KA4CLvZmXjy46SQaXSejuKPhwVdaNinldoYfqruZBaJHqVo6hnRa8SDo9z7PBW5x84SH64+izmldCgbezw=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-hrKXKbX5FdaRJj7lTMusmvKbhMJSGWJ+w++4KmjiDhpTgNlhYobMvKfDoIWecy4O60K6yA4SnztGuNTQF+Lplw=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.0", "", { "os": "linux", "cpu": "none" }, "sha512-6A+nccfSDGKsPm00d3xKcrsBcbqzCTAukjwWK6rbuAnB2bHaL3r9720HBVZ/no7+FhZLz/U3GwwZZEh6tOSI8Q=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.0", "", { "os": "linux", "cpu": "none" }, "sha512-4P1VyYUe6XAJtQH1Hh99THxr0GKMMwIXsRNOceLrJnaHTDgk1FTcTimDgneRJPvB3LqDQxUmroBclQ1S0cIJwQ=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-8Vv6pLuIZCMcgXre6c3nOPhE0gjz1+nZP6T+hwWjr7sVH8k0jRkH+XnfjjOTglyMBdSKBPPz54/y1gToSKwrSQ=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-r1te1M0Sm2TBVD/RxBPC6RZVwNqUTwJTA7w+C/IW5v9Ssu6xmxWEi+iJQlpBhtUiT1raJ5b48pI8tBvEjEFnFA=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.0", "", { "os": "linux", "cpu": "none" }, "sha512-say0uMU/RaPm3CDQLxUUTF2oNWL8ysvHkAjcCzV2znxBr23kFfaxocS9qJm+NdkRhF8wtdEEAJuYcLPhSPbjuQ=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.0", "", { "os": "linux", "cpu": "none" }, "sha512-/MU7/HizQGsnBREtRpcSbSV1zfkoxSTR7wLsRmBPQ8FwUj5sykrP1MyJTvsxP5KBq9SyE6kH8UQQQwa0ASeoQQ=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-Q9eh+gUGILIHEaJf66aF6a414jQbDnn29zeu0eX3dHMuysnhTvsUvZTCAyZ6tJhUjnvzBKE4FtuaYxutxRZpOg=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.0", "", { "os": "linux", "cpu": "x64" }, "sha512-OR5p5yG5OKSxHReWmwvM0P+VTPMwoBS45PXTMYaskKQqybkS3Kmugq1W+YbNWArF8/s7jQScgzXUhArzEQ7x0A=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XeatKzo4lHDsVEbm1XDHZlhYZZSQYym6dg2X/Ko0kSFgio+KXLsxwJQprnR48GvdIKDOpqWqssC3iBCjoMcMpw=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.0", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Lu71y78F5qOfYmubYLHPcJm74GZLU6UJ4THkf/a1K7Tz2ycwC2VUbsqbJAXaR6Bx70SRdlVrt2+n5l7F0agTUw=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.0", "", { "os": "none", "cpu": "arm64" }, "sha512-v5xwKDWcu7qhAEcsUubiav7r+48Uk/ENWdr82MBZZRIm7zThSxCIVDfb3ZeRRq9yqk+oIzMdDo6fCcA5DHfMyA=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-XnaaaSMGSI6Wk8F4KK3QP7GfuuhjGchElsVerCplUuxRIzdvZ7hRBpLR0omCmw+kI2RFJB80nenhOoGXlJ5TfQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-3K1lP+3BXY4t4VihLw5MEg6IZD3ojSYzqzBG571W3kNQe4G4CcFpSUQVgurYgib5d+YaCjeFow8QivWp8vuSvA=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.0", "", { "os": "win32", "cpu": "x64" }, "sha512-MDk610P/vJGc5L5ImE4k5s+GZT3en0KoK1MKPXCRgzmksAMk79j4h3k1IerxTNqwDLxsGxStEZVBqG0gIqZqoA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Zv7v6q6aV+VslnpwzqKAmrk5JdVkLUzok2208ZXGipjb+msxBr/fJPZyeEXiFgH7k62Ak0SLIfxQRZQvTuf7rQ=="], "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], - "@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], + "@shikijs/core": ["@shikijs/core@3.21.0", "", { "dependencies": { "@shikijs/types": "3.21.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA=="], "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.19.0", "", { "dependencies": { "@shikijs/types": "3.19.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-ZfWJNm2VMhKkQIKT9qXbs76RRcT0SF/CAvEz0+RkpUDAoDaCx0uFdCGzSRiD9gSlhm6AHkjdieOBJMaO2eC1rQ=="], @@ -1586,7 +1591,7 @@ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], - "@sindresorhus/is": ["@sindresorhus/is@7.1.1", "", {}, "sha512-rO92VvpgMc3kfiTjGT52LEtJ8Yc5kCWhZjLQ3LwlA4pSgPpQO7bVpYXParOD8Jwf+cVQECJo3yP/4I8aZtUQTQ=="], + "@sindresorhus/is": ["@sindresorhus/is@7.2.0", "", {}, "sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw=="], "@slack/bolt": ["@slack/bolt@3.22.0", "", { "dependencies": { "@slack/logger": "^4.0.0", "@slack/oauth": "^2.6.3", "@slack/socket-mode": "^1.3.6", "@slack/types": "^2.13.0", "@slack/web-api": "^6.13.0", "@types/express": "^4.16.1", "@types/promise.allsettled": "^1.0.3", "@types/tsscmp": "^1.0.0", "axios": "^1.7.4", "express": "^4.21.0", "path-to-regexp": "^8.1.0", "promise.allsettled": "^1.0.2", "raw-body": "^2.3.3", "tsscmp": "^1.0.6" } }, "sha512-iKDqGPEJDnrVwxSVlFW6OKTkijd7s4qLBeSufoBsTM0reTyfdp/5izIQVkxNfzjHi3o6qjdYbRXkYad5HBsBog=="], @@ -1600,75 +1605,75 @@ "@slack/web-api": ["@slack/web-api@6.13.0", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.11.0", "@types/is-stream": "^1.1.0", "@types/node": ">=12.0.0", "axios": "^1.7.4", "eventemitter3": "^3.1.0", "form-data": "^2.5.0", "is-electron": "2.2.2", "is-stream": "^1.1.0", "p-queue": "^6.6.1", "p-retry": "^4.0.0" } }, "sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g=="], - "@smithy/abort-controller": ["@smithy/abort-controller@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA=="], + "@smithy/abort-controller": ["@smithy/abort-controller@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-peuVfkYHAmS5ybKxWcfraK7WBBP0J+rkfUcbHJJKQ4ir3UAUNQI+Y4Vt/PqSzGqgloJ5O1dk7+WzNL8wcCSXbw=="], "@smithy/chunked-blob-reader": ["@smithy/chunked-blob-reader@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA=="], "@smithy/chunked-blob-reader-native": ["@smithy/chunked-blob-reader-native@4.2.1", "", { "dependencies": { "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ=="], - "@smithy/config-resolver": ["@smithy/config-resolver@4.4.3", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw=="], + "@smithy/config-resolver": ["@smithy/config-resolver@4.4.6", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-qJpzYC64kaj3S0fueiu3kXm8xPrR3PcXDPEgnaNMRn0EjNSZFoFjvbUp0YUDsRhN1CB90EnHJtbxWKevnH99UQ=="], - "@smithy/core": ["@smithy/core@3.18.5", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.6", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw=="], + "@smithy/core": ["@smithy/core@3.22.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.9", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-stream": "^4.5.10", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-6vjCHD6vaY8KubeNw2Fg3EK0KLGQYdldG4fYgQmA0xSW0dJ8G2xFhSOdrlUakWVoP5JuWHtFODg3PNd/DN3FDA=="], - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ=="], + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-FNT0xHS1c/CPN8upqbMFP83+ul5YgdisfCfkZ86Jh2NSmnqw/AJ6x5pEogVCTVvSm7j9MopRU89bmDelxuDMYw=="], "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.7", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DrpkEoM3j9cBBWhufqBwnbbn+3nf1N9FP6xuVJ+e220jbactKuQgaZwjwP5CP1t+O94brm2JgVMD2atMGX3xIQ=="], - "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.2.5", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw=="], + "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.2.8", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-MTfQT/CRQz5g24ayXdjg53V0mhucZth4PESoA5IhvaWVDTOQLfo8qI9vzqHcPsdd2v6sqfTYqF5L/l+pea5Uyw=="], - "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.3.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ=="], + "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.3.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-ah12+luBiDGzBruhu3efNy1IlbwSEdNiw8fOZksoKoWW1ZHvO/04MQsdnws/9Aj+5b0YXSSN2JXKy/ClIsW8MQ=="], - "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.2.5", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg=="], + "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.2.8", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-cYpCpp29z6EJHa5T9WL0KAlq3SOKUQkcgSoeRfRVwjGgSFl7Uh32eYGt7IDYCX20skiEdRffyDpvF2efEZPC0A=="], - "@smithy/eventstream-serde-universal": ["@smithy/eventstream-serde-universal@4.2.5", "", { "dependencies": { "@smithy/eventstream-codec": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q=="], + "@smithy/eventstream-serde-universal": ["@smithy/eventstream-serde-universal@4.2.8", "", { "dependencies": { "@smithy/eventstream-codec": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-iJ6YNJd0bntJYnX6s52NC4WFYcZeKrPUr1Kmmr5AwZcwCSzVpS7oavAmxMR7pMq7V+D1G4s9F5NJK0xwOsKAlQ=="], - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg=="], + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-I4UhmcTYXBrct03rwzQX1Y/iqQlzVQaPxWjCjula++5EmWq9YGBrx6bbGqluGc1f0XEfhSkiY4jhLgbsJUMKRA=="], - "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.2.6", "", { "dependencies": { "@smithy/chunked-blob-reader": "^5.2.0", "@smithy/chunked-blob-reader-native": "^4.2.1", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8P//tA8DVPk+3XURk2rwcKgYwFvwGwmJH/wJqQiSKwXZtf/LiZK+hbUZmPj/9KzM+OVSwe4o85KTp5x9DUZTjw=="], + "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.2.9", "", { "dependencies": { "@smithy/chunked-blob-reader": "^5.2.0", "@smithy/chunked-blob-reader-native": "^4.2.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-m80d/iicI7DlBDxyQP6Th7BW/ejDGiF0bgI754+tiwK0lgMkcaIBgvwwVc7OFbY4eUzpGtnig52MhPAEJ7iNYg=="], - "@smithy/hash-node": ["@smithy/hash-node@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA=="], + "@smithy/hash-node": ["@smithy/hash-node@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-7ZIlPbmaDGxVoxErDZnuFG18WekhbA/g2/i97wGj+wUBeS6pcUeAym8u4BXh/75RXWhgIJhyC11hBzig6MljwA=="], - "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6+do24VnEyvWcGdHXomlpd0m8bfZePpUKBy7m311n+JuRwug8J4dCanJdTymx//8mi0nlkflZBvJe+dEO/O12Q=="], + "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-v0FLTXgHrTeheYZFGhR+ehX5qUm4IQsjAiL9qehad2cyjMWcN2QG6/4mSwbSgEQzI7jwfoXj7z4fxZUx/Mhj2w=="], - "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A=="], + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-N9iozRybwAQ2dn9Fot9kI6/w9vos2oTXLhtK7ovGqwZjlOcxu6XhPlpLpC+INsxktqHinn5gS2DXDjDF2kG5sQ=="], "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="], - "@smithy/md5-js": ["@smithy/md5-js@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Bt6jpSTMWfjCtC0s79gZ/WZ1w90grfmopVOWqkI2ovhjpD5Q2XRXuecIPB9689L2+cCySMbaXDhBPU56FKNDNg=="], + "@smithy/md5-js": ["@smithy/md5-js@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-oGMaLj4tVZzLi3itBa9TCswgMBr7k9b+qKYowQ6x1rTyTuO1IU2YHdHUa+891OsOH+wCsH7aTPRsTJO3RMQmjQ=="], - "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.5", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A=="], + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-RO0jeoaYAB1qBRhfVyq0pMgBoUK34YEJxVxyjOWYZiOKOq2yMZ4MnVXMZCUDenpozHue207+9P5ilTV1zeda0A=="], - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.3.12", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-serde": "^4.2.6", "@smithy/node-config-provider": "^4.3.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-middleware": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A=="], + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.12", "", { "dependencies": { "@smithy/core": "^3.22.0", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-middleware": "^4.2.8", "tslib": "^2.6.2" } }, "sha512-9JMKHVJtW9RysTNjcBZQHDwB0p3iTP6B1IfQV4m+uCevkVd/VuLgwfqk5cnI4RHcp4cPwoIvxQqN4B1sxeHo8Q=="], - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.12", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/protocol-http": "^5.3.5", "@smithy/service-error-classification": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ=="], + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.29", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-bmTn75a4tmKRkC5w61yYQLb3DmxNzB8qSVu9SbTYqW6GAL0WXO2bDZuMAn/GJSbOdHEdjZvWxe+9Kk015bw6Cg=="], - "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.6", "", { "dependencies": { "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ=="], + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.9", "", { "dependencies": { "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-eMNiej0u/snzDvlqRGSN3Vl0ESn3838+nKyVfF2FKNXFbi4SERYT6PR392D39iczngbqqGG0Jl1DlCnp7tBbXQ=="], - "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ=="], + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-w6LCfOviTYQjBctOKSwy6A8FIkQy7ICvglrZFl6Bw4FmcQ1Z420fUtIhxaUZZshRe0VCq4kvDiPiXrPZAe8oRA=="], - "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.5", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg=="], + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.8", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-aFP1ai4lrbVlWjfpAfRSL8KFcnJQYfTl5QxLJXY32vghJrDuFyPZ6LtUL+JEGYiFRG1PfPLHLoxj107ulncLIg=="], - "@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/querystring-builder": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw=="], + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.8", "", { "dependencies": { "@smithy/abort-controller": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/querystring-builder": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-q9u+MSbJVIJ1QmJ4+1u+cERXkrhuILCBDsJUBAW1MPE6sFonbCNaegFuwW9ll8kh5UdyY3jOkoOGlc7BesoLpg=="], - "@smithy/property-provider": ["@smithy/property-provider@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg=="], + "@smithy/property-provider": ["@smithy/property-provider@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-EtCTbyIveCKeOXDSWSdze3k612yCPq1YbXsbqX3UHhkOSW8zKsM9NOJG5gTIya0vbY2DIaieG8pKo1rITHYL0w=="], - "@smithy/protocol-http": ["@smithy/protocol-http@5.3.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ=="], + "@smithy/protocol-http": ["@smithy/protocol-http@5.3.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-QNINVDhxpZ5QnP3aviNHQFlRogQZDfYlCkQT+7tJnErPQbDhysondEjhikuANxgMsZrkGeiAxXy4jguEGsDrWQ=="], - "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg=="], + "@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Xr83r31+DrE8CP3MqPgMJl+pQlLLmOfiEUnoyAlGzzJIrEsbKsPy1hqH0qySaQm4oWrCBlUqRt+idEgunKB+iw=="], - "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ=="], + "@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-vUurovluVy50CUlazOiXkPq40KGvGWSdmusa3130MwrR1UNnNgKAlj58wlOe61XSHRpUfIIh6cE0zZ8mzKaDPA=="], - "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0" } }, "sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ=="], + "@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0" } }, "sha512-mZ5xddodpJhEt3RkCjbmUQuXUOaPNTkbMGR0bcS8FE0bJDLMZlhmpgrvPNCYglVw5rsYTpSnv19womw9WWXKQQ=="], - "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA=="], + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.3", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-DfQjxXQnzC5UbCUPeC3Ie8u+rIWZTvuDPAGU/BxzrOGhRvgUanaP68kDZA+jaT3ZI+djOf+4dERGlm9mWfFDrg=="], - "@smithy/signature-v4": ["@smithy/signature-v4@5.3.5", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w=="], + "@smithy/signature-v4": ["@smithy/signature-v4@5.3.8", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6A4vdGj7qKNRF16UIcO8HhHjKW27thsxYci+5r/uVRkdcBEkOEiY8OMPuydLX4QHSrJqGHPJzPRwwVTqbLZJhg=="], - "@smithy/smithy-client": ["@smithy/smithy-client@4.9.8", "", { "dependencies": { "@smithy/core": "^3.18.5", "@smithy/middleware-endpoint": "^4.3.12", "@smithy/middleware-stack": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "@smithy/util-stream": "^4.5.6", "tslib": "^2.6.2" } }, "sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA=="], + "@smithy/smithy-client": ["@smithy/smithy-client@4.11.1", "", { "dependencies": { "@smithy/core": "^3.22.0", "@smithy/middleware-endpoint": "^4.4.12", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" } }, "sha512-SERgNg5Z1U+jfR6/2xPYjSEHY1t3pyTHC/Ma3YQl6qWtmiL42bvNId3W/oMUWIwu7ekL2FMPdqAmwbQegM7HeQ=="], - "@smithy/types": ["@smithy/types@4.9.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA=="], + "@smithy/types": ["@smithy/types@4.12.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9YcuJVTOBDjg9LWo23Qp0lTQ3D7fQsQtwle0jVfpbUHy9qBwCEgKuVH4FqFB3VYu0nwdHKiEMA+oXz7oV8X1kw=="], - "@smithy/url-parser": ["@smithy/url-parser@4.2.5", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ=="], + "@smithy/url-parser": ["@smithy/url-parser@4.2.8", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-NQho9U68TGMEU639YkXnVMV3GEFFULmmaWdlu1E9qzyIePOHsoSnagTGSDv1Zi8DCNN6btxOSdgmy5E/hsZwhA=="], "@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="], @@ -1680,25 +1685,25 @@ "@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="], - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.11", "", { "dependencies": { "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw=="], + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.28", "", { "dependencies": { "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-/9zcatsCao9h6g18p/9vH9NIi5PSqhCkxQ/tb7pMgRFnqYp9XUOyOlGPDMHzr8n5ih6yYgwJEY2MLEobUgi47w=="], - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.14", "", { "dependencies": { "@smithy/config-resolver": "^4.4.3", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/smithy-client": "^4.9.8", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA=="], + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.31", "", { "dependencies": { "@smithy/config-resolver": "^4.4.6", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/smithy-client": "^4.11.1", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-JTvoApUXA5kbpceI2vuqQzRjeTbLpx1eoa5R/YEZbTgtxvIB7AQZxFJ0SEyfCpgPCyVV9IT7we+ytSeIB3CyWA=="], - "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A=="], + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.8", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-8JaVTn3pBDkhZgHQ8R0epwWt+BqPSLCjdjXXusK1onwJlRuN69fbvSK66aIKKO7SwVFM6x2J2ox5X8pOaWcUEw=="], "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="], - "@smithy/util-middleware": ["@smithy/util-middleware@4.2.5", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA=="], + "@smithy/util-middleware": ["@smithy/util-middleware@4.2.8", "", { "dependencies": { "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-PMqfeJxLcNPMDgvPbbLl/2Vpin+luxqTGPpW3NAQVLbRrFRzTa4rNAASYeIGjRV9Ytuhzny39SpyU04EQreF+A=="], - "@smithy/util-retry": ["@smithy/util-retry@4.2.5", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg=="], + "@smithy/util-retry": ["@smithy/util-retry@4.2.8", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-CfJqwvoRY0kTGe5AkQokpURNCT1u/MkRzMTASWMPPo2hNSnKtF1D45dQl3DE2LKLr4m+PW9mCeBMJr5mCAVThg=="], - "@smithy/util-stream": ["@smithy/util-stream@4.5.6", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.6", "@smithy/node-http-handler": "^4.4.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ=="], + "@smithy/util-stream": ["@smithy/util-stream@4.5.10", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.8", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-jbqemy51UFSZSp2y0ZmRfckmrzuKww95zT9BYMmuJ8v3altGcqjwoV1tzpOwuHaKrwQrCjIzOib499ymr2f98g=="], "@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="], "@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], - "@smithy/util-waiter": ["@smithy/util-waiter@4.2.5", "", { "dependencies": { "@smithy/abort-controller": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-Dbun99A3InifQdIrsXZ+QLcC0PGBPAdrl4cj1mTgJvyc9N2zf7QSxg8TBkzsCmGJdE3TLbO9ycwpY0EkWahQ/g=="], + "@smithy/util-waiter": ["@smithy/util-waiter@4.2.8", "", { "dependencies": { "@smithy/abort-controller": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" } }, "sha512-n+lahlMWk+aejGuax7DPWtqav8HYnWxQwR+LCG2BgCUmaGcTe9qZCFsmw8TMg9iG75HOwhrJCX9TCJRLH+Yzqg=="], "@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="], @@ -1716,7 +1721,7 @@ "@solid-primitives/i18n": ["@solid-primitives/i18n@2.2.1", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-TnTnE2Ku11MGYZ1JzhJ8pYscwg1fr9MteoYxPwsfxWfh9Jp5K7RRJncJn9BhOHvNLwROjqOHZ46PT7sPHqbcXw=="], - "@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.2", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-BgoEdqPw48URnI+L5sZIHdF4ua4Las1eWEBBPaoSFs42kkhnHue+rwCBPL2Z9ebOyQ75sUhUfOETdJfmv0D6Kg=="], + "@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.3", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zNadtyYBhJSOjXtogkGHmRxjGdz9KHc8sGGVAGlUABkE8BED2tbIZoxkwSqzOwde8OcUEH0bb5DLZUWIMvyBSA=="], "@solid-primitives/map": ["@solid-primitives/map@0.4.13", "", { "dependencies": { "@solid-primitives/trigger": "^1.1.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew=="], @@ -1750,7 +1755,7 @@ "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dfb2020", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }], - "@speed-highlight/core": ["@speed-highlight/core@1.2.12", "", {}, "sha512-uilwrK0Ygyri5dToHYdZSjcvpS2ZwX0w5aSt3GCEN9hrjxWCoeV4Z2DTXuxjwbntaLQIEEAlCeNQss5SoHvAEA=="], + "@speed-highlight/core": ["@speed-highlight/core@1.2.14", "", {}, "sha512-G4ewlBNhUtlLvrJTb88d2mdy2KRijzs4UhnlrOSRT4bmjh/IqNElZa3zkrZ+TC47TwtlDWzVLFADljF1Ijp5hA=="], "@standard-community/standard-json": ["@standard-community/standard-json@0.3.5", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@types/json-schema": "^7.0.15", "@valibot/to-json-schema": "^1.3.0", "arktype": "^2.1.20", "effect": "^3.16.8", "quansync": "^0.2.11", "sury": "^10.0.0", "typebox": "^1.0.17", "valibot": "^1.1.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.24.5" }, "optionalPeers": ["@valibot/to-json-schema", "arktype", "effect", "sury", "typebox", "valibot", "zod", "zod-to-json-schema"] }, "sha512-4+ZPorwDRt47i+O7RjyuaxHRK/37QY/LmgxlGrRrSTLYoFatEOzvqIc85GTlM18SFZ5E91C+v0o/M37wZPpUHA=="], @@ -1760,7 +1765,7 @@ "@stripe/stripe-js": ["@stripe/stripe-js@8.6.1", "", {}, "sha512-UJ05U2062XDgydbUcETH1AoRQLNhigQ2KmDn1BG8sC3xfzu6JKg95Qt6YozdzFpxl1Npii/02m2LEWFt1RYjVA=="], - "@swc/helpers": ["@swc/helpers@0.5.17", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A=="], + "@swc/helpers": ["@swc/helpers@0.5.18", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ=="], "@tailwindcss/node": ["@tailwindcss/node@4.1.11", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "enhanced-resolve": "^5.18.1", "jiti": "^2.4.2", "lightningcss": "1.30.1", "magic-string": "^0.30.17", "source-map-js": "^1.2.1", "tailwindcss": "4.1.11" } }, "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q=="], @@ -1798,47 +1803,47 @@ "@tanstack/server-functions-plugin": ["@tanstack/server-functions-plugin@1.134.5", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/directive-functions-plugin": "1.134.5", "babel-dead-code-elimination": "^1.0.9", "tiny-invariant": "^1.3.3" } }, "sha512-2sWxq70T+dOEUlE3sHlXjEPhaFZfdPYlWTSkHchWXrFGw2YOAa+hzD6L9wHMjGDQezYd03ue8tQlHG+9Jzbzgw=="], - "@tauri-apps/api": ["@tauri-apps/api@2.9.0", "", {}, "sha512-qD5tMjh7utwBk9/5PrTA/aGr3i5QaJ/Mlt7p8NilQ45WgbifUNPyKWsA63iQ8YfQq6R8ajMapU+/Q8nMcPRLNw=="], + "@tauri-apps/api": ["@tauri-apps/api@2.9.1", "", {}, "sha512-IGlhP6EivjXHepbBic618GOmiWe4URJiIeZFlB7x3czM0yDHHYviH1Xvoiv4FefdkQtn6v7TuwWCRfOGdnVUGw=="], - "@tauri-apps/cli": ["@tauri-apps/cli@2.9.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.9.4", "@tauri-apps/cli-darwin-x64": "2.9.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.4", "@tauri-apps/cli-linux-arm64-gnu": "2.9.4", "@tauri-apps/cli-linux-arm64-musl": "2.9.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.9.4", "@tauri-apps/cli-linux-x64-gnu": "2.9.4", "@tauri-apps/cli-linux-x64-musl": "2.9.4", "@tauri-apps/cli-win32-arm64-msvc": "2.9.4", "@tauri-apps/cli-win32-ia32-msvc": "2.9.4", "@tauri-apps/cli-win32-x64-msvc": "2.9.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-pvylWC9QckrOS9ATWXIXcgu7g2hKK5xTL5ZQyZU/U0n9l88SEFGcWgLQNa8WZmd+wWIOWhkxOFcOl3i6ubDNNw=="], + "@tauri-apps/cli": ["@tauri-apps/cli@2.9.6", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.9.6", "@tauri-apps/cli-darwin-x64": "2.9.6", "@tauri-apps/cli-linux-arm-gnueabihf": "2.9.6", "@tauri-apps/cli-linux-arm64-gnu": "2.9.6", "@tauri-apps/cli-linux-arm64-musl": "2.9.6", "@tauri-apps/cli-linux-riscv64-gnu": "2.9.6", "@tauri-apps/cli-linux-x64-gnu": "2.9.6", "@tauri-apps/cli-linux-x64-musl": "2.9.6", "@tauri-apps/cli-win32-arm64-msvc": "2.9.6", "@tauri-apps/cli-win32-ia32-msvc": "2.9.6", "@tauri-apps/cli-win32-x64-msvc": "2.9.6" }, "bin": { "tauri": "tauri.js" } }, "sha512-3xDdXL5omQ3sPfBfdC8fCtDKcnyV7OqyzQgfyT5P3+zY6lcPqIYKQBvUasNvppi21RSdfhy44ttvJmftb0PCDw=="], - "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9rHkMVtbMhe0AliVbrGpzMahOBg3rwV46JYRELxR9SN6iu1dvPOaMaiC4cP6M/aD1424ziXnnMdYU06RAH8oIw=="], + "@tauri-apps/cli-darwin-arm64": ["@tauri-apps/cli-darwin-arm64@2.9.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gf5no6N9FCk1qMrti4lfwP77JHP5haASZgVbBgpZG7BUepB3fhiLCXGUK8LvuOjP36HivXewjg72LTnPDScnQQ=="], - "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-VT9ymNuT06f5TLjCZW2hfSxbVtZDhORk7CDUDYiq5TiSYQdxkl8MVBy0CCFFcOk4QAkUmqmVUA9r3YZ/N/vPRQ=="], + "@tauri-apps/cli-darwin-x64": ["@tauri-apps/cli-darwin-x64@2.9.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-oWh74WmqbERwwrwcueJyY6HYhgCksUc6NT7WKeXyrlY/FPmNgdyQAgcLuTSkhRFuQ6zh4Np1HZpOqCTpeZBDcw=="], - "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.9.4", "", { "os": "linux", "cpu": "arm" }, "sha512-tTWkEPig+2z3Rk0zqZYfjUYcgD+aSm72wdrIhdYobxbQZOBw0zfn50YtWv+av7bm0SHvv75f0l7JuwgZM1HFow=="], + "@tauri-apps/cli-linux-arm-gnueabihf": ["@tauri-apps/cli-linux-arm-gnueabihf@2.9.6", "", { "os": "linux", "cpu": "arm" }, "sha512-/zde3bFroFsNXOHN204DC2qUxAcAanUjVXXSdEGmhwMUZeAQalNj5cz2Qli2elsRjKN/hVbZOJj0gQ5zaYUjSg=="], - "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-ql6vJ611qoqRYHxkKPnb2vHa27U+YRKRmIpLMMBeZnfFtZ938eao7402AQCH1mO2+/8ioUhbpy9R/ZcLTXVmkg=="], + "@tauri-apps/cli-linux-arm64-gnu": ["@tauri-apps/cli-linux-arm64-gnu@2.9.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-pvbljdhp9VOo4RnID5ywSxgBs7qiylTPlK56cTk7InR3kYSTJKYMqv/4Q/4rGo/mG8cVppesKIeBMH42fw6wjg=="], - "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-vg7yNn7ICTi6hRrcA/6ff2UpZQP7un3xe3SEld5QM0prgridbKAiXGaCKr3BnUBx/rGXegQlD/wiLcWdiiraSw=="], + "@tauri-apps/cli-linux-arm64-musl": ["@tauri-apps/cli-linux-arm64-musl@2.9.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-02TKUndpodXBCR0oP//6dZWGYcc22Upf2eP27NvC6z0DIqvkBBFziQUcvi2n6SrwTRL0yGgQjkm9K5NIn8s6jw=="], - "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.9.4", "", { "os": "linux", "cpu": "none" }, "sha512-l8L+3VxNk6yv5T/Z/gv5ysngmIpsai40B9p6NQQyqYqxImqYX37pqREoEBl1YwG7szGnDibpWhidPrWKR59OJA=="], + "@tauri-apps/cli-linux-riscv64-gnu": ["@tauri-apps/cli-linux-riscv64-gnu@2.9.6", "", { "os": "linux", "cpu": "none" }, "sha512-fmp1hnulbqzl1GkXl4aTX9fV+ubHw2LqlLH1PE3BxZ11EQk+l/TmiEongjnxF0ie4kV8DQfDNJ1KGiIdWe1GvQ=="], - "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-PepPhCXc/xVvE3foykNho46OmCyx47E/aG676vKTVp+mqin5d+IBqDL6wDKiGNT5OTTxKEyNlCQ81Xs2BQhhqA=="], + "@tauri-apps/cli-linux-x64-gnu": ["@tauri-apps/cli-linux-x64-gnu@2.9.6", "", { "os": "linux", "cpu": "x64" }, "sha512-vY0le8ad2KaV1PJr+jCd8fUF9VOjwwQP/uBuTJvhvKTloEwxYA/kAjKK9OpIslGA9m/zcnSo74czI6bBrm2sYA=="], - "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-zcd1QVffh5tZs1u1SCKUV/V7RRynebgYUNWHuV0FsIF1MjnULUChEXhAhug7usCDq4GZReMJOoXa6rukEozWIw=="], + "@tauri-apps/cli-linux-x64-musl": ["@tauri-apps/cli-linux-x64-musl@2.9.6", "", { "os": "linux", "cpu": "x64" }, "sha512-TOEuB8YCFZTWVDzsO2yW0+zGcoMiPPwcUgdnW1ODnmgfwccpnihDRoks+ABT1e3fHb1ol8QQWsHSCovb3o2ENQ=="], - "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-/7ZhnP6PY04bEob23q8MH/EoDISdmR1wuNm0k9d5HV7TDMd2GGCDa8dPXA4vJuglJKXIfXqxFmZ4L+J+MO42+w=="], + "@tauri-apps/cli-win32-arm64-msvc": ["@tauri-apps/cli-win32-arm64-msvc@2.9.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-ujmDGMRc4qRLAnj8nNG26Rlz9klJ0I0jmZs2BPpmNNf0gM/rcVHhqbEkAaHPTBVIrtUdf7bGvQAD2pyIiUrBHQ=="], - "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.9.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-1LmAfaC4Cq+3O1Ir1ksdhczhdtFSTIV51tbAGtbV/mr348O+M52A/xwCCXQank0OcdBxy5BctqkMtuZnQvA8uQ=="], + "@tauri-apps/cli-win32-ia32-msvc": ["@tauri-apps/cli-win32-ia32-msvc@2.9.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-S4pT0yAJgFX8QRCyKA1iKjZ9Q/oPjCZf66A/VlG5Yw54Nnr88J1uBpmenINbXxzyhduWrIXBaUbEY1K80ZbpMg=="], - "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-EdYd4c9wGvtPB95kqtEyY+bUR+k4kRw3IA30mAQ1jPH6z57AftT8q84qwv0RDp6kkEqOBKxeInKfqi4BESYuqg=="], + "@tauri-apps/cli-win32-x64-msvc": ["@tauri-apps/cli-win32-x64-msvc@2.9.6", "", { "os": "win32", "cpu": "x64" }, "sha512-ldWuWSSkWbKOPjQMJoYVj9wLHcOniv7diyI5UAJ4XsBdtaFB0pKHQsqw/ItUma0VXGC7vB4E9fZjivmxur60aw=="], - "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-lNIn5CZuw8WZOn8zHzmFmDSzg5zfohWoa3mdULP0YFh/VogVdMVWZPcWSHlydsiJhRQYaTNSYKN7RmZKE2lCYQ=="], + "@tauri-apps/plugin-dialog": ["@tauri-apps/plugin-dialog@2.6.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg=="], - "@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.5.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-/i4U/9za3mrytTgfRn5RHneKubZE/dwRmshYwyMvNRlkWjvu1m4Ma72kcbVJMZFGXpkbl+qLyWMGrihtWB76Zg=="], + "@tauri-apps/plugin-http": ["@tauri-apps/plugin-http@2.5.6", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-KhCK3TDNDF4vdz75/j+KNQipYKf+295Visa8r32QcXScg0+D3JwShcCM6D+FN8WuDF24X3KSiAB8QtRxW6jKRA=="], "@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="], - "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew=="], + "@tauri-apps/plugin-opener": ["@tauri-apps/plugin-opener@2.5.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ=="], "@tauri-apps/plugin-os": ["@tauri-apps/plugin-os@2.3.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-n+nXWeuSeF9wcEsSPmRnBEGrRgOy6jjkSU+UVCOV8YUGKb2erhDOxis7IqRXiRVHhY8XMKks00BJ0OAdkpf6+A=="], "@tauri-apps/plugin-process": ["@tauri-apps/plugin-process@2.3.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-nCa4fGVaDL/B9ai03VyPOjfAHRHSBz5v6F/ObsB73r/dA3MHHhZtldaDMIc0V/pnUw9ehzr2iEG+XkSEyC0JJA=="], - "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Xod+pRcFxmOWFWEnqH5yZcA7qwAMuaaDkMR1Sply+F8VfBj++CGnj2xf5UoialmjZ2Cvd8qrvSCbU+7GgNVsKQ=="], + "@tauri-apps/plugin-shell": ["@tauri-apps/plugin-shell@2.3.4", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ktsRWf8wHLD17aZEyqE8c5x98eNAuTizR1FSX475zQ4TxaiJnhwksLygQz+AGwckJL5bfEP13nWrlTNQJUpKpA=="], - "@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.1", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-ckGSEzZ5Ii4Hf2D5x25Oqnm2Zf9MfDWAzR+volY0z/OOBz6aucPKEY0F649JvQ0Vupku6UJo7ugpGRDOFOunkA=="], + "@tauri-apps/plugin-store": ["@tauri-apps/plugin-store@2.4.2", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-0ClHS50Oq9HEvLPhNzTNFxbWVOqoAp3dRvtewQBeqfIQ0z5m3JRnOISIn2ZVPCrQC0MyGyhTS9DWhHjpigQE7A=="], "@tauri-apps/plugin-updater": ["@tauri-apps/plugin-updater@2.9.0", "", { "dependencies": { "@tauri-apps/api": "^2.6.0" } }, "sha512-j++sgY8XpeDvzImTrzWA08OqqGqgkNyxczLD7FjNJJx/uXxMZFz5nDcfkyoI/rCjYuj2101Tci/r/HFmOmoxCg=="], @@ -1882,7 +1887,7 @@ "@types/express": ["@types/express@4.17.25", "", { "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "^1" } }, "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw=="], - "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.7", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-FvPtiIf1LfhzsaIXhv/PHan/2FeQBbtBDtfX2QfvPxdUelMDEckK08SM6nqo1MIZY3RUlfA+HV8+hFUSio78qg=="], + "@types/express-serve-static-core": ["@types/express-serve-static-core@4.19.8", "", { "dependencies": { "@types/node": "*", "@types/qs": "*", "@types/range-parser": "*", "@types/send": "*" } }, "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA=="], "@types/fontkit": ["@types/fontkit@2.0.8", "", { "dependencies": { "@types/node": "*" } }, "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew=="], @@ -1934,7 +1939,7 @@ "@types/scheduler": ["@types/scheduler@0.26.0", "", {}, "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA=="], - "@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="], + "@types/send": ["@types/send@1.2.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ=="], "@types/serve-static": ["@types/serve-static@1.15.10", "", { "dependencies": { "@types/http-errors": "*", "@types/node": "*", "@types/send": "<1" } }, "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw=="], @@ -1950,7 +1955,7 @@ "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], - "@types/ws": ["@types/ws@7.4.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@types/yargs": ["@types/yargs@17.0.33", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA=="], @@ -1982,19 +1987,19 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - "@vitest/expect": ["@vitest/expect@4.0.16", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.16", "@vitest/utils": "4.0.16", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA=="], + "@vitest/expect": ["@vitest/expect@4.0.18", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ=="], - "@vitest/mocker": ["@vitest/mocker@4.0.16", "", { "dependencies": { "@vitest/spy": "4.0.16", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-yb6k4AZxJTB+q9ycAvsoxGn+j/po0UaPgajllBgt1PzoMAAmJGYFdDk0uCcRcxb3BrME34I6u8gHZTQlkqSZpg=="], + "@vitest/mocker": ["@vitest/mocker@4.0.18", "", { "dependencies": { "@vitest/spy": "4.0.18", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.0.16", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-eNCYNsSty9xJKi/UdVD8Ou16alu7AYiS2fCPRs0b1OdhJiV89buAXQLpTbe+X8V9L6qrs9CqyvU7OaAopJYPsA=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.0.18", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw=="], - "@vitest/runner": ["@vitest/runner@4.0.16", "", { "dependencies": { "@vitest/utils": "4.0.16", "pathe": "^2.0.3" } }, "sha512-VWEDm5Wv9xEo80ctjORcTQRJ539EGPB3Pb9ApvVRAY1U/WkHXmmYISqU5E79uCwcW7xYUV38gwZD+RV755fu3Q=="], + "@vitest/runner": ["@vitest/runner@4.0.18", "", { "dependencies": { "@vitest/utils": "4.0.18", "pathe": "^2.0.3" } }, "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw=="], - "@vitest/snapshot": ["@vitest/snapshot@4.0.16", "", { "dependencies": { "@vitest/pretty-format": "4.0.16", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-sf6NcrYhYBsSYefxnry+DR8n3UV4xWZwWxYbCJUt2YdvtqzSPR7VfGrY0zsv090DAbjFZsi7ZaMi1KnSRyK1XA=="], + "@vitest/snapshot": ["@vitest/snapshot@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA=="], - "@vitest/spy": ["@vitest/spy@4.0.16", "", {}, "sha512-4jIOWjKP0ZUaEmJm00E0cOBLU+5WE0BpeNr3XN6TEF05ltro6NJqHWxXD0kA8/Zc8Nh23AT8WQxwNG+WeROupw=="], + "@vitest/spy": ["@vitest/spy@4.0.18", "", {}, "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw=="], - "@vitest/utils": ["@vitest/utils@4.0.16", "", { "dependencies": { "@vitest/pretty-format": "4.0.16", "tinyrainbow": "^3.0.3" } }, "sha512-h8z9yYhV3e1LEfaQ3zdypIrnAg/9hguReGZoS7Gl0aBG5xgA410zBqECqmaF/+RkTggRsfnzc1XaAHA6bmUufA=="], + "@vitest/utils": ["@vitest/utils@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "tinyrainbow": "^3.0.3" } }, "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA=="], "@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="], @@ -2070,7 +2075,7 @@ "astro": ["astro@5.7.13", "", { "dependencies": { "@astrojs/compiler": "^2.11.0", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.1", "@astrojs/telemetry": "3.2.1", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-cRGq2llKOhV3XMcYwQpfBIUcssN6HEK5CRbcMxAfd9OcFhvWE7KUy50zLioAZVVl3AqgUTJoNTlmZfD2eG0G1w=="], - "astro-expressive-code": ["astro-expressive-code@0.41.3", "", { "dependencies": { "rehype-expressive-code": "^0.41.3" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" } }, "sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw=="], + "astro-expressive-code": ["astro-expressive-code@0.41.6", "", { "dependencies": { "rehype-expressive-code": "^0.41.6" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, "sha512-l47tb1uhmVIebHUkw+HEPtU/av0G4O8Q34g2cbkPvC7/e9ZhANcjUUciKt9Hp6gSVDdIuXBBLwJQn2LkeGMOAw=="], "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], @@ -2078,7 +2083,7 @@ "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], - "autoprefixer": ["autoprefixer@10.4.22", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-lite": "^1.0.30001754", "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg=="], + "autoprefixer": ["autoprefixer@10.4.23", "", { "dependencies": { "browserslist": "^4.28.1", "caniuse-lite": "^1.0.30001760", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA=="], "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], @@ -2090,13 +2095,13 @@ "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], - "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], + "axios": ["axios@1.13.4", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "b4a": ["b4a@1.7.3", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q=="], - "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.10", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA=="], + "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="], "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.3", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-5HOwwt0BYiv/zxl7j8Pf2bGL6rDXfV6nUhLs8ygBX+EFJXzBPHM/euj9j/6deMZ6wa52Wb2PBaAV5U/jKwIY1w=="], @@ -2134,7 +2139,7 @@ "bmp-ts": ["bmp-ts@1.0.9", "", {}, "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw=="], - "body-parser": ["body-parser@2.2.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.0", "http-errors": "^2.0.0", "iconv-lite": "^0.6.3", "on-finished": "^2.4.1", "qs": "^6.14.0", "raw-body": "^3.0.0", "type-is": "^2.0.0" } }, "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg=="], + "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], @@ -2142,7 +2147,7 @@ "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="], - "bowser": ["bowser@2.12.1", "", {}, "sha512-z4rE2Gxh7tvshQ4hluIT7XcFrgLIQaw9X3A+kTTRdovCz5PMukm/0QC/BKSYPj3omF5Qfypn9O/c5kgpmvYUCw=="], + "bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="], "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], @@ -2152,7 +2157,7 @@ "brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="], - "browserslist": ["browserslist@4.28.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", "electron-to-chromium": "^1.5.249", "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ=="], + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], "buffer": ["buffer@4.9.2", "", { "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg=="], @@ -2198,11 +2203,11 @@ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001756", "", {}, "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A=="], + "caniuse-lite": ["caniuse-lite@1.0.30001766", "", {}, "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - "chai": ["chai@6.2.1", "", {}, "sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg=="], + "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "chainsaw": ["chainsaw@0.1.0", "", { "dependencies": { "traverse": ">=0.3.0 <0.4" } }, "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ=="], @@ -2236,7 +2241,7 @@ "cli-boxes": ["cli-boxes@3.0.0", "", {}, "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g=="], - "cli-spinners": ["cli-spinners@3.3.0", "", {}, "sha512-/+40ljC3ONVnYIttjMWrlL51nItDAbBrq2upN8BPyvGU/2n5Oxw3tbNwORCaNuNqLJnxGqOfjUuhsv7l5Q4IsQ=="], + "cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="], "clipboardy": ["clipboardy@4.0.0", "", { "dependencies": { "execa": "^8.0.1", "is-wsl": "^3.1.0", "is64bit": "^2.0.0" } }, "sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w=="], @@ -2248,8 +2253,6 @@ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], - "cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="], - "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], @@ -2286,7 +2289,7 @@ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], - "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + "cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="], "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], @@ -2294,7 +2297,7 @@ "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], - "cors": ["cors@2.8.5", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g=="], + "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], @@ -2304,11 +2307,11 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - "crossws": ["crossws@0.4.1", "", { "peerDependencies": { "srvx": ">=0.7.1" }, "optionalPeers": ["srvx"] }, "sha512-E7WKBcHVhAVrY6JYD5kteNqVq1GSZxqGrdSiwXR9at+XHi43HJoCQKXcCczR5LBnBquFZPsB3o7HklulKoBU5w=="], + "crossws": ["crossws@0.4.4", "", { "peerDependencies": { "srvx": ">=0.7.1" }, "optionalPeers": ["srvx"] }, "sha512-w6c4OdpRNnudVmcgr7brb/+/HmYjMQvYToO/oTrprTwxRUiom3LYWU1PMWuD006okbUWpII1Ea9/+kwpUfmyRg=="], "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], - "css-selector-parser": ["css-selector-parser@3.2.0", "", {}, "sha512-L1bdkNKUP5WYxiW5dW6vA2hd3sL8BdRNLy2FCX0rLVise4eNw9nBdeBuJHxlELieSE2H1f6bYQFfwVUwWCV9rQ=="], + "css-selector-parser": ["css-selector-parser@3.3.0", "", {}, "sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g=="], "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="], @@ -2332,7 +2335,7 @@ "decimal.js": ["decimal.js@10.5.0", "", {}, "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw=="], - "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], @@ -2368,7 +2371,7 @@ "deterministic-object-hash": ["deterministic-object-hash@2.0.2", "", { "dependencies": { "base-64": "^1.0.0" } }, "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ=="], - "devalue": ["devalue@5.5.0", "", {}, "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w=="], + "devalue": ["devalue@5.6.2", "", {}, "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], @@ -2418,7 +2421,7 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "electron-to-chromium": ["electron-to-chromium@1.5.259", "", {}, "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.282", "", {}, "sha512-FCPkJtpst28UmFzd903iU7PdeVTfY0KAeJy+Lk0GLZRwgwYHn/irRcaCbQQOmr5Vytc/7rcavsYLvTM8RiHYhQ=="], "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], @@ -2430,7 +2433,7 @@ "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], - "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], + "enhanced-resolve": ["enhanced-resolve@5.18.4", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q=="], "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], @@ -2440,7 +2443,7 @@ "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], - "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="], + "es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="], "es-array-method-boxes-properly": ["es-array-method-boxes-properly@1.0.0", "", {}, "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="], @@ -2462,7 +2465,7 @@ "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="], - "esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], "esbuild-plugin-copy": ["esbuild-plugin-copy@2.1.1", "", { "dependencies": { "chalk": "^4.1.2", "chokidar": "^3.5.3", "fs-extra": "^10.0.1", "globby": "^11.0.3" }, "peerDependencies": { "esbuild": ">= 0.14.0" } }, "sha512-Bk66jpevTcV8KMFzZI1P7MZKZ+uDcrZm2G2egZ2jNIvVnivDpodZI+/KnpL3Jnap0PBdIHU7HwFGB8r+vV5CVw=="], @@ -2494,7 +2497,7 @@ "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], - "eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="], + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], @@ -2512,11 +2515,11 @@ "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], - "express": ["express@5.1.0", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.0", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA=="], + "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], "express-rate-limit": ["express-rate-limit@7.5.1", "", { "peerDependencies": { "express": ">= 4.11" } }, "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw=="], - "expressive-code": ["expressive-code@0.41.3", "", { "dependencies": { "@expressive-code/core": "^0.41.3", "@expressive-code/plugin-frames": "^0.41.3", "@expressive-code/plugin-shiki": "^0.41.3", "@expressive-code/plugin-text-markers": "^0.41.3" } }, "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg=="], + "expressive-code": ["expressive-code@0.41.6", "", { "dependencies": { "@expressive-code/core": "^0.41.6", "@expressive-code/plugin-frames": "^0.41.6", "@expressive-code/plugin-shiki": "^0.41.6", "@expressive-code/plugin-text-markers": "^0.41.6" } }, "sha512-W/5+IQbrpCIM5KGLjO35wlp1NCwDOOVQb+PAvzEoGkW1xjGM807ZGfBKptNWH6UECvt6qgmLyWolCMYKh7eQmA=="], "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], @@ -2536,7 +2539,7 @@ "fast-xml-parser": ["fast-xml-parser@4.4.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw=="], - "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], @@ -2546,7 +2549,7 @@ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], - "finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="], + "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], "find-babel-config": ["find-babel-config@2.1.2", "", { "dependencies": { "json5": "^2.2.3" } }, "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg=="], @@ -2662,7 +2665,7 @@ "h3": ["h3@2.0.1-rc.4", "", { "dependencies": { "rou3": "^0.7.8", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-vZq8pEUp6THsXKXrUXX44eOqfChic2wVQ1GlSzQCBr7DeFBkfIZAo2WyNND4GSv54TAa0E4LYIK73WSPdgKUgw=="], - "happy-dom": ["happy-dom@20.0.11", "", { "dependencies": { "@types/node": "^20.0.0", "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" } }, "sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g=="], + "happy-dom": ["happy-dom@20.4.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^4.5.0", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-RDeQm3dT9n0A5f/TszjUmNCLEuPnMGv3Tv4BmNINebz/h17PA6LMBcxJ5FrcqltNBMh9jA/8ufgDdBYUdBt+eg=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], @@ -2710,7 +2713,7 @@ "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="], - "hast-util-to-parse5": ["hast-util-to-parse5@8.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw=="], + "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="], "hast-util-to-string": ["hast-util-to-string@3.0.1", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A=="], @@ -2760,7 +2763,7 @@ "i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="], - "iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], + "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ieee754": ["ieee754@1.1.13", "", {}, "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="], @@ -2780,8 +2783,6 @@ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], - "ioredis": ["ioredis@5.8.2", "", { "dependencies": { "@ioredis/commands": "1.4.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q=="], - "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], @@ -2930,11 +2931,11 @@ "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], - "jsonwebtoken": ["jsonwebtoken@9.0.2", "", { "dependencies": { "jws": "^3.2.2", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ=="], + "jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="], "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], - "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], "jwt-decode": ["jwt-decode@3.1.2", "", {}, "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="], @@ -2982,14 +2983,10 @@ "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - - "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], + "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], "lodash.includes": ["lodash.includes@4.3.0", "", {}, "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w=="], - "lodash.isarguments": ["lodash.isarguments@3.1.0", "", {}, "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="], - "lodash.isboolean": ["lodash.isboolean@3.0.3", "", {}, "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg=="], "lodash.isinteger": ["lodash.isinteger@4.0.4", "", {}, "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA=="], @@ -3068,7 +3065,7 @@ "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], - "mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="], + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="], "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], @@ -3196,7 +3193,7 @@ "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], - "named-placeholders": ["named-placeholders@1.1.3", "", { "dependencies": { "lru-cache": "^7.14.1" } }, "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w=="], + "named-placeholders": ["named-placeholders@1.1.6", "", { "dependencies": { "lru.min": "^1.1.0" } }, "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w=="], "nanoevents": ["nanoevents@7.0.1", "", {}, "sha512-o6lpKiCxLeijK4hgsqfR6CNToPyRU3keKyyI6uwuHRvpRTbZ0wXw51WRgyldVugZqoJfkGFrjrIenYH3bfEO3Q=="], @@ -3224,9 +3221,9 @@ "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], - "node-html-parser": ["node-html-parser@7.0.1", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-KGtmPY2kS0thCWGK0VuPyOS+pBKhhe8gXztzA2ilAOhbUbxa9homF1bOyKvhGzMLXUoRds9IOmr/v5lr/lqNmA=="], + "node-html-parser": ["node-html-parser@7.0.2", "", { "dependencies": { "css-select": "^5.1.0", "he": "1.2.0" } }, "sha512-DxodLVh7a6JMkYzWyc8nBX9MaF4M0lLFYkJHlWOiu7+9/I6mwNK9u5TbAMC7qfqDJEPX9OIoWA2A9t4C2l1mUQ=="], - "node-mock-http": ["node-mock-http@1.0.3", "", {}, "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog=="], + "node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="], "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], @@ -3234,13 +3231,11 @@ "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], - "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], - "npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + "nypm": ["nypm@0.6.4", "", { "dependencies": { "citty": "^0.2.0", "pathe": "^2.0.3", "tinyexec": "^1.0.2" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-1TvCKjZyyklN+JJj2TS3P4uSQEInrM/HkkuSXsEzm1ApPgBffOn8gFguNnZf07r/1X6vlryfIqMUkJKQMzlZiw=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -3308,7 +3303,7 @@ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "package-manager-detector": ["package-manager-detector@1.5.0", "", {}, "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw=="], + "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], "pagefind": ["pagefind@1.4.0", "", { "optionalDependencies": { "@pagefind/darwin-arm64": "1.4.0", "@pagefind/darwin-x64": "1.4.0", "@pagefind/freebsd-x64": "1.4.0", "@pagefind/linux-arm64": "1.4.0", "@pagefind/linux-x64": "1.4.0", "@pagefind/windows-x64": "1.4.0" }, "bin": { "pagefind": "lib/runner/bin.cjs" } }, "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g=="], @@ -3356,7 +3351,7 @@ "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], - "perfect-debounce": ["perfect-debounce@2.0.0", "", {}, "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow=="], + "perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="], "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], @@ -3434,7 +3429,7 @@ "punycode": ["punycode@1.3.2", "", {}, "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="], - "qs": ["qs@6.14.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w=="], + "qs": ["qs@6.14.1", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ=="], "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], @@ -3484,13 +3479,9 @@ "recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="], - "redis-errors": ["redis-errors@1.2.0", "", {}, "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="], - - "redis-parser": ["redis-parser@3.0.0", "", { "dependencies": { "redis-errors": "^1.0.0" } }, "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A=="], - "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], - "regex": ["regex@6.0.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA=="], + "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="], @@ -3502,7 +3493,7 @@ "rehype-autolink-headings": ["rehype-autolink-headings@7.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-heading-rank": "^3.0.0", "hast-util-is-element": "^3.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw=="], - "rehype-expressive-code": ["rehype-expressive-code@0.41.3", "", { "dependencies": { "expressive-code": "^0.41.3" } }, "sha512-8d9Py4c/V6I/Od2VIXFAdpiO2kc0SV2qTJsRAaqSIcM9aruW4ASLNe2kOEo1inXAAkIhpFzAHTc358HKbvpNUg=="], + "rehype-expressive-code": ["rehype-expressive-code@0.41.6", "", { "dependencies": { "expressive-code": "^0.41.6" } }, "sha512-aBMX8kxPtjmDSFUdZlAWJkMvsQ4ZMASfee90JWIAV8tweltXLzkWC3q++43ToTelI8ac5iC0B3/S/Cl4Ql1y2g=="], "rehype-format": ["rehype-format@5.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-format": "^1.0.0" } }, "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ=="], @@ -3560,9 +3551,9 @@ "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], - "rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="], + "rollup": ["rollup@4.57.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.0", "@rollup/rollup-android-arm64": "4.57.0", "@rollup/rollup-darwin-arm64": "4.57.0", "@rollup/rollup-darwin-x64": "4.57.0", "@rollup/rollup-freebsd-arm64": "4.57.0", "@rollup/rollup-freebsd-x64": "4.57.0", "@rollup/rollup-linux-arm-gnueabihf": "4.57.0", "@rollup/rollup-linux-arm-musleabihf": "4.57.0", "@rollup/rollup-linux-arm64-gnu": "4.57.0", "@rollup/rollup-linux-arm64-musl": "4.57.0", "@rollup/rollup-linux-loong64-gnu": "4.57.0", "@rollup/rollup-linux-loong64-musl": "4.57.0", "@rollup/rollup-linux-ppc64-gnu": "4.57.0", "@rollup/rollup-linux-ppc64-musl": "4.57.0", "@rollup/rollup-linux-riscv64-gnu": "4.57.0", "@rollup/rollup-linux-riscv64-musl": "4.57.0", "@rollup/rollup-linux-s390x-gnu": "4.57.0", "@rollup/rollup-linux-x64-gnu": "4.57.0", "@rollup/rollup-linux-x64-musl": "4.57.0", "@rollup/rollup-openbsd-x64": "4.57.0", "@rollup/rollup-openharmony-arm64": "4.57.0", "@rollup/rollup-win32-arm64-msvc": "4.57.0", "@rollup/rollup-win32-ia32-msvc": "4.57.0", "@rollup/rollup-win32-x64-gnu": "4.57.0", "@rollup/rollup-win32-x64-msvc": "4.57.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-e5lPJi/aui4TO1LpAXIRLySmwXSE8k3b9zoGfd42p67wzxog4WHjiZF3M2uheQih4DGyc25QEV4yRBbpueNiUA=="], - "rou3": ["rou3@0.7.10", "", {}, "sha512-aoFj6f7MJZ5muJ+Of79nrhs9N3oLGqi2VEMe94Zbkjb6Wupha46EuoYgpWSOZlXww3bbd8ojgXTAA2mzimX5Ww=="], + "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], @@ -3592,7 +3583,7 @@ "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - "send": ["send@1.2.0", "", { "dependencies": { "debug": "^4.3.5", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.0", "mime-types": "^3.0.1", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.1" } }, "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw=="], + "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], "seq-queue": ["seq-queue@0.0.5", "", {}, "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="], @@ -3600,7 +3591,7 @@ "seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], - "serve-static": ["serve-static@2.2.0", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ=="], + "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], @@ -3644,7 +3635,7 @@ "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - "smol-toml": ["smol-toml@1.5.2", "", {}, "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ=="], + "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], "socket.io-client": ["socket.io-client@4.8.3", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-client": "~6.6.1", "socket.io-parser": "~4.2.4" } }, "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g=="], @@ -3676,7 +3667,7 @@ "sqlstring": ["sqlstring@2.3.3", "", {}, "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg=="], - "srvx": ["srvx@0.9.6", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-5L4rT6qQqqb+xcoDoklUgCNdmzqJ6vbcDRwPVGRXewF55IJH0pqh0lQlrJ266ZWTKJ4mfeioqHQJeAYesS+RrQ=="], + "srvx": ["srvx@0.9.8", "", { "bin": { "srvx": "bin/srvx.mjs" } }, "sha512-RZaxTKJEE/14HYn8COLuUOJAt0U55N9l1Xf6jj+T0GoA01EUH1Xz5JtSUOI+EHn+AEgPCVn7gk6jHJffrr06fQ=="], "sst": ["sst@3.17.23", "", { "dependencies": { "aws-sdk": "2.1692.0", "aws4fetch": "1.0.18", "jose": "5.2.3", "opencontrol": "0.0.6", "openid-client": "5.6.4" }, "optionalDependencies": { "sst-darwin-arm64": "3.17.23", "sst-darwin-x64": "3.17.23", "sst-linux-arm64": "3.17.23", "sst-linux-x64": "3.17.23", "sst-linux-x86": "3.17.23", "sst-win32-arm64": "3.17.23", "sst-win32-x64": "3.17.23", "sst-win32-x86": "3.17.23" }, "bin": { "sst": "bin/sst.mjs" } }, "sha512-TwKgUgDnZdc1Swe+bvCNeyO4dQnYz5cTodMpYj3jlXZdK9/KNz0PVxT1f0u5E76i1pmilXrUBL/f7iiMPw4RDg=="], @@ -3700,9 +3691,7 @@ "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], - "stage-js": ["stage-js@1.0.0-alpha.17", "", {}, "sha512-AzlMO+t51v6cFvKZ+Oe9DJnL1OXEH5s9bEy6di5aOrUpcP7PCzI/wIeXF0u3zg0L89gwnceoKxrLId0ZpYnNXw=="], - - "standard-as-callback": ["standard-as-callback@2.1.0", "", {}, "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="], + "stage-js": ["stage-js@1.0.0-alpha.18", "", {}, "sha512-Mh+pbkfxA6NXlDrcutP8vp1Zg04pDRcC8D39UXKZzEcQeBPOZ4SRUSkIsF26aoODUZ4CSQRY7shXc1Avb0wZKA=="], "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], @@ -3762,13 +3751,13 @@ "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], - "tar": ["tar@7.5.2", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg=="], + "tar": ["tar@7.5.7", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ=="], "tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="], - "terracotta": ["terracotta@1.0.6", "", { "dependencies": { "solid-use": "^0.9.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-yVrmT/Lg6a3tEbeYEJH8ksb1PYkR5FA9k5gr1TchaSNIiA2ZWs5a+koEbePXwlBP0poaV7xViZ/v50bQFcMgqw=="], + "terracotta": ["terracotta@1.1.0", "", { "dependencies": { "solid-use": "^0.9.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww=="], - "terser": ["terser@5.44.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw=="], + "terser": ["terser@5.46.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], "text-decoder": ["text-decoder@1.2.3", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA=="], @@ -3860,7 +3849,7 @@ "typescript": ["typescript@5.8.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ=="], - "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="], "ulid": ["ulid@3.0.1", "", { "bin": { "ulid": "dist/cli.js" } }, "sha512-dPJyqPzx8preQhqq24bBG1YNkvigm87K8kVEHCD+ruZg24t6IFEFv00xMWfxcC4djmFtiTLdFuADn4+DOz6R7Q=="], @@ -3898,7 +3887,7 @@ "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], - "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], "unist-util-visit-children": ["unist-util-visit-children@3.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA=="], @@ -3912,11 +3901,11 @@ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "unstorage": ["unstorage@2.0.0-alpha.4", "", { "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4.0.3", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "lru-cache": "^11.2.2", "mongodb": "^6.20.0", "ofetch": "*", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-ywXZMZRfrvmO1giJeMTCw6VUn0ALYxVl8pFqJPStiyQUvgJImejtAHrKvXPj4QGJAoS/iLGcVGF6ljN/lkh1bw=="], + "unstorage": ["unstorage@2.0.0-alpha.5", "", { "peerDependencies": { "@azure/app-configuration": "^1.9.0", "@azure/cosmos": "^4.7.0", "@azure/data-tables": "^13.3.1", "@azure/identity": "^4.13.0", "@azure/keyvault-secrets": "^4.10.0", "@azure/storage-blob": "^12.29.1", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.12.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.35.6", "@vercel/blob": ">=0.27.3", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "chokidar": "^4 || ^5", "db0": ">=0.3.4", "idb-keyval": "^6.2.2", "ioredis": "^5.8.2", "lru-cache": "^11.2.2", "mongodb": "^6 || ^7", "ofetch": "*", "uploadthing": "^7.7.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "chokidar", "db0", "idb-keyval", "ioredis", "lru-cache", "mongodb", "ofetch", "uploadthing"] }, "sha512-Sj8btci21Twnd6M+N+MHhjg3fVn6lAPElPmvFTe0Y/wR0WImErUdA1PzlAaUavHylJ7uDiFwlZDQKm0elG4b7g=="], "unzip-stream": ["unzip-stream@0.3.4", "", { "dependencies": { "binary": "^0.3.0", "mkdirp": "^0.5.1" } }, "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw=="], - "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "url": ["url@0.10.3", "", { "dependencies": { "punycode": "1.3.2", "querystring": "0.2.0" } }, "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ=="], @@ -3954,7 +3943,7 @@ "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], - "vitest": ["vitest@4.0.16", "", { "dependencies": { "@vitest/expect": "4.0.16", "@vitest/mocker": "4.0.16", "@vitest/pretty-format": "4.0.16", "@vitest/runner": "4.0.16", "@vitest/snapshot": "4.0.16", "@vitest/spy": "4.0.16", "@vitest/utils": "4.0.16", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.16", "@vitest/browser-preview": "4.0.16", "@vitest/browser-webdriverio": "4.0.16", "@vitest/ui": "4.0.16", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-E4t7DJ9pESL6E3I8nFjPa4xGUd3PmiWDLsDztS2qXSJWfHtbQnwAWylaBvSNY48I3vr8PTqIZlyK8TE3V3CA4Q=="], + "vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="], "vscode-jsonrpc": ["vscode-jsonrpc@8.2.1", "", {}, "sha512-kdjOSJ2lLIn7r1rtrMbbNCHjyMPfRnowdKjBQ+mGq6NAW5QY2bEZC/khaC5OR8svbbjvLEaIXkOq45e2X9BIbQ=="], @@ -3982,7 +3971,7 @@ "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="], - "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + "which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="], "why-is-node-running": ["why-is-node-running@3.2.2", "", { "bin": { "why-is-node-running": "cli.js" } }, "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A=="], @@ -4000,7 +3989,7 @@ "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], - "wsl-utils": ["wsl-utils@0.3.0", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ=="], + "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], "xdg-basedir": ["xdg-basedir@5.1.0", "", {}, "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ=="], @@ -4018,7 +4007,7 @@ "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], + "yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="], "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], @@ -4046,36 +4035,32 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@actions/artifact/@actions/core": ["@actions/core@2.0.1", "", { "dependencies": { "@actions/exec": "^2.0.0", "@actions/http-client": "^3.0.0" } }, "sha512-oBfqT3GwkvLlo1fjvhQLQxuwZCGTarTE5OuZ2Wg10hvhBj7LRIlF611WT4aZS6fDhO5ZKlY7lCAZTlpmyaHaeg=="], + "@actions/artifact/@actions/core": ["@actions/core@2.0.3", "", { "dependencies": { "@actions/exec": "^2.0.0", "@actions/http-client": "^3.0.2" } }, "sha512-Od9Thc3T1mQJYddvVPM4QGiLUewdh+3txmDYHHxoNdkqysR1MbCT+rFOtNUxYAz+7+6RIsqipVahY2GJqGPyxA=="], "@actions/core/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], "@actions/github/@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="], - "@ai-sdk/amazon-bedrock/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.5", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA=="], + "@actions/http-client/undici": ["undici@6.23.0", "", {}, "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g=="], "@astrojs/cloudflare/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - "@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "@astrojs/markdown-remark/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], - - "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.9", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.5", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.13.0", "smol-toml": "^1.4.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng=="], + "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.10", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.5", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.19.0", "smol-toml": "^1.5.2", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A=="], "@astrojs/sitemap/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "@astrojs/solid-js/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], - "@astrojs/starlight/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "@astrojs/starlight/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], "@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@aws-crypto/sha256-js/@aws-sdk/types": ["@aws-sdk/types@3.775.0", "", { "dependencies": { "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZoGKwa4C9fC9Av6bdfqcW6Ix5ot05F/S4VxWR2nHuMv7hzfmAjTOcUiWT7UR4hM/U0whf84VhDtXN/DWAk52KA=="], - "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], "@aws-sdk/client-sts/@aws-sdk/core": ["@aws-sdk/core@3.775.0", "", { "dependencies": { "@aws-sdk/types": "3.775.0", "@smithy/core": "^3.2.0", "@smithy/node-config-provider": "^4.0.2", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/signature-v4": "^5.0.2", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/util-middleware": "^4.0.2", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" } }, "sha512-8vpW4WihVfz0DX+7WnnLGm3GuQER++b0IwQG35JlQMlgqnc44M//KbJPsIHA0aJUJVwJAEShgfr5dUbY8WUzaA=="], @@ -4128,9 +4113,7 @@ "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], - "@expressive-code/plugin-shiki/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], - - "@gitlab/gitlab-ai-provider/openai": ["openai@6.16.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-fZ1uBqjFUjXzbGc35fFtYKEOxd20kd9fDpFeqWtsOZWiubY8CZ1NAlXHW3iathaFvqmNtCWMIsosCuyeI7Joxg=="], + "@gitlab/gitlab-ai-provider/openai": ["openai@6.17.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-NHRpPEUPzAvFOAFs9+9pC6+HCw/iWsYsKCMPXH5Kw7BpMxqd8g/A07/1o7Gx2TWtCnzevVRyKMRFqyiHyAlqcA=="], "@gitlab/gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -4278,7 +4261,7 @@ "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], - "@shikijs/core/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], + "@shikijs/core/@shikijs/types": ["@shikijs/types@3.21.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA=="], "@shikijs/engine-javascript/@shikijs/types": ["@shikijs/types@3.19.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-Z2hdeEQlzuntf/BZpFG8a+Fsw9UVXdML7w0o3TgSXV3yNESGon+bs9ITkQb3Ki7zxoXOOu5oJWqZ2uto06V9iQ=="], @@ -4290,16 +4273,18 @@ "@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.9.2", "", { "dependencies": { "@shikijs/types": "3.9.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-3q/mzmw09B2B6PgFNeiaN8pkNOixWS726IHmJEpjDAcneDPMQmUg2cweT9cWXY4XcyQS3i6mOOUgQz9RRUP6HA=="], - "@slack/bolt/express": ["express@4.21.2", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "0.19.0", "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA=="], + "@slack/bolt/express": ["express@4.22.1", "", { "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", "body-parser": "~1.20.3", "content-disposition": "~0.5.4", "content-type": "~1.0.4", "cookie": "~0.7.1", "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "finalhandler": "~1.3.1", "fresh": "~0.5.2", "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", "send": "~0.19.0", "serve-static": "~1.16.2", "setprototypeof": "1.2.0", "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" } }, "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g=="], "@slack/bolt/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], - "@slack/bolt/raw-body": ["raw-body@2.5.2", "", { "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA=="], + "@slack/bolt/raw-body": ["raw-body@2.5.3", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "unpipe": "~1.0.0" } }, "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA=="], "@slack/oauth/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], "@slack/socket-mode/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], + "@slack/socket-mode/@types/ws": ["@types/ws@7.4.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww=="], + "@slack/socket-mode/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "@slack/web-api/@slack/logger": ["@slack/logger@3.0.0", "", { "dependencies": { "@types/node": ">=12.0.0" } }, "sha512-DTuBFbqu4gGfajREEMrkq5jBhcnskinhr4+AnfJEk48zhVeEv3XnUKGIX98B74kxhYsIMfApGGySTn7V3b5yBA=="], @@ -4312,11 +4297,7 @@ "@slack/web-api/p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="], - "@smithy/eventstream-codec/@smithy/types": ["@smithy/types@4.11.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA=="], - - "@smithy/eventstream-serde-universal/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.5", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.9.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA=="], - - "@solidjs/start/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "@smithy/eventstream-serde-universal/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.8", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.12.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-jS/O5Q14UsufqoGhov7dHLOPCzkYJl9QDzusI2Psh4wyYx/izhzvX9P4D69aTxcdfVhEPhjK+wYyn/PzLjKbbw=="], "@solidjs/start/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], @@ -4326,9 +4307,9 @@ "@tailwindcss/oxide/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], @@ -4338,6 +4319,12 @@ "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@tanstack/directive-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@tanstack/server-functions-plugin/@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="], + + "@types/serve-static/@types/send": ["@types/send@0.17.6", "", { "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og=="], + "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -4348,15 +4335,11 @@ "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - "astro/diff": ["diff@5.2.0", "", {}, "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A=="], + "astro/diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="], - "astro/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "astro/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "astro/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - - "astro/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], - - "astro/unstorage": ["unstorage@1.17.3", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.1" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q=="], + "astro/unstorage": ["unstorage@1.17.4", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.5", "lru-cache": "^11.2.0", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw=="], "astro/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], @@ -4364,17 +4347,15 @@ "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "astro/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + "aws-sdk/events": ["events@1.1.1", "", {}, "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="], "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], - "body-parser/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "browserslist/baseline-browser-mapping": ["baseline-browser-mapping@2.8.30", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA=="], - - "bun-webgpu/@webgpu/types": ["@webgpu/types@0.1.66", "", {}, "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA=="], + "bun-webgpu/@webgpu/types": ["@webgpu/types@0.1.69", "", {}, "sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -4392,8 +4373,6 @@ "editorconfig/minimatch": ["minimatch@9.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w=="], - "editorconfig/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - "engine.io-client/ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="], "es-get-iterator/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -4410,24 +4389,18 @@ "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "gel/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - "gel/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], "glob/minimatch": ["minimatch@10.1.1", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ=="], "globby/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], - "hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], + "happy-dom/ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="], "html-minifier-terser/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], - "jsonwebtoken/jws": ["jws@3.2.2", "", { "dependencies": { "jwa": "^1.4.1", "safe-buffer": "^5.0.1" } }, "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA=="], - - "jsonwebtoken/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], - "katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -4448,14 +4421,14 @@ "miniflare/zod": ["zod@3.22.3", "", {}, "sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug=="], - "named-placeholders/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], - "nitro/h3": ["h3@2.0.1-rc.5", "", { "dependencies": { "rou3": "^0.7.9", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg=="], - "nitro/undici": ["undici@7.16.0", "", {}, "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g=="], + "nitro/undici": ["undici@7.19.2", "", {}, "sha512-4VQSpGEGsWzk0VYxyB/wVX/Q7qf9t5znLRgs0dzszr9w9Fej/8RVNQ+S20vdXSAyra/bJ7ZQfGv6ZMj7UEbzSg=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + "nypm/citty": ["citty@0.2.0", "", {}, "sha512-8csy5IBFI2ex2hTVpaHN2j+LNE199AgiI7y4dMintrr8i0lQiFn+0AWMZrWdHKIgMOer65f8IThysYhoReqjWA=="], + "nypm/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], "opencontrol/@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.6.1", "", { "dependencies": { "content-type": "^1.0.5", "cors": "^2.8.5", "eventsource": "^3.0.2", "express": "^5.0.1", "express-rate-limit": "^7.5.0", "pkce-challenge": "^4.1.0", "raw-body": "^3.0.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.24.1" } }, "sha512-oxzMzYCkZHMntzuyerehK3fV6A2Kwh5BD6CGEJSVDU2QNEhfLOptf2X7esQgaHZXHZY0oHmMsOtIDLP71UJXgA=="], @@ -4478,7 +4451,7 @@ "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], - "path-scurry/lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], + "path-scurry/lru-cache": ["lru-cache@11.2.5", "", {}, "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="], "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], @@ -4504,13 +4477,13 @@ "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "sharp/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + "shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], "shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], "shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], - "sitemap/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], + "sitemap/sax": ["sax@1.4.4", "", {}, "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw=="], "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], @@ -4542,8 +4515,6 @@ "unifont/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], - "vite-plugin-solid/babel-preset-solid": ["babel-preset-solid@1.9.10", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.3" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.10" }, "optionalPeers": ["solid-js"] }, "sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ=="], - "vitest/tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="], "vitest/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], @@ -4552,14 +4523,14 @@ "which-builtin-type/isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "xml2js/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], - "zod-to-json-schema/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], "zod-to-ts/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -4568,25 +4539,11 @@ "@astrojs/markdown-remark/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], - - "@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], - - "@astrojs/markdown-remark/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA=="], - - "@astrojs/markdown-remark/shiki/@shikijs/langs": ["@shikijs/langs@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A=="], - - "@astrojs/markdown-remark/shiki/@shikijs/themes": ["@shikijs/themes@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ=="], - - "@astrojs/markdown-remark/shiki/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.5", "", {}, "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA=="], "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="], - "@astrojs/mdx/@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki": ["shiki@3.15.0", "", { "dependencies": { "@shikijs/core": "3.15.0", "@shikijs/engine-javascript": "3.15.0", "@shikijs/engine-oniguruma": "3.15.0", "@shikijs/langs": "3.15.0", "@shikijs/themes": "3.15.0", "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw=="], + "@astrojs/mdx/@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], "@astrojs/starlight/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -4608,11 +4565,9 @@ "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.782.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/nested-clients": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xCna0opVPaueEbJoclj5C6OpDNi0Gynj+4d7tnuXGgQhTHPyAz8ZyClkVqpi5qvHTgxROdUEDxWqEO5jqRHZHQ=="], - "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], + "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], - "@azure/core-http/xml2js/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], - - "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.1.1", "", {}, "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw=="], + "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="], "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], @@ -4660,18 +4615,6 @@ "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], - "@expressive-code/plugin-shiki/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/langs": ["@shikijs/langs@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/themes": ["@shikijs/themes@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ=="], - - "@expressive-code/plugin-shiki/shiki/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - "@hey-api/json-schema-ref-parser/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -4834,38 +4777,30 @@ "@slack/bolt/express/accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - "@slack/bolt/express/body-parser": ["body-parser@1.20.3", "", { "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" } }, "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g=="], + "@slack/bolt/express/body-parser": ["body-parser@1.20.4", "", { "dependencies": { "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "~1.2.0", "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", "qs": "~6.14.0", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" } }, "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA=="], "@slack/bolt/express/content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="], - "@slack/bolt/express/cookie": ["cookie@0.7.1", "", {}, "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w=="], + "@slack/bolt/express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], - "@slack/bolt/express/cookie-signature": ["cookie-signature@1.0.6", "", {}, "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="], + "@slack/bolt/express/cookie-signature": ["cookie-signature@1.0.7", "", {}, "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA=="], "@slack/bolt/express/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], - "@slack/bolt/express/finalhandler": ["finalhandler@1.3.1", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" } }, "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ=="], + "@slack/bolt/express/finalhandler": ["finalhandler@1.3.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "~2.4.1", "parseurl": "~1.3.3", "statuses": "~2.0.2", "unpipe": "~1.0.0" } }, "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg=="], "@slack/bolt/express/fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], - "@slack/bolt/express/http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], - "@slack/bolt/express/merge-descriptors": ["merge-descriptors@1.0.3", "", {}, "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ=="], "@slack/bolt/express/path-to-regexp": ["path-to-regexp@0.1.12", "", {}, "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ=="], - "@slack/bolt/express/qs": ["qs@6.13.0", "", { "dependencies": { "side-channel": "^1.0.6" } }, "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg=="], + "@slack/bolt/express/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], - "@slack/bolt/express/send": ["send@0.19.0", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "2.4.1", "range-parser": "~1.2.1", "statuses": "2.0.1" } }, "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw=="], - - "@slack/bolt/express/serve-static": ["serve-static@1.16.2", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "0.19.0" } }, "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw=="], - - "@slack/bolt/express/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], + "@slack/bolt/express/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], "@slack/bolt/express/type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], - "@slack/bolt/raw-body/http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], - "@slack/bolt/raw-body/iconv-lite": ["iconv-lite@0.4.24", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], "@slack/web-api/form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], @@ -4874,56 +4809,6 @@ "@slack/web-api/p-queue/p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="], - "@solidjs/start/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "@solidjs/start/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "@solidjs/start/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "@solidjs/start/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "@solidjs/start/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "@solidjs/start/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "@solidjs/start/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "@solidjs/start/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "@solidjs/start/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "@solidjs/start/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "@solidjs/start/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "@solidjs/start/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "@solidjs/start/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "@solidjs/start/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "@solidjs/start/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "@solidjs/start/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "@solidjs/start/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "@solidjs/start/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "@solidjs/start/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "@solidjs/start/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "@solidjs/start/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "@solidjs/start/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "@solidjs/start/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - - "@solidjs/start/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - - "@solidjs/start/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@solidjs/start/shiki/@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="], "@solidjs/start/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="], @@ -4950,21 +4835,11 @@ "astro/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "astro/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], + "astro/unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], - "astro/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], + "astro/unstorage/h3": ["h3@1.15.5", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg=="], - "astro/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA=="], - - "astro/shiki/@shikijs/langs": ["@shikijs/langs@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A=="], - - "astro/shiki/@shikijs/themes": ["@shikijs/themes@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ=="], - - "astro/shiki/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - - "astro/unstorage/h3": ["h3@1.15.4", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.2", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ=="], - - "astro/unstorage/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "astro/unstorage/lru-cache": ["lru-cache@11.2.5", "", {}, "sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw=="], "astro/unstorage/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], @@ -5034,8 +4909,6 @@ "js-beautify/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - "jsonwebtoken/jws/jwa": ["jwa@1.4.2", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw=="], - "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], @@ -5044,9 +4917,7 @@ "opencontrol/@modelcontextprotocol/sdk/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], - "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.24.5", "", { "peerDependencies": { "zod": "^3.24.1" } }, "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g=="], - - "parse-bmfont-xml/xml2js/sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], + "opencontrol/@modelcontextprotocol/sdk/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -5070,7 +4941,55 @@ "tw-to-css/tailwindcss/postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], - "vitest/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], + + "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], + + "wrangler/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.4", "", { "os": "android", "cpu": "arm64" }, "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A=="], + + "wrangler/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.4", "", { "os": "android", "cpu": "x64" }, "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ=="], + + "wrangler/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g=="], + + "wrangler/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A=="], + + "wrangler/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ=="], + + "wrangler/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ=="], + + "wrangler/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.4", "", { "os": "linux", "cpu": "arm" }, "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ=="], + + "wrangler/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ=="], + + "wrangler/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.4", "", { "os": "linux", "cpu": "ia32" }, "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ=="], + + "wrangler/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA=="], + + "wrangler/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg=="], + + "wrangler/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag=="], + + "wrangler/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.4", "", { "os": "linux", "cpu": "none" }, "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA=="], + + "wrangler/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g=="], + + "wrangler/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.4", "", { "os": "linux", "cpu": "x64" }, "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA=="], + + "wrangler/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.4", "", { "os": "none", "cpu": "arm64" }, "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ=="], + + "wrangler/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.4", "", { "os": "none", "cpu": "x64" }, "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw=="], + + "wrangler/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.4", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A=="], + + "wrangler/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw=="], + + "wrangler/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.4", "", { "os": "sunos", "cpu": "x64" }, "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q=="], + + "wrangler/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ=="], + + "wrangler/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg=="], + + "wrangler/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.4", "", { "os": "win32", "cpu": "x64" }, "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ=="], "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -5080,18 +4999,6 @@ "@astrojs/mdx/@astrojs/markdown-remark/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.3" } }, "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/langs": ["@shikijs/langs@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/themes": ["@shikijs/themes@3.15.0", "", { "dependencies": { "@shikijs/types": "3.15.0" } }, "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ=="], - - "@astrojs/mdx/@astrojs/markdown-remark/shiki/@shikijs/types": ["@shikijs/types@3.15.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw=="], - "@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], "@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], @@ -5164,6 +5071,12 @@ "@octokit/rest/@octokit/core/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@27.0.0", "", {}, "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA=="], + "@opencode-ai/console-function/@ai-sdk/anthropic/@ai-sdk/provider-utils/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + + "@opencode-ai/console-function/@ai-sdk/openai-compatible/@ai-sdk/provider-utils/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + + "@opencode-ai/console-function/@ai-sdk/openai/@ai-sdk/provider-utils/zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="], + "@slack/bolt/express/accepts/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "@slack/bolt/express/accepts/negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="], @@ -5172,16 +5085,12 @@ "@slack/bolt/express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@slack/bolt/express/send/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="], - "@slack/bolt/express/send/mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="], "@slack/bolt/express/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], "@slack/bolt/express/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], - "@slack/bolt/raw-body/http-errors/statuses": ["statuses@2.0.1", "", {}, "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="], - "@slack/web-api/form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="], @@ -5190,6 +5099,8 @@ "archiver-utils/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "astro/unstorage/chokidar/readdirp": ["readdirp@5.0.0", "", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + "astro/unstorage/h3/cookie-es": ["cookie-es@1.2.2", "", {}, "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg=="], "astro/unstorage/h3/crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], @@ -5210,56 +5121,6 @@ "tw-to-css/tailwindcss/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "vitest/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], - - "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], - - "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], - - "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], - - "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], - - "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], - - "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], - - "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], - - "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], - - "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], - - "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], - - "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], - - "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], - - "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], - - "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], - - "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], - - "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], - - "vitest/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], - - "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], - - "vitest/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], - - "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], - - "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], - - "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], - - "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], - - "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], - "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], "@jsx-email/cli/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], diff --git a/nix/hashes.json b/nix/hashes.json index faeef5c48d..7bf0ac8c59 100644 --- a/nix/hashes.json +++ b/nix/hashes.json @@ -1,8 +1,8 @@ { "nodeModules": { - "x86_64-linux": "sha256-iVeqbnW1I3Qk9J0GXWYN68FLwDQcNwxY+5bBUVXNilc=", - "aarch64-linux": "sha256-OF5APKxCY3DLxEMmhBRuJuUzDrL1nfLv2KcKUEwZ670=", - "aarch64-darwin": "sha256-F3HCMZdBBAEXkCiyx6npY/rrhEB7pjfL3Wf6dhUw+u8=", - "x86_64-darwin": "sha256-o88ZWXUfcKS7dbGH4JEprUMhfzxVBNKgWunC/0994UY=" + "x86_64-linux": "sha256-Rc3LrA/FBFM1V0ZszEnNjCjxxw5p/V8Mk3I6rKxNaJ0=", + "aarch64-linux": "sha256-IZQ9fAHf7R3P7/QpeMEnOTBgpY/rcc4TB+Gx5IQnsmg=", + "aarch64-darwin": "sha256-kCKFb59YLV9ydFS3NvlNHT6oce7YUODG0aZyO8Lh69I=", + "x86_64-darwin": "sha256-OhQNnMJqm5SkojLrnXeCN6LxDSxl3ZEe9XjEBnxe9Ys=" } } diff --git a/packages/app/e2e/file-tree.spec.ts b/packages/app/e2e/file-tree.spec.ts new file mode 100644 index 0000000000..c22a810f4f --- /dev/null +++ b/packages/app/e2e/file-tree.spec.ts @@ -0,0 +1,37 @@ +import { test, expect } from "./fixtures" + +test("file tree can expand folders and open a file", async ({ page, gotoSession }) => { + await gotoSession() + + const toggle = page.getByRole("button", { name: "Toggle file tree" }) + const treeTabs = page.locator('[data-component="tabs"][data-variant="pill"][data-scope="filetree"]') + + if ((await toggle.getAttribute("aria-expanded")) !== "true") await toggle.click() + await expect(treeTabs).toBeVisible() + + await treeTabs.locator('[data-slot="tabs-trigger"]').nth(1).click() + + const node = (name: string) => treeTabs.getByRole("button", { name, exact: true }) + + await expect(node("packages")).toBeVisible() + await node("packages").click() + + await expect(node("app")).toBeVisible() + await node("app").click() + + await expect(node("src")).toBeVisible() + await node("src").click() + + await expect(node("components")).toBeVisible() + await node("components").click() + + await expect(node("file-tree.tsx")).toBeVisible() + await node("file-tree.tsx").click() + + const tab = page.getByRole("tab", { name: "file-tree.tsx" }) + await expect(tab).toBeVisible() + await tab.click() + + const code = page.locator('[data-component="code"]').first() + await expect(code.getByText("export default function FileTree")).toBeVisible() +}) diff --git a/packages/app/e2e/fixtures.ts b/packages/app/e2e/fixtures.ts index 721d60049c..c5315ff194 100644 --- a/packages/app/e2e/fixtures.ts +++ b/packages/app/e2e/fixtures.ts @@ -1,5 +1,5 @@ import { test as base, expect } from "@playwright/test" -import { createSdk, dirSlug, getWorktree, promptSelector, sessionPath } from "./utils" +import { createSdk, dirSlug, getWorktree, promptSelector, serverUrl, sessionPath } from "./utils" type TestFixtures = { sdk: ReturnType @@ -29,6 +29,55 @@ export const test = base.extend({ await use(createSdk(directory)) }, gotoSession: async ({ page, directory }, use) => { + await page.addInitScript( + (input: { directory: string; serverUrl: string }) => { + const key = "opencode.global.dat:server" + const raw = localStorage.getItem(key) + const parsed = (() => { + if (!raw) return undefined + try { + return JSON.parse(raw) as unknown + } catch { + return undefined + } + })() + + const store = parsed && typeof parsed === "object" ? (parsed as Record) : {} + const list = Array.isArray(store.list) ? store.list : [] + const lastProject = store.lastProject && typeof store.lastProject === "object" ? store.lastProject : {} + const projects = store.projects && typeof store.projects === "object" ? store.projects : {} + const nextProjects = { ...(projects as Record) } + + const add = (origin: string) => { + const current = nextProjects[origin] + const items = Array.isArray(current) ? current : [] + const existing = items.filter( + (p): p is { worktree: string; expanded?: boolean } => + !!p && + typeof p === "object" && + "worktree" in p && + typeof (p as { worktree?: unknown }).worktree === "string", + ) + + if (existing.some((p) => p.worktree === input.directory)) return + nextProjects[origin] = [{ worktree: input.directory, expanded: true }, ...existing] + } + + add("local") + add(input.serverUrl) + + localStorage.setItem( + key, + JSON.stringify({ + list, + projects: nextProjects, + lastProject, + }), + ) + }, + { directory, serverUrl }, + ) + const gotoSession = async (sessionID?: string) => { await page.goto(sessionPath(directory, sessionID)) await expect(page.locator(promptSelector)).toBeVisible() diff --git a/packages/app/e2e/models-visibility.spec.ts b/packages/app/e2e/models-visibility.spec.ts new file mode 100644 index 0000000000..680ba96a31 --- /dev/null +++ b/packages/app/e2e/models-visibility.spec.ts @@ -0,0 +1,86 @@ +import { test, expect } from "./fixtures" +import { modKey, promptSelector } from "./utils" + +test("hiding a model removes it from the model picker", async ({ page, gotoSession }) => { + await gotoSession() + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + + const command = page.locator('[data-slash-id="model.choose"]') + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const picker = page.getByRole("dialog") + await expect(picker).toBeVisible() + + const target = picker.locator('[data-slot="list-item"]').first() + await expect(target).toBeVisible() + + const key = await target.getAttribute("data-key") + if (!key) throw new Error("Failed to resolve model key from list item") + + const name = (await target.locator("span").first().innerText()).trim() + if (!name) throw new Error("Failed to resolve model name from list item") + + await page.keyboard.press("Escape") + await expect(picker).toHaveCount(0) + + const settings = page.getByRole("dialog") + + await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined) + const opened = await settings + .waitFor({ state: "visible", timeout: 3000 }) + .then(() => true) + .catch(() => false) + + if (!opened) { + await page.getByRole("button", { name: "Settings" }).first().click() + await expect(settings).toBeVisible() + } + + await settings.getByRole("tab", { name: "Models" }).click() + const search = settings.getByPlaceholder("Search models") + await expect(search).toBeVisible() + await search.fill(name) + + const toggle = settings.locator('[data-component="switch"]').filter({ hasText: name }).first() + const input = toggle.locator('[data-slot="switch-input"]') + await expect(toggle).toBeVisible() + await expect(input).toHaveAttribute("aria-checked", "true") + await toggle.locator('[data-slot="switch-control"]').click() + await expect(input).toHaveAttribute("aria-checked", "false") + + await page.keyboard.press("Escape") + const closed = await settings + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + if (!closed) { + await page.keyboard.press("Escape") + const closedSecond = await settings + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + if (!closedSecond) { + await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } }) + await expect(settings).toHaveCount(0) + } + } + + await page.locator(promptSelector).click() + await page.keyboard.type("/model") + await expect(command).toBeVisible() + await command.hover() + await page.keyboard.press("Enter") + + const pickerAgain = page.getByRole("dialog") + await expect(pickerAgain).toBeVisible() + await expect(pickerAgain.locator('[data-slot="list-item"]').first()).toBeVisible() + + await expect(pickerAgain.locator(`[data-slot="list-item"][data-key="${key}"]`)).toHaveCount(0) + + await page.keyboard.press("Escape") + await expect(pickerAgain).toHaveCount(0) +}) diff --git a/packages/app/e2e/server-default.spec.ts b/packages/app/e2e/server-default.spec.ts new file mode 100644 index 0000000000..b6b16f0bcc --- /dev/null +++ b/packages/app/e2e/server-default.spec.ts @@ -0,0 +1,67 @@ +import { test, expect } from "./fixtures" +import { serverName, serverUrl } from "./utils" + +const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl" + +test("can set a default server on web", async ({ page, gotoSession }) => { + await page.addInitScript((key: string) => { + try { + localStorage.removeItem(key) + } catch { + return + } + }, DEFAULT_SERVER_URL_KEY) + + await gotoSession() + + const status = page.getByRole("button", { name: "Status" }) + await expect(status).toBeVisible() + const popover = page.locator('[data-component="popover-content"]').filter({ hasText: "Manage servers" }) + + const ensurePopoverOpen = async () => { + if (await popover.isVisible()) return + await status.click() + await expect(popover).toBeVisible() + } + + await ensurePopoverOpen() + await popover.getByRole("button", { name: "Manage servers" }).click() + + const dialog = page.getByRole("dialog") + await expect(dialog).toBeVisible() + + const row = dialog.locator('[data-slot="list-item"]').filter({ hasText: serverName }).first() + await expect(row).toBeVisible() + + const menu = row.locator('[data-component="icon-button"]').last() + await menu.click() + await page.getByRole("menuitem", { name: "Set as default" }).click() + + await expect.poll(() => page.evaluate((key) => localStorage.getItem(key), DEFAULT_SERVER_URL_KEY)).toBe(serverUrl) + await expect(row.getByText("Default", { exact: true })).toBeVisible() + + await page.keyboard.press("Escape") + const closed = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (!closed) { + await page.keyboard.press("Escape") + const closedSecond = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + + if (!closedSecond) { + await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } }) + await expect(dialog).toHaveCount(0) + } + } + + await ensurePopoverOpen() + + const serverRow = popover.locator("button").filter({ hasText: serverName }).first() + await expect(serverRow).toBeVisible() + await expect(serverRow.getByText("Default", { exact: true })).toBeVisible() +}) diff --git a/packages/app/e2e/settings-providers.spec.ts b/packages/app/e2e/settings-providers.spec.ts new file mode 100644 index 0000000000..326a9fad1d --- /dev/null +++ b/packages/app/e2e/settings-providers.spec.ts @@ -0,0 +1,56 @@ +import { test, expect } from "./fixtures" +import { modKey, promptSelector } from "./utils" + +test("smoke providers settings opens provider selector", async ({ page, gotoSession }) => { + await gotoSession() + + const dialog = page.getByRole("dialog") + + await page.keyboard.press(`${modKey}+Comma`).catch(() => undefined) + + const opened = await dialog + .waitFor({ state: "visible", timeout: 3000 }) + .then(() => true) + .catch(() => false) + + if (!opened) { + await page.getByRole("button", { name: "Settings" }).first().click() + await expect(dialog).toBeVisible() + } + + await dialog.getByRole("tab", { name: "Providers" }).click() + await expect(dialog.getByText("Connected providers", { exact: true })).toBeVisible() + await expect(dialog.getByText("Popular providers", { exact: true })).toBeVisible() + + await dialog.getByRole("button", { name: "Show more providers" }).click() + + const providerDialog = page.getByRole("dialog").filter({ has: page.getByPlaceholder("Search providers") }) + + await expect(providerDialog).toBeVisible() + await expect(providerDialog.getByPlaceholder("Search providers")).toBeVisible() + await expect(providerDialog.locator('[data-slot="list-item"]').first()).toBeVisible() + + await page.keyboard.press("Escape") + await expect(providerDialog).toHaveCount(0) + await expect(page.locator(promptSelector)).toBeVisible() + + const stillOpen = await dialog.isVisible().catch(() => false) + if (!stillOpen) return + + await page.keyboard.press("Escape") + const closed = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + if (closed) return + + await page.keyboard.press("Escape") + const closedSecond = await dialog + .waitFor({ state: "detached", timeout: 1500 }) + .then(() => true) + .catch(() => false) + if (closedSecond) return + + await page.locator('[data-component="dialog-overlay"]').click({ position: { x: 5, y: 5 } }) + await expect(dialog).toHaveCount(0) +}) diff --git a/packages/app/e2e/sidebar-session-links.spec.ts b/packages/app/e2e/sidebar-session-links.spec.ts new file mode 100644 index 0000000000..fab64736e2 --- /dev/null +++ b/packages/app/e2e/sidebar-session-links.spec.ts @@ -0,0 +1,61 @@ +import { test, expect } from "./fixtures" +import { modKey, promptSelector } from "./utils" + +type Locator = { + first: () => Locator + getAttribute: (name: string) => Promise + scrollIntoViewIfNeeded: () => Promise + click: () => Promise +} + +type Page = { + locator: (selector: string) => Locator + keyboard: { + press: (key: string) => Promise + } +} + +type Fixtures = { + page: Page + slug: string + sdk: { + session: { + create: (input: { title: string }) => Promise<{ data?: { id?: string } }> + delete: (input: { sessionID: string }) => Promise + } + } + gotoSession: (sessionID?: string) => Promise +} + +test("sidebar session links navigate to the selected session", async ({ page, slug, sdk, gotoSession }: Fixtures) => { + const stamp = Date.now() + + const one = await sdk.session.create({ title: `e2e sidebar nav 1 ${stamp}` }).then((r) => r.data) + const two = await sdk.session.create({ title: `e2e sidebar nav 2 ${stamp}` }).then((r) => r.data) + + if (!one?.id) throw new Error("Session create did not return an id") + if (!two?.id) throw new Error("Session create did not return an id") + + try { + await gotoSession(one.id) + + const main = page.locator("main") + const collapsed = ((await main.getAttribute("class")) ?? "").includes("xl:border-l") + if (collapsed) { + await page.keyboard.press(`${modKey}+B`) + await expect(main).not.toHaveClass(/xl:border-l/) + } + + const target = page.locator(`[data-session-id="${two.id}"] a`).first() + await expect(target).toBeVisible() + await target.scrollIntoViewIfNeeded() + await target.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + await expect(page.locator(`[data-session-id="${two.id}"] a`).first()).toHaveClass(/\bactive\b/) + } finally { + await sdk.session.delete({ sessionID: one.id }).catch(() => undefined) + await sdk.session.delete({ sessionID: two.id }).catch(() => undefined) + } +}) diff --git a/packages/app/e2e/titlebar-history.spec.ts b/packages/app/e2e/titlebar-history.spec.ts new file mode 100644 index 0000000000..d4aa605e6d --- /dev/null +++ b/packages/app/e2e/titlebar-history.spec.ts @@ -0,0 +1,52 @@ +import { test, expect } from "./fixtures" +import { modKey, promptSelector } from "./utils" + +test("titlebar back/forward navigates between sessions", async ({ page, slug, sdk, gotoSession }) => { + await page.setViewportSize({ width: 1400, height: 800 }) + + const stamp = Date.now() + const one = await sdk.session.create({ title: `e2e titlebar history 1 ${stamp}` }).then((r) => r.data) + const two = await sdk.session.create({ title: `e2e titlebar history 2 ${stamp}` }).then((r) => r.data) + + if (!one?.id) throw new Error("Session create did not return an id") + if (!two?.id) throw new Error("Session create did not return an id") + + try { + await gotoSession(one.id) + + const main = page.locator("main") + const collapsed = ((await main.getAttribute("class")) ?? "").includes("xl:border-l") + if (collapsed) { + await page.keyboard.press(`${modKey}+B`) + await expect(main).not.toHaveClass(/xl:border-l/) + } + + const link = page.locator(`[data-session-id="${two.id}"] a`).first() + await expect(link).toBeVisible() + await link.scrollIntoViewIfNeeded() + await link.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + const back = page.getByRole("button", { name: "Back" }) + const forward = page.getByRole("button", { name: "Forward" }) + + await expect(back).toBeVisible() + await expect(back).toBeEnabled() + await back.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${one.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + + await expect(forward).toBeVisible() + await expect(forward).toBeEnabled() + await forward.click() + + await expect(page).toHaveURL(new RegExp(`/${slug}/session/${two.id}(?:\\?|#|$)`)) + await expect(page.locator(promptSelector)).toBeVisible() + } finally { + await sdk.session.delete({ sessionID: one.id }).catch(() => undefined) + await sdk.session.delete({ sessionID: two.id }).catch(() => undefined) + } +}) diff --git a/packages/app/package.json b/packages/app/package.json index 5deeed0215..4471c8987b 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/app", - "version": "1.1.36", + "version": "1.1.42", "description": "", "type": "module", "exports": { diff --git a/packages/app/src/app.tsx b/packages/app/src/app.tsx index d5009c8d1d..ba0d1e7aa4 100644 --- a/packages/app/src/app.tsx +++ b/packages/app/src/app.tsx @@ -14,22 +14,22 @@ import { GlobalSyncProvider } from "@/context/global-sync" import { PermissionProvider } from "@/context/permission" import { LayoutProvider } from "@/context/layout" import { GlobalSDKProvider } from "@/context/global-sdk" -import { ServerProvider, useServer } from "@/context/server" +import { normalizeServerUrl, ServerProvider, useServer } from "@/context/server" import { SettingsProvider } from "@/context/settings" import { TerminalProvider } from "@/context/terminal" import { PromptProvider } from "@/context/prompt" import { FileProvider } from "@/context/file" import { CommentsProvider } from "@/context/comments" import { NotificationProvider } from "@/context/notification" +import { ModelsProvider } from "@/context/models" import { DialogProvider } from "@opencode-ai/ui/context/dialog" import { CommandProvider } from "@/context/command" import { LanguageProvider, useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" -import { Logo } from "@opencode-ai/ui/logo" +import { HighlightsProvider } from "@/context/highlights" import Layout from "@/pages/layout" import DirectoryLayout from "@/pages/directory-layout" import { ErrorPage } from "./pages/error" -import { iife } from "@opencode-ai/util/iife" import { Suspense } from "solid-js" const Home = lazy(() => import("@/pages/home")) @@ -85,8 +85,19 @@ function ServerKey(props: ParentProps) { } export function AppInterface(props: { defaultUrl?: string }) { + const platform = usePlatform() + + const stored = (() => { + if (platform.platform !== "web") return + const result = platform.getDefaultServerUrl?.() + if (result instanceof Promise) return + if (!result) return + return normalizeServerUrl(result) + })() + const defaultServerUrl = () => { if (props.defaultUrl) return props.defaultUrl + if (stored) return stored if (location.hostname.includes("opencode.ai")) return "http://localhost:4096" if (import.meta.env.DEV) return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}` @@ -105,9 +116,13 @@ export function AppInterface(props: { defaultUrl?: string }) { - - {props.children} - + + + + {props.children} + + + diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index c8bf4ff238..e629505915 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -27,6 +27,17 @@ export function DialogConnectProvider(props: { provider: string }) { const globalSDK = useGlobalSDK() const platform = usePlatform() const language = useLanguage() + + const alive = { value: true } + const timer = { current: undefined as ReturnType | undefined } + + onCleanup(() => { + alive.value = false + if (timer.current === undefined) return + clearTimeout(timer.current) + timer.current = undefined + }) + const provider = createMemo(() => globalSync.data.provider.all.find((x) => x.id === props.provider)!) const methods = createMemo( () => @@ -53,6 +64,11 @@ export function DialogConnectProvider(props: { provider: string }) { } async function selectMethod(index: number) { + if (timer.current !== undefined) { + clearTimeout(timer.current) + timer.current = undefined + } + const method = methods()[index] setStore( produce((draft) => { @@ -75,11 +91,15 @@ export function DialogConnectProvider(props: { provider: string }) { { throwOnError: true }, ) .then((x) => { + if (!alive.value) return const elapsed = Date.now() - start const delay = 1000 - elapsed if (delay > 0) { - setTimeout(() => { + if (timer.current !== undefined) clearTimeout(timer.current) + timer.current = setTimeout(() => { + timer.current = undefined + if (!alive.value) return setStore("state", "complete") setStore("authorization", x.data!) }, delay) @@ -89,6 +109,7 @@ export function DialogConnectProvider(props: { provider: string }) { setStore("authorization", x.data!) }) .catch((e) => { + if (!alive.value) return setStore("state", "error") setStore("error", String(e)) }) @@ -374,26 +395,33 @@ export function DialogConnectProvider(props: { provider: string }) { return instructions }) - onMount(async () => { - if (store.authorization?.url) { - platform.openLink(store.authorization.url) - } - const result = await globalSDK.client.provider.oauth - .callback({ - providerID: props.provider, - method: store.methodIndex, - }) - .then((value) => - value.error ? { ok: false as const, error: value.error } : { ok: true as const }, - ) - .catch((error) => ({ ok: false as const, error })) - if (!result.ok) { - const message = result.error instanceof Error ? result.error.message : String(result.error) - setStore("state", "error") - setStore("error", message) - return - } - await complete() + onMount(() => { + void (async () => { + if (store.authorization?.url) { + platform.openLink(store.authorization.url) + } + + const result = await globalSDK.client.provider.oauth + .callback({ + providerID: props.provider, + method: store.methodIndex, + }) + .then((value) => + value.error ? { ok: false as const, error: value.error } : { ok: true as const }, + ) + .catch((error) => ({ ok: false as const, error })) + + if (!alive.value) return + + if (!result.ok) { + const message = result.error instanceof Error ? result.error.message : String(result.error) + setStore("state", "error") + setStore("error", message) + return + } + + await complete() + })() }) return ( diff --git a/packages/app/src/components/dialog-custom-provider.tsx b/packages/app/src/components/dialog-custom-provider.tsx new file mode 100644 index 0000000000..28a947f3b3 --- /dev/null +++ b/packages/app/src/components/dialog-custom-provider.tsx @@ -0,0 +1,424 @@ +import { Button } from "@opencode-ai/ui/button" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { Dialog } from "@opencode-ai/ui/dialog" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { ProviderIcon } from "@opencode-ai/ui/provider-icon" +import { TextField } from "@opencode-ai/ui/text-field" +import { showToast } from "@opencode-ai/ui/toast" +import { For } from "solid-js" +import { createStore, produce } from "solid-js/store" +import { Link } from "@/components/link" +import { useGlobalSDK } from "@/context/global-sdk" +import { useGlobalSync } from "@/context/global-sync" +import { useLanguage } from "@/context/language" +import { DialogSelectProvider } from "./dialog-select-provider" + +const PROVIDER_ID = /^[a-z0-9][a-z0-9-_]*$/ +const OPENAI_COMPATIBLE = "@ai-sdk/openai-compatible" + +type Props = { + back?: "providers" | "close" +} + +export function DialogCustomProvider(props: Props) { + const dialog = useDialog() + const globalSync = useGlobalSync() + const globalSDK = useGlobalSDK() + const language = useLanguage() + + const [form, setForm] = createStore({ + providerID: "", + name: "", + baseURL: "", + apiKey: "", + models: [{ id: "", name: "" }], + headers: [{ key: "", value: "" }], + saving: false, + }) + + const [errors, setErrors] = createStore({ + providerID: undefined as string | undefined, + name: undefined as string | undefined, + baseURL: undefined as string | undefined, + models: [{} as { id?: string; name?: string }], + headers: [{} as { key?: string; value?: string }], + }) + + const goBack = () => { + if (props.back === "close") { + dialog.close() + return + } + dialog.show(() => ) + } + + const addModel = () => { + setForm( + "models", + produce((draft) => { + draft.push({ id: "", name: "" }) + }), + ) + setErrors( + "models", + produce((draft) => { + draft.push({}) + }), + ) + } + + const removeModel = (index: number) => { + if (form.models.length <= 1) return + setForm( + "models", + produce((draft) => { + draft.splice(index, 1) + }), + ) + setErrors( + "models", + produce((draft) => { + draft.splice(index, 1) + }), + ) + } + + const addHeader = () => { + setForm( + "headers", + produce((draft) => { + draft.push({ key: "", value: "" }) + }), + ) + setErrors( + "headers", + produce((draft) => { + draft.push({}) + }), + ) + } + + const removeHeader = (index: number) => { + if (form.headers.length <= 1) return + setForm( + "headers", + produce((draft) => { + draft.splice(index, 1) + }), + ) + setErrors( + "headers", + produce((draft) => { + draft.splice(index, 1) + }), + ) + } + + const validate = () => { + const providerID = form.providerID.trim() + const name = form.name.trim() + const baseURL = form.baseURL.trim() + const apiKey = form.apiKey.trim() + + const env = apiKey.match(/^\{env:([^}]+)\}$/)?.[1]?.trim() + const key = apiKey && !env ? apiKey : undefined + + const idError = !providerID + ? "Provider ID is required" + : !PROVIDER_ID.test(providerID) + ? "Use lowercase letters, numbers, hyphens, or underscores" + : undefined + + const nameError = !name ? "Display name is required" : undefined + const urlError = !baseURL + ? "Base URL is required" + : !/^https?:\/\//.test(baseURL) + ? "Must start with http:// or https://" + : undefined + + const disabled = (globalSync.data.config.disabled_providers ?? []).includes(providerID) + const existingProvider = globalSync.data.provider.all.find((p) => p.id === providerID) + const existsError = idError + ? undefined + : existingProvider && !disabled + ? "That provider ID already exists" + : undefined + + const seenModels = new Set() + const modelErrors = form.models.map((m) => { + const id = m.id.trim() + const modelIdError = !id + ? "Required" + : seenModels.has(id) + ? "Duplicate" + : (() => { + seenModels.add(id) + return undefined + })() + const modelNameError = !m.name.trim() ? "Required" : undefined + return { id: modelIdError, name: modelNameError } + }) + const modelsValid = modelErrors.every((m) => !m.id && !m.name) + const models = Object.fromEntries(form.models.map((m) => [m.id.trim(), { name: m.name.trim() }])) + + const seenHeaders = new Set() + const headerErrors = form.headers.map((h) => { + const key = h.key.trim() + const value = h.value.trim() + + if (!key && !value) return {} + const keyError = !key + ? "Required" + : seenHeaders.has(key.toLowerCase()) + ? "Duplicate" + : (() => { + seenHeaders.add(key.toLowerCase()) + return undefined + })() + const valueError = !value ? "Required" : undefined + return { key: keyError, value: valueError } + }) + const headersValid = headerErrors.every((h) => !h.key && !h.value) + const headers = Object.fromEntries( + form.headers + .map((h) => ({ key: h.key.trim(), value: h.value.trim() })) + .filter((h) => !!h.key && !!h.value) + .map((h) => [h.key, h.value]), + ) + + setErrors( + produce((draft) => { + draft.providerID = idError ?? existsError + draft.name = nameError + draft.baseURL = urlError + draft.models = modelErrors + draft.headers = headerErrors + }), + ) + + const ok = !idError && !existsError && !nameError && !urlError && modelsValid && headersValid + if (!ok) return + + const options = { + baseURL, + ...(Object.keys(headers).length ? { headers } : {}), + } + + return { + providerID, + name, + key, + config: { + npm: OPENAI_COMPATIBLE, + name, + ...(env ? { env: [env] } : {}), + options, + models, + }, + } + } + + const save = async (e: SubmitEvent) => { + e.preventDefault() + if (form.saving) return + + const result = validate() + if (!result) return + + setForm("saving", true) + + const disabledProviders = globalSync.data.config.disabled_providers ?? [] + const nextDisabled = disabledProviders.filter((id) => id !== result.providerID) + + const auth = result.key + ? globalSDK.client.auth.set({ + providerID: result.providerID, + auth: { + type: "api", + key: result.key, + }, + }) + : Promise.resolve() + + auth + .then(() => + globalSync.updateConfig({ provider: { [result.providerID]: result.config }, disabled_providers: nextDisabled }), + ) + .then(() => { + dialog.close() + showToast({ + variant: "success", + icon: "circle-check", + title: language.t("provider.connect.toast.connected.title", { provider: result.name }), + description: language.t("provider.connect.toast.connected.description", { provider: result.name }), + }) + }) + .catch((err: unknown) => { + const message = err instanceof Error ? err.message : String(err) + showToast({ title: language.t("common.requestFailed"), description: message }) + }) + .finally(() => { + setForm("saving", false) + }) + } + + return ( + + } + transition + > +
+
+ +
Custom provider
+
+ +
+

+ Configure an OpenAI-compatible provider. See the{" "} + + provider config docs + + . +

+ +
+ + + + +
+ +
+ + + {(m, i) => ( +
+
+ setForm("models", i(), "id", v)} + validationState={errors.models[i()]?.id ? "invalid" : undefined} + error={errors.models[i()]?.id} + /> +
+
+ setForm("models", i(), "name", v)} + validationState={errors.models[i()]?.name ? "invalid" : undefined} + error={errors.models[i()]?.name} + /> +
+ removeModel(i())} + disabled={form.models.length <= 1} + aria-label="Remove model" + /> +
+ )} +
+ +
+ +
+ + + {(h, i) => ( +
+
+ setForm("headers", i(), "key", v)} + validationState={errors.headers[i()]?.key ? "invalid" : undefined} + error={errors.headers[i()]?.key} + /> +
+
+ setForm("headers", i(), "value", v)} + validationState={errors.headers[i()]?.value ? "invalid" : undefined} + error={errors.headers[i()]?.value} + /> +
+ removeHeader(i())} + disabled={form.headers.length <= 1} + aria-label="Remove header" + /> +
+ )} +
+ +
+ + +
+
+
+ ) +} diff --git a/packages/app/src/components/dialog-edit-project.tsx b/packages/app/src/components/dialog-edit-project.tsx index 9e2bddc6be..490753e622 100644 --- a/packages/app/src/components/dialog-edit-project.tsx +++ b/packages/app/src/components/dialog-edit-project.tsx @@ -3,7 +3,7 @@ import { useDialog } from "@opencode-ai/ui/context/dialog" import { Dialog } from "@opencode-ai/ui/dialog" import { TextField } from "@opencode-ai/ui/text-field" import { Icon } from "@opencode-ai/ui/icon" -import { createMemo, createSignal, For, Show } from "solid-js" +import { createMemo, For, Show } from "solid-js" import { createStore } from "solid-js/store" import { useGlobalSDK } from "@/context/global-sdk" import { useGlobalSync } from "@/context/global-sync" @@ -29,35 +29,34 @@ export function DialogEditProject(props: { project: LocalProject }) { iconUrl: props.project.icon?.override || "", startup: props.project.commands?.start ?? "", saving: false, + dragOver: false, + iconHover: false, }) - const [dragOver, setDragOver] = createSignal(false) - const [iconHover, setIconHover] = createSignal(false) - function handleFileSelect(file: File) { if (!file.type.startsWith("image/")) return const reader = new FileReader() reader.onload = (e) => { setStore("iconUrl", e.target?.result as string) - setIconHover(false) + setStore("iconHover", false) } reader.readAsDataURL(file) } function handleDrop(e: DragEvent) { e.preventDefault() - setDragOver(false) + setStore("dragOver", false) const file = e.dataTransfer?.files[0] if (file) handleFileSelect(file) } function handleDragOver(e: DragEvent) { e.preventDefault() - setDragOver(true) + setStore("dragOver", true) } function handleDragLeave() { - setDragOver(false) + setStore("dragOver", false) } function handleInputChange(e: Event) { @@ -116,19 +115,23 @@ export function DialogEditProject(props: { project: LocalProject }) {
-
setIconHover(true)} onMouseLeave={() => setIconHover(false)}> +
setStore("iconHover", true)} + onMouseLeave={() => setStore("iconHover", false)} + >
{ - if (store.iconUrl && iconHover()) { + if (store.iconUrl && store.iconHover) { clearIcon() } else { document.getElementById("icon-upload")?.click() @@ -142,8 +145,7 @@ export function DialogEditProject(props: { project: LocalProject }) {
} @@ -156,39 +158,19 @@ export function DialogEditProject(props: { project: LocalProject }) {
diff --git a/packages/app/src/components/dialog-fork.tsx b/packages/app/src/components/dialog-fork.tsx index 45329751c7..da1126e8e0 100644 --- a/packages/app/src/components/dialog-fork.tsx +++ b/packages/app/src/components/dialog-fork.tsx @@ -90,12 +90,8 @@ export const DialogFork: Component = () => { > {(item) => (
- - {item.text} - - - {item.time} - + {item.text} + {item.time}
)} diff --git a/packages/app/src/components/dialog-manage-models.tsx b/packages/app/src/components/dialog-manage-models.tsx index dad29b4dc3..9b50fe020f 100644 --- a/packages/app/src/components/dialog-manage-models.tsx +++ b/packages/app/src/components/dialog-manage-models.tsx @@ -1,16 +1,33 @@ import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { Switch } from "@opencode-ai/ui/switch" +import { Button } from "@opencode-ai/ui/button" import type { Component } from "solid-js" import { useLocal } from "@/context/local" import { preferredProviders } from "@/hooks/use-providers" import { useLanguage } from "@/context/language" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { DialogSelectProvider } from "./dialog-select-provider" export const DialogManageModels: Component = () => { const local = useLocal() const language = useLanguage() + const dialog = useDialog() + + const handleConnectProvider = () => { + dialog.show(() => ) + } + return ( - + + {language.t("command.provider.connect")} + + } + > props.highlights.length + const last = () => Math.max(0, total() - 1) + const feature = () => props.highlights[index()] ?? props.highlights[last()] + const isFirst = () => index() === 0 + const isLast = () => index() >= last() + const paged = () => total() > 1 + + function handleNext() { + if (isLast()) return + setIndex(index() + 1) + } + + function handleClose() { + dialog.close() + } + + function handleDisable() { + settings.general.setReleaseNotes(false) + handleClose() + } + + let focusTrap: HTMLDivElement | undefined + + function handleKeyDown(e: KeyboardEvent) { + if (e.key === "Escape") { + e.preventDefault() + handleClose() + return + } + + if (!paged()) return + if (e.key === "ArrowLeft" && !isFirst()) { + e.preventDefault() + setIndex(index() - 1) + } + if (e.key === "ArrowRight" && !isLast()) { + e.preventDefault() + setIndex(index() + 1) + } + } + + onMount(() => { + focusTrap?.focus() + document.addEventListener("keydown", handleKeyDown) + onCleanup(() => document.removeEventListener("keydown", handleKeyDown)) + }) + + // Refocus the trap when index changes to ensure escape always works + createEffect(() => { + index() // track index + focusTrap?.focus() + }) + + return ( + + {/* Hidden element to capture initial focus and handle escape */} +
+
+ {/* Left side - Text content */} +
+ {/* Top section - feature content (fixed position from top) */} +
+
+

{feature()?.title ?? ""}

+
+

{feature()?.description ?? ""}

+
+ + {/* Spacer to push buttons to bottom */} +
+ + {/* Bottom section - buttons and indicators (fixed position) */} +
+
+ {isLast() ? ( + + ) : ( + + )} + + +
+ + {paged() && ( +
+ {props.highlights.map((_, i) => ( + + ))} +
+ )} +
+
+ + {/* Right side - Media content (edge to edge) */} + {feature()?.media && ( +
+ {feature()!.media!.type === "image" ? ( + {feature()!.media!.alt + ) : ( +
+ )} +
+
+ ) +} diff --git a/packages/app/src/components/dialog-select-file.tsx b/packages/app/src/components/dialog-select-file.tsx index 1bb95c68aa..64b83d31bf 100644 --- a/packages/app/src/components/dialog-select-file.tsx +++ b/packages/app/src/components/dialog-select-file.tsx @@ -24,16 +24,18 @@ type Entry = { path?: string } -export function DialogSelectFile() { +type DialogSelectFileMode = "all" | "files" + +export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFile?: (path: string) => void }) { const command = useCommand() const language = useLanguage() const layout = useLayout() const file = useFile() const dialog = useDialog() const params = useParams() + const filesOnly = () => props.mode === "files" const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const tabs = createMemo(() => layout.tabs(sessionKey)) - const view = createMemo(() => layout.view(sessionKey)) const state = { cleanup: undefined as (() => void) | void, committed: false } const [grouped, setGrouped] = createSignal(false) const common = [ @@ -46,11 +48,12 @@ export function DialogSelectFile() { ] const limit = 5 - const allowed = createMemo(() => - command.options.filter( + const allowed = createMemo(() => { + if (filesOnly()) return [] + return command.options.filter( (option) => !option.disabled && !option.id.startsWith("suggested.") && option.id !== "file.open", - ), - ) + ) + }) const commandItem = (option: CommandOption): Entry => ({ id: "command:" + option.id, @@ -99,10 +102,50 @@ export function DialogSelectFile() { return items.slice(0, limit) }) - const items = async (filter: string) => { - const query = filter.trim() + const root = createMemo(() => { + const nodes = file.tree.children("") + const paths = nodes + .filter((node) => node.type === "file") + .map((node) => node.path) + .sort((a, b) => a.localeCompare(b)) + return paths.slice(0, limit).map(fileItem) + }) + + const unique = (items: Entry[]) => { + const seen = new Set() + const out: Entry[] = [] + for (const item of items) { + if (seen.has(item.id)) continue + seen.add(item.id) + out.push(item) + } + return out + } + + const items = async (text: string) => { + const query = text.trim() setGrouped(query.length > 0) + + if (!query && filesOnly()) { + const loaded = file.tree.state("")?.loaded + const pending = loaded ? Promise.resolve() : file.tree.list("") + const next = unique([...recent(), ...root()]) + + if (loaded || next.length > 0) { + void pending + return next + } + + await pending + return unique([...recent(), ...root()]) + } + if (!query) return [...picks(), ...recent()] + + if (filesOnly()) { + const files = await file.searchFiles(query) + return files.map(fileItem) + } const files = await file.searchFiles(query) const entries = files.map(fileItem) return [...list(), ...entries] @@ -119,7 +162,9 @@ export function DialogSelectFile() { const value = file.tab(path) tabs().open(value) file.load(path) - view().reviewPanel.open() + layout.fileTree.open() + layout.fileTree.setTab("all") + props.onOpenFile?.(path) } const handleSelect = (item: Entry | undefined) => { @@ -143,13 +188,14 @@ export function DialogSelectFile() { }) return ( - + } > -
+
{item.title} diff --git a/packages/app/src/components/dialog-select-model.tsx b/packages/app/src/components/dialog-select-model.tsx index 8bbe5bd34d..2b8470e265 100644 --- a/packages/app/src/components/dialog-select-model.tsx +++ b/packages/app/src/components/dialog-select-model.tsx @@ -54,6 +54,7 @@ const ModelList: Component<{ class="w-full" placement="right-start" gutter={12} + forceMount={false} value={ (props: { setStore("open", false) dialog.show(() => ) } + + const handleConnectProvider = () => { + setStore("open", false) + dialog.show(() => ) + } const language = useLanguage() createEffect(() => { @@ -181,7 +187,7 @@ export function ModelSelectorPopover(props: { setStore("content", el)} - class="w-72 h-80 flex flex-col rounded-md border border-border-base bg-surface-raised-stronger-non-alpha shadow-md z-50 outline-none overflow-hidden" + class="w-72 h-80 flex flex-col p-2 rounded-md border border-border-base bg-surface-raised-stronger-non-alpha shadow-md z-50 outline-none overflow-hidden" onEscapeKeyDown={(event) => { setStore("dismiss", "escape") setStore("open", false) @@ -207,15 +213,28 @@ export function ModelSelectorPopover(props: { onSelect={() => setStore("open", false)} class="p-1" action={ - +
+ + + + + + +
} />
diff --git a/packages/app/src/components/dialog-select-provider.tsx b/packages/app/src/components/dialog-select-provider.tsx index 946b84b44c..cb570f75f6 100644 --- a/packages/app/src/components/dialog-select-provider.tsx +++ b/packages/app/src/components/dialog-select-provider.tsx @@ -5,9 +5,17 @@ import { Dialog } from "@opencode-ai/ui/dialog" import { List } from "@opencode-ai/ui/list" import { Tag } from "@opencode-ai/ui/tag" import { ProviderIcon } from "@opencode-ai/ui/provider-icon" -import { IconName } from "@opencode-ai/ui/icons/provider" +import { iconNames, type IconName } from "@opencode-ai/ui/icons/provider" import { DialogConnectProvider } from "./dialog-connect-provider" import { useLanguage } from "@/context/language" +import { DialogCustomProvider } from "./dialog-custom-provider" + +const CUSTOM_ID = "_custom" + +function icon(id: string): IconName { + if (iconNames.includes(id as IconName)) return id as IconName + return "synthetic" +} export const DialogSelectProvider: Component = () => { const dialog = useDialog() @@ -20,7 +28,7 @@ export const DialogSelectProvider: Component = () => { // kilocode_change end return ( - + { key={(x) => x?.id} items={() => { language.locale() - return providers.all() + return [{ id: CUSTOM_ID, name: "Custom provider" }, ...providers.all()] }} filterKeys={["id", "name"]} groupBy={(x) => (preferredProviders.includes(x.id) ? recommendedGroup() : otherGroup())} sortBy={(a, b) => { + if (a.id === CUSTOM_ID) return -1 + if (b.id === CUSTOM_ID) return 1 if (preferredProviders.includes(a.id) && preferredProviders.includes(b.id)) return preferredProviders.indexOf(a.id) - preferredProviders.indexOf(b.id) return a.name.localeCompare(b.name) @@ -45,12 +55,16 @@ export const DialogSelectProvider: Component = () => { }} onSelect={(x) => { if (!x) return + if (x.id === CUSTOM_ID) { + dialog.show(() => ) + return + } dialog.show(() => ) }} > {(i) => (
- + {i.name} {/* kilocode_change start - Provider tags and notes */} @@ -58,6 +72,9 @@ export const DialogSelectProvider: Component = () => {
{language.t("dialog.provider.kilo.note")}
{/* kilocode_change end */} + + {language.t("settings.providers.tag.custom")} + {language.t("dialog.provider.tag.recommended")} diff --git a/packages/app/src/components/dialog-select-server.tsx b/packages/app/src/components/dialog-select-server.tsx index f3bbf6269d..e8a36f1380 100644 --- a/packages/app/src/components/dialog-select-server.tsx +++ b/packages/app/src/components/dialog-select-server.tsx @@ -14,6 +14,7 @@ import { useLanguage } from "@/context/language" import { DropdownMenu } from "@opencode-ai/ui/dropdown-menu" import { Tooltip } from "@opencode-ai/ui/tooltip" import { useGlobalSDK } from "@/context/global-sdk" +import { showToast } from "@opencode-ai/ui/toast" type ServerStatus = { healthy: boolean; version?: string } @@ -40,10 +41,11 @@ interface EditRowProps { } async function checkHealth(url: string, platform: ReturnType): Promise { + const signal = (AbortSignal as unknown as { timeout?: (ms: number) => AbortSignal }).timeout?.(3000) const sdk = createOpencodeClient({ baseUrl: url, fetch: platform.fetch, - signal: AbortSignal.timeout(3000), + signal, }) return sdk.global .health() @@ -57,18 +59,16 @@ function AddRow(props: AddRowProps) {
{ // Position relative to input-wrapper requestAnimationFrame(() => { const wrapper = el.parentElement?.querySelector('[data-slot="input-wrapper"]') if (wrapper instanceof HTMLElement) { - wrapper.style.position = "relative" wrapper.appendChild(el) } }) @@ -149,13 +149,22 @@ export function DialogSelectServer() { }) const [defaultUrl, defaultUrlActions] = createResource( async () => { - const url = await platform.getDefaultServerUrl?.() - if (!url) return null - return normalizeServerUrl(url) ?? null + try { + const url = await platform.getDefaultServerUrl?.() + if (!url) return null + return normalizeServerUrl(url) ?? null + } catch (err) { + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: err instanceof Error ? err.message : String(err), + }) + return null + } }, { initialValue: null }, ) - const isDesktop = platform.platform === "desktop" + const canDefault = createMemo(() => !!platform.getDefaultServerUrl && !!platform.setDefaultServerUrl) const looksComplete = (value: string) => { const normalized = normalizeServerUrl(value) @@ -505,11 +514,19 @@ export function DialogSelectServer() { > {language.t("dialog.server.menu.edit")} - + { - await platform.setDefaultServerUrl?.(i) - defaultUrlActions.mutate(i) + try { + await platform.setDefaultServerUrl?.(i) + defaultUrlActions.mutate(i) + } catch (err) { + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: err instanceof Error ? err.message : String(err), + }) + } }} > @@ -517,11 +534,19 @@ export function DialogSelectServer() { - + { - await platform.setDefaultServerUrl?.(null) - defaultUrlActions.mutate(null) + try { + await platform.setDefaultServerUrl?.(null) + defaultUrlActions.mutate(null) + } catch (err) { + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: err instanceof Error ? err.message : String(err), + }) + } }} > diff --git a/packages/app/src/components/dialog-settings.tsx b/packages/app/src/components/dialog-settings.tsx index dbbc8fa7ad..f8892ebbdc 100644 --- a/packages/app/src/components/dialog-settings.tsx +++ b/packages/app/src/components/dialog-settings.tsx @@ -6,81 +6,54 @@ import { useLanguage } from "@/context/language" import { usePlatform } from "@/context/platform" import { SettingsGeneral } from "./settings-general" import { SettingsKeybinds } from "./settings-keybinds" -import { SettingsPermissions } from "./settings-permissions" import { SettingsProviders } from "./settings-providers" import { SettingsModels } from "./settings-models" -import { SettingsAgents } from "./settings-agents" -import { SettingsCommands } from "./settings-commands" -import { SettingsMcp } from "./settings-mcp" export const DialogSettings: Component = () => { const language = useLanguage() const platform = usePlatform() return ( - + -
-
- {language.t("settings.section.desktop")} -
- - - {language.t("settings.tab.general")} - - - - {language.t("settings.tab.shortcuts")} - +
+
+
+
+ {language.t("settings.section.desktop")} +
+ + + {language.t("settings.tab.general")} + + + + {language.t("settings.tab.shortcuts")} + +
+
+ +
+ {language.t("settings.section.server")} +
+ + + {language.t("settings.providers.title")} + + + + {language.t("settings.models.title")} + +
+
- OpenCode Desktop + {language.t("app.name.desktop")} v{platform.version}
- {/* Server */} - {/* */} - {/* */} - {/* Permissions */} - {/* */} - {/* */} - {/* */} - {/* Providers */} - {/* */} - {/* */} - {/* */} - {/* Models */} - {/* */} - {/* */} - {/* */} - {/* Agents */} - {/* */} - {/* */} - {/* */} - {/* Commands */} - {/* */} - {/* */} - {/* */} - {/* MCP */} - {/* */} @@ -88,15 +61,12 @@ export const DialogSettings: Component = () => { - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} + + + + + + {/* */} {/* */} {/* */} diff --git a/packages/app/src/components/file-tree.tsx b/packages/app/src/components/file-tree.tsx index 3439d366ce..97c1541de0 100644 --- a/packages/app/src/components/file-tree.tsx +++ b/packages/app/src/components/file-tree.tsx @@ -1,111 +1,373 @@ -import { useLocal, type LocalFile } from "@/context/local" +import { useFile } from "@/context/file" import { Collapsible } from "@opencode-ai/ui/collapsible" import { FileIcon } from "@opencode-ai/ui/file-icon" +import { Icon } from "@opencode-ai/ui/icon" import { Tooltip } from "@opencode-ai/ui/tooltip" -import { For, Match, Switch, type ComponentProps, type ParentProps } from "solid-js" +import { + createEffect, + createMemo, + For, + Match, + Show, + splitProps, + Switch, + untrack, + type ComponentProps, + type ParentProps, +} from "solid-js" import { Dynamic } from "solid-js/web" +import type { FileNode } from "@kilocode/sdk/v2" // kilocode_change + +type Kind = "add" | "del" | "mix" + +type Filter = { + files: Set + dirs: Set +} export default function FileTree(props: { path: string class?: string nodeClass?: string + active?: string level?: number - onFileClick?: (file: LocalFile) => void + allowed?: readonly string[] + modified?: readonly string[] + kinds?: ReadonlyMap + draggable?: boolean + tooltip?: boolean + onFileClick?: (file: FileNode) => void + + _filter?: Filter + _marks?: Set + _deeps?: Map + _kinds?: ReadonlyMap }) { - const local = useLocal() + const file = useFile() const level = props.level ?? 0 + const draggable = () => props.draggable ?? true + const tooltip = () => props.tooltip ?? true - const Node = (p: ParentProps & ComponentProps<"div"> & { node: LocalFile; as?: "div" | "button" }) => ( - { - const evt = e as globalThis.DragEvent - evt.dataTransfer!.effectAllowed = "copy" - evt.dataTransfer!.setData("text/plain", `file:${p.node.path}`) + const filter = createMemo(() => { + if (props._filter) return props._filter - // Create custom drag image without margins - const dragImage = document.createElement("div") - dragImage.className = - "flex items-center gap-x-2 px-2 py-1 bg-background-element rounded-md border border-border-1" - dragImage.style.position = "absolute" - dragImage.style.top = "-1000px" + const allowed = props.allowed + if (!allowed) return - // Copy only the icon and text content without padding - const icon = e.currentTarget.querySelector("svg") - const text = e.currentTarget.querySelector("span") - if (icon && text) { - dragImage.innerHTML = icon.outerHTML + text.outerHTML - } + const files = new Set(allowed) + const dirs = new Set() - document.body.appendChild(dragImage) - evt.dataTransfer!.setDragImage(dragImage, 0, 12) - setTimeout(() => document.body.removeChild(dragImage), 0) - }} - {...p} - > - {p.children} - { + if (props._marks) return props._marks + + const out = new Set() + for (const item of props.modified ?? []) out.add(item) + for (const item of props.kinds?.keys() ?? []) out.add(item) + if (out.size === 0) return + return out + }) + + const kinds = createMemo(() => { + if (props._kinds) return props._kinds + return props.kinds + }) + + const deeps = createMemo(() => { + if (props._deeps) return props._deeps + + const out = new Map() + + const visit = (dir: string, lvl: number): number => { + const expanded = file.tree.state(dir)?.expanded ?? false + if (!expanded) return -1 + + const nodes = file.tree.children(dir) + const max = nodes.reduce((max, node) => { + if (node.type !== "directory") return max + const open = file.tree.state(node.path)?.expanded ?? false + if (!open) return max + return Math.max(max, visit(node.path, lvl + 1)) + }, lvl) + + out.set(dir, max) + return max + } + + visit(props.path, level - 1) + return out + }) + + createEffect(() => { + const current = filter() + if (!current) return + if (level !== 0) return + + for (const dir of current.dirs) { + const expanded = untrack(() => file.tree.state(dir)?.expanded) ?? false + if (expanded) continue + file.tree.expand(dir) + } + }) + + createEffect(() => { + const path = props.path + untrack(() => void file.tree.list(path)) + }) + + const nodes = createMemo(() => { + const nodes = file.tree.children(props.path) + const current = filter() + if (!current) return nodes + return nodes.filter((node) => { + if (node.type === "file") return current.files.has(node.path) + return current.dirs.has(node.path) + }) + }) + + const Node = ( + p: ParentProps & + ComponentProps<"div"> & + ComponentProps<"button"> & { + node: FileNode + as?: "div" | "button" + }, + ) => { + const [local, rest] = splitProps(p, ["node", "as", "children", "class", "classList"]) + return ( + { + if (!draggable()) return + e.dataTransfer?.setData("text/plain", `file:${local.node.path}`) + e.dataTransfer?.setData("text/uri-list", `file://${local.node.path}`) + if (e.dataTransfer) e.dataTransfer.effectAllowed = "copy" + + const dragImage = document.createElement("div") + dragImage.className = + "flex items-center gap-x-2 px-2 py-1 bg-surface-raised-base rounded-md border border-border-base text-12-regular text-text-strong" + dragImage.style.position = "absolute" + dragImage.style.top = "-1000px" + + const icon = + (e.currentTarget as HTMLElement).querySelector('[data-component="file-icon"]') ?? + (e.currentTarget as HTMLElement).querySelector("svg") + const text = (e.currentTarget as HTMLElement).querySelector("span") + if (icon && text) { + dragImage.innerHTML = (icon as SVGElement).outerHTML + (text as HTMLSpanElement).outerHTML + } + + document.body.appendChild(dragImage) + e.dataTransfer?.setDragImage(dragImage, 0, 12) + setTimeout(() => document.body.removeChild(dragImage), 0) + }} + {...rest} > - {p.node.name} - - {/* */} - {/* */} - {/* */} - - ) + {local.children} + {(() => { + const kind = kinds()?.get(local.node.path) + const marked = marks()?.has(local.node.path) ?? false + const active = !!kind && marked && !local.node.ignored + const color = + kind === "add" + ? "color: var(--icon-diff-add-base)" + : kind === "del" + ? "color: var(--icon-diff-delete-base)" + : kind === "mix" + ? "color: var(--icon-diff-modified-base)" + : undefined + return ( + + {local.node.name} + + ) + })()} + {(() => { + const kind = kinds()?.get(local.node.path) + if (!kind) return null + if (!marks()?.has(local.node.path)) return null + + if (local.node.type === "file") { + const text = kind === "add" ? "A" : kind === "del" ? "D" : "M" + const color = + kind === "add" + ? "color: var(--icon-diff-add-base)" + : kind === "del" + ? "color: var(--icon-diff-delete-base)" + : "color: var(--icon-diff-modified-base)" + + return ( + + {text} + + ) + } + + if (local.node.type === "directory") { + const color = + kind === "add" + ? "background-color: var(--icon-diff-add-base)" + : kind === "del" + ? "background-color: var(--icon-diff-delete-base)" + : "background-color: var(--icon-diff-modified-base)" + + return
+ } + + return null + })()} + + ) + } return ( -
- - {(node) => ( - +
+ + {(node) => { + const expanded = () => file.tree.state(node.path)?.expanded ?? false + const deep = () => deeps().get(node.path) ?? -1 + const Wrapper = (p: ParentProps) => { + if (!tooltip()) return p.children + + const parts = node.path.split("/") + const leaf = parts[parts.length - 1] ?? node.path + const head = parts.slice(0, -1).join("/") + const prefix = head ? `${head}/` : "" + + const kind = () => kinds()?.get(node.path) + const label = () => { + const k = kind() + if (!k) return + if (k === "add") return "Additions" + if (k === "del") return "Deletions" + return "Modifications" + } + + const ignored = () => node.type === "directory" && node.ignored + + return ( + + + {prefix} + + {leaf} + + {(t: () => string) => ( + <> + + {t()} + + )} + + + <> + + Ignored + + +
+ } + > + {p.children} +
+ ) + } + + return ( (open ? local.file.expand(node.path) : local.file.collapse(node.path))} + open={expanded()} + onOpenChange={(open) => (open ? file.tree.expand(node.path) : file.tree.collapse(node.path))} > - - - - + + +
+ +
+
+
- - + +
+ - props.onFileClick?.(node)}> -
- - + + props.onFileClick?.(node)}> +
+ + + - - )} + ) + }}
) diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 5b3f9c82b9..633d749996 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -171,7 +171,6 @@ export const PromptInput: Component = (props) => { const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const tabs = createMemo(() => layout.tabs(sessionKey)) - const view = createMemo(() => layout.view(sessionKey)) const commentInReview = (path: string) => { const sessionID = params.id @@ -187,20 +186,17 @@ export const PromptInput: Component = (props) => { const focus = { file: item.path, id: item.commentID } comments.setActive(focus) - view().reviewPanel.open() - if (item.commentOrigin === "review") { - tabs().open("review") - requestAnimationFrame(() => comments.setFocus(focus)) - return - } - - if (item.commentOrigin !== "file" && commentInReview(item.path)) { - tabs().open("review") + const wantsReview = item.commentOrigin === "review" || (item.commentOrigin !== "file" && commentInReview(item.path)) + if (wantsReview) { + layout.fileTree.open() + layout.fileTree.setTab("changes") requestAnimationFrame(() => comments.setFocus(focus)) return } + layout.fileTree.open() + layout.fileTree.setTab("all") const tab = files.tab(item.path) tabs().open(tab) files.load(item.path) @@ -1042,13 +1038,17 @@ export const PromptInput: Component = (props) => { return } + const ctrl = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey + if (store.popover) { if (event.key === "Tab") { selectPopoverActive() event.preventDefault() return } - if (event.key === "ArrowUp" || event.key === "ArrowDown" || event.key === "Enter") { + const nav = event.key === "ArrowUp" || event.key === "ArrowDown" || event.key === "Enter" + const ctrlNav = ctrl && (event.key === "n" || event.key === "p") + if (nav || ctrlNav) { if (store.popover === "at") { atOnKeyDown(event) event.preventDefault() @@ -1062,8 +1062,6 @@ export const PromptInput: Component = (props) => { } } - const ctrl = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey - if (ctrl && event.code === "KeyG") { if (store.popover) { setStore("popover", null) @@ -1563,13 +1561,17 @@ export const PromptInput: Component = (props) => { }) const timeoutMs = 5 * 60 * 1000 + const timer = { id: undefined as number | undefined } const timeout = new Promise>>((resolve) => { - setTimeout(() => { - resolve({ status: "failed", message: "Workspace is still preparing" }) + timer.id = window.setTimeout(() => { + resolve({ status: "failed", message: language.t("workspace.error.stillPreparing") }) }, timeoutMs) }) - const result = await Promise.race([WorktreeState.wait(sessionDirectory), abort, timeout]) + const result = await Promise.race([WorktreeState.wait(sessionDirectory), abort, timeout]).finally(() => { + if (timer.id === undefined) return + clearTimeout(timer.id) + }) pending.delete(session.id) if (controller.signal.aborted) return false if (result.status === "failed") throw new Error(result.message) @@ -1746,10 +1748,7 @@ export const PromptInput: Component = (props) => { - + {getDirectory(item.path)} {getFilename(item.path)} @@ -1772,10 +1771,7 @@ export const PromptInput: Component = (props) => { >
-
+
{getFilenameTruncated(item.path, 14)} {(sel) => ( @@ -1863,9 +1859,9 @@ export const PromptInput: Component = (props) => { store.mode === "shell" ? language.t("prompt.placeholder.shell") : commentCount() > 1 - ? "Summarize comments…" + ? language.t("prompt.placeholder.summarizeComments") : commentCount() === 1 - ? "Summarize comment…" + ? language.t("prompt.placeholder.summarizeComment") : language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) }) } contenteditable="true" @@ -1887,9 +1883,9 @@ export const PromptInput: Component = (props) => { {store.mode === "shell" ? language.t("prompt.placeholder.shell") : commentCount() > 1 - ? "Summarize comments…" + ? language.t("prompt.placeholder.summarizeComments") : commentCount() === 1 - ? "Summarize comment…" + ? language.t("prompt.placeholder.summarizeComment") : language.t("prompt.placeholder.normal", { example: language.t(EXAMPLES[store.placeholder]) })}
diff --git a/packages/app/src/components/session-context-usage.tsx b/packages/app/src/components/session-context-usage.tsx index aae9ddc00c..20fa5740cf 100644 --- a/packages/app/src/components/session-context-usage.tsx +++ b/packages/app/src/components/session-context-usage.tsx @@ -23,7 +23,6 @@ export function SessionContextUsage(props: SessionContextUsageProps) { const variant = createMemo(() => props.variant ?? "button") const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const tabs = createMemo(() => layout.tabs(sessionKey)) - const view = createMemo(() => layout.view(sessionKey)) const messages = createMemo(() => (params.id ? (sync.data.message[params.id] ?? []) : [])) const usd = createMemo( @@ -58,7 +57,8 @@ export function SessionContextUsage(props: SessionContextUsageProps) { const openContext = () => { if (!params.id) return - view().reviewPanel.open() + layout.fileTree.open() + layout.fileTree.setTab("all") tabs().open("context") tabs().setActive("context") } diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx index e4a64b3390..d794fb5c63 100644 --- a/packages/app/src/components/session/session-header.tsx +++ b/packages/app/src/components/session/session-header.tsx @@ -9,7 +9,7 @@ import { usePlatform } from "@/context/platform" import { useSync } from "@/context/sync" import { useGlobalSDK } from "@/context/global-sdk" import { getFilename } from "@opencode-ai/util/path" -import { base64Decode } from "@opencode-ai/util/encode" +import { decode64 } from "@/utils/base64" import { Icon } from "@opencode-ai/ui/icon" import { IconButton } from "@opencode-ai/ui/icon-button" @@ -29,7 +29,7 @@ export function SessionHeader() { const platform = usePlatform() const language = useLanguage() - const projectDirectory = createMemo(() => base64Decode(params.dir ?? "")) + const projectDirectory = createMemo(() => decode64(params.dir) ?? "") const project = createMemo(() => { const directory = projectDirectory() if (!directory) return @@ -45,7 +45,6 @@ export function SessionHeader() { const currentSession = createMemo(() => sync.data.session.find((s) => s.id === params.id)) const shareEnabled = createMemo(() => sync.data.config.share !== "disabled") const showShare = createMemo(() => shareEnabled() && !!currentSession()) - const showReview = createMemo(() => !!currentSession()) const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`) const view = createMemo(() => layout.view(sessionKey)) @@ -131,7 +130,7 @@ export function SessionHeader() { diff --git a/packages/app/src/components/session/session-new-view.tsx b/packages/app/src/components/session/session-new-view.tsx index 2b79c47dfc..9306e8acb6 100644 --- a/packages/app/src/components/session/session-new-view.tsx +++ b/packages/app/src/components/session/session-new-view.tsx @@ -45,10 +45,7 @@ export function NewSessionView(props: NewSessionViewProps) { } return ( -
+
{language.t("command.session.new")}
diff --git a/packages/app/src/components/session/session-sortable-tab.tsx b/packages/app/src/components/session/session-sortable-tab.tsx index af2f57b06b..06609fcfb8 100644 --- a/packages/app/src/components/session/session-sortable-tab.tsx +++ b/packages/app/src/components/session/session-sortable-tab.tsx @@ -11,7 +11,7 @@ import { useLanguage } from "@/context/language" export function FileVisual(props: { path: string; active?: boolean }): JSX.Element { return ( -
+
- {getFilename(props.path)} + {getFilename(props.path)}
) } @@ -38,8 +38,9 @@ export function SortableTab(props: { tab: string; onTabClose: (tab: string) => v closeButton={ props.onTabClose(props.tab)} aria-label={language.t("common.closeTab")} /> diff --git a/packages/app/src/components/session/session-sortable-terminal-tab.tsx b/packages/app/src/components/session/session-sortable-terminal-tab.tsx index d16379e80a..aedf678765 100644 --- a/packages/app/src/components/session/session-sortable-terminal-tab.tsx +++ b/packages/app/src/components/session/session-sortable-terminal-tab.tsx @@ -1,5 +1,6 @@ import type { JSX } from "solid-js" -import { createSignal, Show } from "solid-js" +import { Show } from "solid-js" +import { createStore } from "solid-js/store" import { createSortable } from "@thisbeyond/solid-dnd" import { IconButton } from "@opencode-ai/ui/icon-button" import { Tabs } from "@opencode-ai/ui/tabs" @@ -12,11 +13,13 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => const terminal = useTerminal() const language = useLanguage() const sortable = createSortable(props.terminal.id) - const [editing, setEditing] = createSignal(false) - const [title, setTitle] = createSignal(props.terminal.title) - const [menuOpen, setMenuOpen] = createSignal(false) - const [menuPosition, setMenuPosition] = createSignal({ x: 0, y: 0 }) - const [blurEnabled, setBlurEnabled] = createSignal(false) + const [store, setStore] = createStore({ + editing: false, + title: props.terminal.title, + menuOpen: false, + menuPosition: { x: 0, y: 0 }, + blurEnabled: false, + }) const isDefaultTitle = () => { const number = props.terminal.titleNumber @@ -47,7 +50,7 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => } const focus = () => { - if (editing()) return + if (store.editing) return if (document.activeElement instanceof HTMLElement) { document.activeElement.blur() @@ -71,26 +74,26 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => e.preventDefault() } - setBlurEnabled(false) - setTitle(props.terminal.title) - setEditing(true) + setStore("blurEnabled", false) + setStore("title", props.terminal.title) + setStore("editing", true) setTimeout(() => { const input = document.getElementById(`terminal-title-input-${props.terminal.id}`) as HTMLInputElement if (!input) return input.focus() input.select() - setTimeout(() => setBlurEnabled(true), 100) + setTimeout(() => setStore("blurEnabled", true), 100) }, 10) } const save = () => { - if (!blurEnabled()) return + if (!store.blurEnabled) return - const value = title().trim() + const value = store.title.trim() if (value && value !== props.terminal.title) { terminal.update({ id: props.terminal.id, title: value }) } - setEditing(false) + setStore("editing", false) } const keydown = (e: KeyboardEvent) => { @@ -101,14 +104,14 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => } if (e.key === "Escape") { e.preventDefault() - setEditing(false) + setStore("editing", false) } } const menu = (e: MouseEvent) => { e.preventDefault() - setMenuPosition({ x: e.clientX, y: e.clientY }) - setMenuOpen(true) + setStore("menuPosition", { x: e.clientX, y: e.clientY }) + setStore("menuOpen", true) } return ( @@ -143,17 +146,17 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => /> } > - + {label()} - +
setTitle(e.currentTarget.value)} + value={store.title} + onInput={(e) => setStore("title", e.currentTarget.value)} onBlur={save} onKeyDown={keydown} onMouseDown={(e) => e.stopPropagation()} @@ -161,13 +164,13 @@ export function SortableTerminalTab(props: { terminal: LocalPTY; onClose?: () => />
- + setStore("menuOpen", open)}> diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index cfb8a998d3..3b08652bbb 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -1,8 +1,12 @@ import { Component, createMemo, type JSX } from "solid-js" +import { createStore } from "solid-js/store" +import { Button } from "@opencode-ai/ui/button" import { Select } from "@opencode-ai/ui/select" import { Switch } from "@opencode-ai/ui/switch" import { useTheme, type ColorScheme } from "@opencode-ai/ui/theme" +import { showToast } from "@opencode-ai/ui/toast" import { useLanguage } from "@/context/language" +import { usePlatform } from "@/context/platform" import { useSettings, monoFontFamily } from "@/context/settings" import { playSound, SOUND_OPTIONS } from "@/utils/sound" import { Link } from "./link" @@ -29,8 +33,67 @@ const playDemoSound = (src: string) => { export const SettingsGeneral: Component = () => { const theme = useTheme() const language = useLanguage() + const platform = usePlatform() const settings = useSettings() + const [store, setStore] = createStore({ + checking: false, + }) + + const check = () => { + if (!platform.checkUpdate) return + setStore("checking", true) + + void platform + .checkUpdate() + .then((result) => { + if (!result.updateAvailable) { + showToast({ + variant: "success", + icon: "circle-check", + title: language.t("settings.updates.toast.latest.title"), + description: language.t("settings.updates.toast.latest.description", { version: platform.version ?? "" }), + }) + return + } + + const actions = + platform.update && platform.restart + ? [ + { + label: language.t("toast.update.action.installRestart"), + onClick: async () => { + await platform.update!() + await platform.restart!() + }, + }, + { + label: language.t("toast.update.action.notYet"), + onClick: "dismiss" as const, + }, + ] + : [ + { + label: language.t("toast.update.action.notYet"), + onClick: "dismiss" as const, + }, + ] + + showToast({ + persistent: true, + icon: "download", + title: language.t("toast.update.title"), + description: language.t("toast.update.description", { version: result.version ?? "" }), + actions, + }) + }) + .catch((err: unknown) => { + const message = err instanceof Error ? err.message : String(err) + showToast({ title: language.t("common.requestFailed"), description: message }) + }) + .finally(() => setStore("checking", false)) + } + const themeOptions = createMemo(() => Object.entries(theme.themes()).map(([id, def]) => ({ id, name: def.name ?? id })), ) @@ -67,14 +130,8 @@ export const SettingsGeneral: Component = () => { const soundOptions = [...SOUND_OPTIONS] return ( -
-
+
+

{language.t("settings.tab.general")}

@@ -292,6 +349,50 @@ export const SettingsGeneral: Component = () => {
+ + {/* Updates Section */} +
+

{language.t("settings.general.section.updates")}

+ +
+ + settings.updates.setStartup(checked)} + /> + + + + settings.general.setReleaseNotes(checked)} + /> + + + + + +
+
) @@ -305,8 +406,8 @@ interface SettingsRowProps { const SettingsRow: Component = (props) => { return ( -
-
+
+
{props.title} {props.description}
diff --git a/packages/app/src/components/settings-keybinds.tsx b/packages/app/src/components/settings-keybinds.tsx index 4dc3971495..393da0c2ab 100644 --- a/packages/app/src/components/settings-keybinds.tsx +++ b/packages/app/src/components/settings-keybinds.tsx @@ -1,4 +1,5 @@ -import { Component, For, Show, createMemo, createSignal, onCleanup, onMount } from "solid-js" +import { Component, For, Show, createMemo, onCleanup, onMount } from "solid-js" +import { createStore } from "solid-js/store" import { Button } from "@opencode-ai/ui/button" import { Icon } from "@opencode-ai/ui/icon" import { IconButton } from "@opencode-ai/ui/icon-button" @@ -111,24 +112,26 @@ export const SettingsKeybinds: Component = () => { const language = useLanguage() const settings = useSettings() - const [active, setActive] = createSignal(null) - const [filter, setFilter] = createSignal("") + const [store, setStore] = createStore({ + active: null as string | null, + filter: "", + }) const stop = () => { - if (!active()) return - setActive(null) + if (!store.active) return + setStore("active", null) command.keybinds(true) } const start = (id: string) => { - if (active() === id) { + if (store.active === id) { stop() return } - if (active()) stop() + if (store.active) stop() - setActive(id) + setStore("active", id) command.keybinds(false) } @@ -203,7 +206,7 @@ export const SettingsKeybinds: Component = () => { }) const filtered = createMemo(() => { - const query = filter().toLowerCase().trim() + const query = store.filter.toLowerCase().trim() if (!query) return grouped() const map = list() @@ -285,7 +288,7 @@ export const SettingsKeybinds: Component = () => { onMount(() => { const handle = (event: KeyboardEvent) => { - const id = active() + const id = store.active if (!id) return event.preventDefault() @@ -345,18 +348,12 @@ export const SettingsKeybinds: Component = () => { }) onCleanup(() => { - if (active()) command.keybinds(true) + if (store.active) command.keybinds(true) }) return ( -
-
+
+

{language.t("settings.shortcuts.title")}

@@ -370,8 +367,8 @@ export const SettingsKeybinds: Component = () => { setStore("filter", v)} placeholder={language.t("settings.shortcuts.search.placeholder")} spellcheck={false} autocorrect="off" @@ -379,8 +376,8 @@ export const SettingsKeybinds: Component = () => { autocapitalize="off" class="flex-1" /> - - setFilter("")} /> + + setStore("filter", "")} />
@@ -402,13 +399,13 @@ export const SettingsKeybinds: Component = () => { classList={{ "h-8 px-3 rounded-md text-12-regular": true, "bg-surface-base text-text-subtle hover:bg-surface-raised-base-hover active:bg-surface-raised-base-active": - active() !== id, - "border border-border-weak-base bg-surface-inset-base text-text-weak": active() === id, + store.active !== id, + "border border-border-weak-base bg-surface-inset-base text-text-weak": store.active === id, }} onClick={() => start(id)} > {language.t("settings.shortcuts.pressKeys")} @@ -423,11 +420,11 @@ export const SettingsKeybinds: Component = () => { )} - +
{language.t("settings.shortcuts.search.empty")} - - "{filter()}" + + "{store.filter}"
diff --git a/packages/app/src/components/settings-models.tsx b/packages/app/src/components/settings-models.tsx index 6a636879d0..e3687fd0f2 100644 --- a/packages/app/src/components/settings-models.tsx +++ b/packages/app/src/components/settings-models.tsx @@ -1,14 +1,129 @@ -import { Component } from "solid-js" +import { useFilteredList } from "@opencode-ai/ui/hooks" +import { ProviderIcon } from "@opencode-ai/ui/provider-icon" +import { Switch } from "@opencode-ai/ui/switch" +import { Icon } from "@opencode-ai/ui/icon" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { TextField } from "@opencode-ai/ui/text-field" +import type { IconName } from "@opencode-ai/ui/icons/provider" +import { type Component, For, Show } from "solid-js" import { useLanguage } from "@/context/language" +import { useModels } from "@/context/models" +import { preferredProviders } from "@/hooks/use-providers" + +type ModelItem = ReturnType["list"]>[number] export const SettingsModels: Component = () => { const language = useLanguage() + const models = useModels() + + const list = useFilteredList({ + items: (_filter) => models.list(), + key: (x) => `${x.provider.id}:${x.id}`, + filterKeys: ["provider.name", "name", "id"], + sortBy: (a, b) => a.name.localeCompare(b.name), + groupBy: (x) => x.provider.id, + sortGroupsBy: (a, b) => { + const aIndex = preferredProviders.indexOf(a.category) + const bIndex = preferredProviders.indexOf(b.category) + const aPopular = aIndex >= 0 + const bPopular = bIndex >= 0 + + if (aPopular && !bPopular) return -1 + if (!aPopular && bPopular) return 1 + if (aPopular && bPopular) return aIndex - bIndex + + const aName = a.items[0].provider.name + const bName = b.items[0].provider.name + return aName.localeCompare(bName) + }, + }) return ( -
-
-

{language.t("settings.models.title")}

-

{language.t("settings.models.description")}

+
+
+
+

{language.t("settings.models.title")}

+
+ + + + + +
+
+
+ +
+ + + {language.t("common.loading")} + {language.t("common.loading.ellipsis")} + +
+ } + > + 0} + fallback={ +
+ {language.t("dialog.model.empty")} + + "{list.filter()}" + +
+ } + > + + {(group) => ( +
+
+ + {group.items[0].provider.name} +
+
+ + {(item) => { + const key = { providerID: item.provider.id, modelID: item.id } + return ( +
+
+ {item.name} +
+
+ { + models.setVisibility(key, checked) + }} + hideLabel + > + {item.name} + +
+
+ ) + }} +
+
+
+ )} +
+
+
) diff --git a/packages/app/src/components/settings-permissions.tsx b/packages/app/src/components/settings-permissions.tsx index 1381515f5d..7dd43a7075 100644 --- a/packages/app/src/components/settings-permissions.tsx +++ b/packages/app/src/components/settings-permissions.tsx @@ -175,20 +175,14 @@ export const SettingsPermissions: Component = () => { return (
-
-
+
+

{language.t("settings.permissions.title")}

{language.t("settings.permissions.description")}

-
+

{language.t("settings.permissions.section.tools")}

@@ -223,8 +217,8 @@ interface SettingsRowProps { const SettingsRow: Component = (props) => { return ( -
-
+
+
{props.title} {props.description}
diff --git a/packages/app/src/components/settings-providers.tsx b/packages/app/src/components/settings-providers.tsx index 7b6ca19392..53870d63f7 100644 --- a/packages/app/src/components/settings-providers.tsx +++ b/packages/app/src/components/settings-providers.tsx @@ -1,14 +1,262 @@ -import { Component } from "solid-js" +import { Button } from "@opencode-ai/ui/button" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { ProviderIcon } from "@opencode-ai/ui/provider-icon" +import { Tag } from "@opencode-ai/ui/tag" +import { showToast } from "@opencode-ai/ui/toast" +import { iconNames, type IconName } from "@opencode-ai/ui/icons/provider" +import { preferredProviders, useProviders } from "@/hooks/use-providers" +import { createMemo, type Component, For, Show } from "solid-js" import { useLanguage } from "@/context/language" +import { useGlobalSDK } from "@/context/global-sdk" +import { useGlobalSync } from "@/context/global-sync" +import { DialogConnectProvider } from "./dialog-connect-provider" +import { DialogSelectProvider } from "./dialog-select-provider" +import { DialogCustomProvider } from "./dialog-custom-provider" + +type ProviderSource = "env" | "api" | "config" | "custom" +type ProviderMeta = { source?: ProviderSource } export const SettingsProviders: Component = () => { + const dialog = useDialog() const language = useLanguage() + const globalSDK = useGlobalSDK() + const globalSync = useGlobalSync() + const providers = useProviders() + + const icon = (id: string): IconName => { + if (iconNames.includes(id as IconName)) return id as IconName + return "synthetic" + } + + const connected = createMemo(() => { + return providers + .connected() + .filter((p) => p.id !== "opencode" || Object.values(p.models).find((m) => m.cost?.input)) + }) + + const popular = createMemo(() => { + const connectedIDs = new Set(connected().map((p) => p.id)) + const items = providers + .preferred() + .filter((p) => !connectedIDs.has(p.id)) + .slice() + items.sort((a, b) => preferredProviders.indexOf(a.id) - preferredProviders.indexOf(b.id)) + return items + }) + + const source = (item: unknown) => (item as ProviderMeta).source + + const type = (item: unknown) => { + const current = source(item) + if (current === "env") return language.t("settings.providers.tag.environment") + if (current === "api") return language.t("provider.connect.method.apiKey") + if (current === "config") { + const id = (item as { id?: string }).id + if (id && isConfigCustom(id)) return language.t("settings.providers.tag.custom") + return language.t("settings.providers.tag.config") + } + if (current === "custom") return language.t("settings.providers.tag.custom") + return language.t("settings.providers.tag.other") + } + + const canDisconnect = (item: unknown) => source(item) !== "env" + + const isConfigCustom = (providerID: string) => { + const provider = globalSync.data.config.provider?.[providerID] + if (!provider) return false + if (provider.npm !== "@ai-sdk/openai-compatible") return false + if (!provider.models || Object.keys(provider.models).length === 0) return false + return true + } + + const disableProvider = async (providerID: string, name: string) => { + const before = globalSync.data.config.disabled_providers ?? [] + const next = before.includes(providerID) ? before : [...before, providerID] + globalSync.set("config", "disabled_providers", next) + + await globalSync + .updateConfig({ disabled_providers: next }) + .then(() => { + showToast({ + variant: "success", + icon: "circle-check", + title: language.t("provider.disconnect.toast.disconnected.title", { provider: name }), + description: language.t("provider.disconnect.toast.disconnected.description", { provider: name }), + }) + }) + .catch((err: unknown) => { + globalSync.set("config", "disabled_providers", before) + const message = err instanceof Error ? err.message : String(err) + showToast({ title: language.t("common.requestFailed"), description: message }) + }) + } + + const disconnect = async (providerID: string, name: string) => { + if (isConfigCustom(providerID)) { + await globalSDK.client.auth.remove({ providerID }).catch(() => undefined) + await disableProvider(providerID, name) + return + } + await globalSDK.client.auth + .remove({ providerID }) + .then(async () => { + await globalSDK.client.global.dispose() + showToast({ + variant: "success", + icon: "circle-check", + title: language.t("provider.disconnect.toast.disconnected.title", { provider: name }), + description: language.t("provider.disconnect.toast.disconnected.description", { provider: name }), + }) + }) + .catch((err: unknown) => { + const message = err instanceof Error ? err.message : String(err) + showToast({ title: language.t("common.requestFailed"), description: message }) + }) + } return ( -
-
-

{language.t("settings.providers.title")}

-

{language.t("settings.providers.description")}

+
+
+
+

{language.t("settings.providers.title")}

+
+
+ +
+
+

{language.t("settings.providers.section.connected")}

+
+ 0} + fallback={ +
+ {language.t("settings.providers.connected.empty")} +
+ } + > + + {(item) => ( +
+
+ + {item.name} + {type(item)} +
+ + Connected from your environment variables + + } + > + + +
+ )} +
+
+
+
+ +
+

{language.t("settings.providers.section.popular")}

+
+ + {(item) => ( +
+
+
+ + {item.name} + + {language.t("dialog.provider.tag.recommended")} + +
+ + + {language.t("dialog.provider.opencode.note")} + + + + + {language.t("dialog.provider.anthropic.note")} + + + + + {language.t("dialog.provider.copilot.note")} + + + + + {language.t("dialog.provider.openai.note")} + + + + + {language.t("dialog.provider.google.note")} + + + + + {language.t("dialog.provider.openrouter.note")} + + + + + {language.t("dialog.provider.vercel.note")} + + +
+ +
+ )} +
+ +
+
+
+ + Custom provider + {language.t("settings.providers.tag.custom")} +
+ Add an OpenAI-compatible provider by base URL. +
+ +
+
+ + +
) diff --git a/packages/app/src/components/status-popover.tsx b/packages/app/src/components/status-popover.tsx index 0e0300049c..efc3fc03e7 100644 --- a/packages/app/src/components/status-popover.tsx +++ b/packages/app/src/components/status-popover.tsx @@ -15,14 +15,16 @@ import { usePlatform } from "@/context/platform" import { useLanguage } from "@/context/language" import { createOpencodeClient } from "@kilocode/sdk/v2/client" // kilocode_change import { DialogSelectServer } from "./dialog-select-server" +import { showToast } from "@opencode-ai/ui/toast" type ServerStatus = { healthy: boolean; version?: string } async function checkHealth(url: string, platform: ReturnType): Promise { + const signal = (AbortSignal as unknown as { timeout?: (ms: number) => AbortSignal }).timeout?.(3000) const sdk = createOpencodeClient({ baseUrl: url, fetch: platform.fetch, - signal: AbortSignal.timeout(3000), + signal, }) return sdk.global .health() @@ -39,9 +41,10 @@ export function StatusPopover() { const language = useLanguage() const navigate = useNavigate() - const [loading, setLoading] = createSignal(null) const [store, setStore] = createStore({ status: {} as Record, + loading: null as string | null, + defaultServerUrl: undefined as string | undefined, }) const servers = createMemo(() => { @@ -97,17 +100,23 @@ export function StatusPopover() { const mcpConnected = createMemo(() => mcpItems().filter((i) => i.status === "connected").length) const toggleMcp = async (name: string) => { - if (loading()) return - setLoading(name) - const status = sync.data.mcp[name] - if (status?.status === "connected") { - await sdk.client.mcp.disconnect({ name }) - } else { - await sdk.client.mcp.connect({ name }) + if (store.loading) return + setStore("loading", name) + + try { + const status = sync.data.mcp[name] + await (status?.status === "connected" ? sdk.client.mcp.disconnect({ name }) : sdk.client.mcp.connect({ name })) + const result = await sdk.client.mcp.status() + if (result.data) sync.set("mcp", result.data) + } catch (err) { + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: err instanceof Error ? err.message : String(err), + }) + } finally { + setStore("loading", null) } - const result = await sdk.client.mcp.status() - if (result.data) sync.set("mcp", result.data) - setLoading(null) } const lspItems = createMemo(() => sync.data.lsp ?? []) @@ -123,15 +132,21 @@ export function StatusPopover() { const serverCount = createMemo(() => sortedServers().length) - const [defaultServerUrl, setDefaultServerUrl] = createSignal() - - createEffect(() => { + const refreshDefaultServerUrl = () => { const result = platform.getDefaultServerUrl?.() - if (result instanceof Promise) { - result.then((url) => setDefaultServerUrl(url ? normalizeServerUrl(url) : undefined)) + if (!result) { + setStore("defaultServerUrl", undefined) return } - if (result) setDefaultServerUrl(normalizeServerUrl(result)) + if (result instanceof Promise) { + result.then((url) => setStore("defaultServerUrl", url ? normalizeServerUrl(url) : undefined)) + return + } + setStore("defaultServerUrl", normalizeServerUrl(result)) + } + + createEffect(() => { + refreshDefaultServerUrl() }) return ( @@ -161,33 +176,16 @@ export function StatusPopover() { placement="bottom-end" shift={-136} > -
+
- + {serverCount() > 0 ? `${serverCount()} ` : ""} {language.t("status.popover.tab.servers")} @@ -212,7 +210,7 @@ export function StatusPopover() { {(url) => { const isActive = () => url === server.url - const isDefault = () => url === defaultServerUrl() + const isDefault = () => url === store.defaultServerUrl const status = () => store.status[url] const isBlocked = () => status()?.healthy === false const [truncated, setTruncated] = createSignal(false) @@ -294,7 +292,7 @@ export function StatusPopover() { @@ -321,7 +319,7 @@ export function StatusPopover() { type="button" class="flex items-center gap-2 w-full h-8 pl-3 pr-2 py-1 rounded-md hover:bg-surface-raised-base-hover transition-colors text-left" onClick={() => toggleMcp(item.name)} - disabled={loading() === item.name} + disabled={store.loading === item.name} >
event.stopPropagation()}> toggleMcp(item.name)} />
diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx index 02d561fbaf..d388448024 100644 --- a/packages/app/src/components/terminal.tsx +++ b/packages/app/src/components/terminal.tsx @@ -5,6 +5,8 @@ import { monoFontFamily, useSettings } from "@/context/settings" import { SerializeAddon } from "@/addons/serialize" import { LocalPTY } from "@/context/terminal" import { resolveThemeVariant, useTheme, withAlpha, type HexColor } from "@opencode-ai/ui/theme" +import { useLanguage } from "@/context/language" +import { showToast } from "@opencode-ai/ui/toast" export interface TerminalProps extends ComponentProps<"div"> { pty: LocalPTY @@ -14,6 +16,19 @@ export interface TerminalProps extends ComponentProps<"div"> { onConnectError?: (error: unknown) => void } +let shared: Promise<{ mod: typeof import("ghostty-web"); ghostty: Ghostty }> | undefined + +const loadGhostty = () => { + if (shared) return shared + shared = import("ghostty-web") + .then(async (mod) => ({ mod, ghostty: await mod.Ghostty.load() })) + .catch((err) => { + shared = undefined + throw err + }) + return shared +} + type TerminalColors = { background: string foreground: string @@ -40,6 +55,7 @@ export const Terminal = (props: TerminalProps) => { const sdk = useSDK() const settings = useSettings() const theme = useTheme() + const language = useLanguage() let container!: HTMLDivElement const [local, others] = splitProps(props, ["pty", "class", "classList", "onConnect", "onConnectError"]) let ws: WebSocket | undefined @@ -50,8 +66,20 @@ export const Terminal = (props: TerminalProps) => { let handleResize: () => void let handleTextareaFocus: () => void let handleTextareaBlur: () => void - let reconnect: number | undefined let disposed = false + const cleanups: VoidFunction[] = [] + + const cleanup = () => { + if (!cleanups.length) return + const fns = cleanups.splice(0).reverse() + for (const fn of fns) { + try { + fn() + } catch { + // ignore + } + } + } const getTerminalColors = (): TerminalColors => { const mode = theme.mode() @@ -107,188 +135,237 @@ export const Terminal = (props: TerminalProps) => { focusTerminal() } - onMount(async () => { - const mod = await import("ghostty-web") - ghostty = await mod.Ghostty.load() + onMount(() => { + const run = async () => { + const loaded = await loadGhostty() + if (disposed) return - const once = { value: false } + const mod = loaded.mod + const g = loaded.ghostty - const url = new URL(sdk.url + `/pty/${local.pty.id}/connect?directory=${encodeURIComponent(sdk.directory)}`) - if (window.__OPENCODE__?.serverPassword) { - url.username = "opencode" - url.password = window.__OPENCODE__?.serverPassword - } - const socket = new WebSocket(url) - ws = socket + const once = { value: false } - const t = new mod.Terminal({ - cursorBlink: true, - cursorStyle: "bar", - fontSize: 14, - fontFamily: monoFontFamily(settings.appearance.font()), - allowTransparency: true, - theme: terminalColors(), - scrollback: 10_000, - ghostty, - }) - term = t - - const copy = () => { - const selection = t.getSelection() - if (!selection) return false - - const body = document.body - if (body) { - const textarea = document.createElement("textarea") - textarea.value = selection - textarea.setAttribute("readonly", "") - textarea.style.position = "fixed" - textarea.style.opacity = "0" - body.appendChild(textarea) - textarea.select() - const copied = document.execCommand("copy") - body.removeChild(textarea) - if (copied) return true + const url = new URL(sdk.url + `/pty/${local.pty.id}/connect?directory=${encodeURIComponent(sdk.directory)}`) + if (window.__OPENCODE__?.serverPassword) { + url.username = "opencode" + url.password = window.__OPENCODE__?.serverPassword } - - const clipboard = navigator.clipboard - if (clipboard?.writeText) { - clipboard.writeText(selection).catch(() => {}) - return true - } - - return false - } - - t.attachCustomKeyEventHandler((event) => { - const key = event.key.toLowerCase() - - if (event.ctrlKey && event.shiftKey && !event.metaKey && key === "c") { - copy() - return true - } - - if (event.metaKey && !event.ctrlKey && !event.altKey && key === "c") { - if (!t.hasSelection()) return true - copy() - return true - } - - // allow for ctrl-` to toggle terminal in parent - if (event.ctrlKey && key === "`") { - return true - } - - return false - }) - - fitAddon = new mod.FitAddon() - serializeAddon = new SerializeAddon() - t.loadAddon(serializeAddon) - t.loadAddon(fitAddon) - - t.open(container) - container.addEventListener("pointerdown", handlePointerDown) - - handleTextareaFocus = () => { - t.options.cursorBlink = true - } - handleTextareaBlur = () => { - t.options.cursorBlink = false - } - - t.textarea?.addEventListener("focus", handleTextareaFocus) - t.textarea?.addEventListener("blur", handleTextareaBlur) - - focusTerminal() - - if (local.pty.buffer) { - if (local.pty.rows && local.pty.cols) { - t.resize(local.pty.cols, local.pty.rows) - } - t.write(local.pty.buffer, () => { - if (local.pty.scrollY) { - t.scrollToLine(local.pty.scrollY) - } - fitAddon.fit() + const socket = new WebSocket(url) + cleanups.push(() => { + if (socket.readyState !== WebSocket.CLOSED && socket.readyState !== WebSocket.CLOSING) socket.close() }) - } + if (disposed) { + cleanup() + return + } + ws = socket - fitAddon.observeResize() - handleResize = () => fitAddon.fit() - window.addEventListener("resize", handleResize) - t.onResize(async (size) => { - if (socket.readyState === WebSocket.OPEN) { - await sdk.client.pty + const t = new mod.Terminal({ + cursorBlink: true, + cursorStyle: "bar", + fontSize: 14, + fontFamily: monoFontFamily(settings.appearance.font()), + allowTransparency: true, + theme: terminalColors(), + scrollback: 10_000, + ghostty: g, + }) + cleanups.push(() => t.dispose()) + if (disposed) { + cleanup() + return + } + ghostty = g + term = t + + const copy = () => { + const selection = t.getSelection() + if (!selection) return false + + const body = document.body + if (body) { + const textarea = document.createElement("textarea") + textarea.value = selection + textarea.setAttribute("readonly", "") + textarea.style.position = "fixed" + textarea.style.opacity = "0" + body.appendChild(textarea) + textarea.select() + const copied = document.execCommand("copy") + body.removeChild(textarea) + if (copied) return true + } + + const clipboard = navigator.clipboard + if (clipboard?.writeText) { + clipboard.writeText(selection).catch(() => {}) + return true + } + + return false + } + + t.attachCustomKeyEventHandler((event) => { + const key = event.key.toLowerCase() + + if (event.ctrlKey && event.shiftKey && !event.metaKey && key === "c") { + copy() + return true + } + + if (event.metaKey && !event.ctrlKey && !event.altKey && key === "c") { + if (!t.hasSelection()) return true + copy() + return true + } + + // allow for ctrl-` to toggle terminal in parent + if (event.ctrlKey && key === "`") { + return true + } + + return false + }) + + const fit = new mod.FitAddon() + const serializer = new SerializeAddon() + cleanups.push(() => (fit as unknown as { dispose?: VoidFunction }).dispose?.()) + t.loadAddon(serializer) + t.loadAddon(fit) + fitAddon = fit + serializeAddon = serializer + + t.open(container) + container.addEventListener("pointerdown", handlePointerDown) + cleanups.push(() => container.removeEventListener("pointerdown", handlePointerDown)) + + handleTextareaFocus = () => { + t.options.cursorBlink = true + } + handleTextareaBlur = () => { + t.options.cursorBlink = false + } + + t.textarea?.addEventListener("focus", handleTextareaFocus) + t.textarea?.addEventListener("blur", handleTextareaBlur) + cleanups.push(() => t.textarea?.removeEventListener("focus", handleTextareaFocus)) + cleanups.push(() => t.textarea?.removeEventListener("blur", handleTextareaBlur)) + + focusTerminal() + + if (local.pty.buffer) { + if (local.pty.rows && local.pty.cols) { + t.resize(local.pty.cols, local.pty.rows) + } + t.write(local.pty.buffer, () => { + if (local.pty.scrollY) { + t.scrollToLine(local.pty.scrollY) + } + fitAddon.fit() + }) + } + + fit.observeResize() + handleResize = () => fit.fit() + window.addEventListener("resize", handleResize) + cleanups.push(() => window.removeEventListener("resize", handleResize)) + const onResize = t.onResize(async (size) => { + if (socket.readyState === WebSocket.OPEN) { + await sdk.client.pty + .update({ + ptyID: local.pty.id, + size: { + cols: size.cols, + rows: size.rows, + }, + }) + .catch(() => {}) + } + }) + cleanups.push(() => (onResize as unknown as { dispose?: VoidFunction }).dispose?.()) + const onData = t.onData((data) => { + if (socket.readyState === WebSocket.OPEN) { + socket.send(data) + } + }) + cleanups.push(() => (onData as unknown as { dispose?: VoidFunction }).dispose?.()) + const onKey = t.onKey((key) => { + if (key.key == "Enter") { + props.onSubmit?.() + } + }) + cleanups.push(() => (onKey as unknown as { dispose?: VoidFunction }).dispose?.()) + // t.onScroll((ydisp) => { + // console.log("Scroll position:", ydisp) + // }) + + const handleOpen = () => { + local.onConnect?.() + sdk.client.pty .update({ ptyID: local.pty.id, size: { - cols: size.cols, - rows: size.rows, + cols: t.cols, + rows: t.rows, }, }) .catch(() => {}) } - }) - t.onData((data) => { - if (socket.readyState === WebSocket.OPEN) { - socket.send(data) + socket.addEventListener("open", handleOpen) + cleanups.push(() => socket.removeEventListener("open", handleOpen)) + + const handleMessage = (event: MessageEvent) => { + t.write(event.data) } - }) - t.onKey((key) => { - if (key.key == "Enter") { - props.onSubmit?.() - } - }) - // t.onScroll((ydisp) => { - // console.log("Scroll position:", ydisp) - // }) - socket.addEventListener("open", () => { - local.onConnect?.() - sdk.client.pty - .update({ - ptyID: local.pty.id, - size: { - cols: t.cols, - rows: t.rows, - }, - }) - .catch(() => {}) - }) - socket.addEventListener("message", (event) => { - t.write(event.data) - }) - socket.addEventListener("error", (error) => { - if (disposed) return - if (once.value) return - once.value = true - console.error("WebSocket error:", error) - local.onConnectError?.(error) - }) - socket.addEventListener("close", (event) => { - if (disposed) return - // Normal closure (code 1000) means PTY process exited - server event handles cleanup - // For other codes (network issues, server restart), trigger error handler - if (event.code !== 1000) { + socket.addEventListener("message", handleMessage) + cleanups.push(() => socket.removeEventListener("message", handleMessage)) + + const handleError = (error: Event) => { + if (disposed) return if (once.value) return once.value = true - local.onConnectError?.(new Error(`WebSocket closed abnormally: ${event.code}`)) + console.error("WebSocket error:", error) + local.onConnectError?.(error) } + socket.addEventListener("error", handleError) + cleanups.push(() => socket.removeEventListener("error", handleError)) + + const handleClose = (event: CloseEvent) => { + if (disposed) return + // Normal closure (code 1000) means PTY process exited - server event handles cleanup + // For other codes (network issues, server restart), trigger error handler + if (event.code !== 1000) { + if (once.value) return + once.value = true + local.onConnectError?.(new Error(`WebSocket closed abnormally: ${event.code}`)) + } + } + socket.addEventListener("close", handleClose) + cleanups.push(() => socket.removeEventListener("close", handleClose)) + } + + void run().catch((err) => { + if (disposed) return + showToast({ + variant: "error", + title: language.t("terminal.connectionLost.title"), + description: err instanceof Error ? err.message : language.t("terminal.connectionLost.description"), + }) + local.onConnectError?.(err) }) }) onCleanup(() => { disposed = true - if (handleResize) { - window.removeEventListener("resize", handleResize) - } - container.removeEventListener("pointerdown", handlePointerDown) - term?.textarea?.removeEventListener("focus", handleTextareaFocus) - term?.textarea?.removeEventListener("blur", handleTextareaBlur) - const t = term if (serializeAddon && props.onCleanup && t) { - const buffer = serializeAddon.serialize() + const buffer = (() => { + try { + return serializeAddon.serialize() + } catch { + return "" + } + })() props.onCleanup({ ...local.pty, buffer, @@ -298,8 +375,7 @@ export const Terminal = (props: TerminalProps) => { }) } - ws?.close() - t?.dispose() + cleanup() }) return ( diff --git a/packages/app/src/components/titlebar.tsx b/packages/app/src/components/titlebar.tsx index 159216a4f7..e3831c70fe 100644 --- a/packages/app/src/components/titlebar.tsx +++ b/packages/app/src/components/titlebar.tsx @@ -1,8 +1,10 @@ -import { createEffect, createMemo, Show } from "solid-js" +import { createEffect, createMemo, Show, untrack } from "solid-js" +import { createStore } from "solid-js/store" +import { useLocation, useNavigate } from "@solidjs/router" import { IconButton } from "@opencode-ai/ui/icon-button" import { Icon } from "@opencode-ai/ui/icon" import { Button } from "@opencode-ai/ui/button" -import { TooltipKeybind } from "@opencode-ai/ui/tooltip" +import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip" import { useTheme } from "@opencode-ai/ui/theme" import { useLayout } from "@/context/layout" @@ -16,11 +18,68 @@ export function Titlebar() { const command = useCommand() const language = useLanguage() const theme = useTheme() + const navigate = useNavigate() + const location = useLocation() const mac = createMemo(() => platform.platform === "desktop" && platform.os === "macos") const windows = createMemo(() => platform.platform === "desktop" && platform.os === "windows") const web = createMemo(() => platform.platform === "web") + const [history, setHistory] = createStore({ + stack: [] as string[], + index: 0, + action: undefined as "back" | "forward" | undefined, + }) + + const path = () => `${location.pathname}${location.search}${location.hash}` + + createEffect(() => { + const current = path() + + untrack(() => { + if (!history.stack.length) { + const stack = current === "/" ? ["/"] : ["/", current] + setHistory({ stack, index: stack.length - 1 }) + return + } + + const active = history.stack[history.index] + if (current === active) { + if (history.action) setHistory("action", undefined) + return + } + + if (history.action) { + setHistory("action", undefined) + return + } + + const next = history.stack.slice(0, history.index + 1).concat(current) + setHistory({ stack: next, index: next.length - 1 }) + }) + }) + + const canBack = createMemo(() => history.index > 0) + const canForward = createMemo(() => history.index < history.stack.length - 1) + + const back = () => { + if (!canBack()) return + const index = history.index - 1 + const to = history.stack[index] + if (!to) return + setHistory({ index, action: "back" }) + navigate(to) + } + + const forward = () => { + if (!canForward()) return + const index = history.index + 1 + const to = history.stack[index] + if (!to) return + setHistory({ index, action: "forward" }) + navigate(to) + } + const getWin = () => { if (platform.platform !== "desktop") return @@ -106,34 +165,58 @@ export function Titlebar() { />
- - + + - - + +
+
[]>([]) - const [suspendCount, setSuspendCount] = createSignal(0) + const [store, setStore] = createStore({ + registrations: [] as Accessor[], + suspendCount: 0, + }) const [catalog, setCatalog, _, catalogReady] = persisted( Persist.global("command.catalog.v1"), @@ -175,7 +186,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex const seen = new Set() const all: CommandOption[] = [] - for (const reg of registrations()) { + for (const reg of store.registrations) { for (const opt of reg()) { if (seen.has(opt.id)) continue seen.add(opt.id) @@ -221,7 +232,31 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex ] }) - const suspended = () => suspendCount() > 0 + const suspended = () => store.suspendCount > 0 + + const palette = createMemo(() => { + const config = settings.keybinds.get(PALETTE_ID) ?? DEFAULT_PALETTE_KEYBIND + const keybinds = parseKeybind(config) + return new Set(keybinds.map((kb) => signature(kb.key, kb.ctrl, kb.meta, kb.shift, kb.alt))) + }) + + const keymap = createMemo(() => { + const map = new Map() + for (const option of options()) { + if (option.id.startsWith(SUGGESTED_PREFIX)) continue + if (option.disabled) continue + if (!option.keybind) continue + + const keybinds = parseKeybind(option.keybind) + for (const kb of keybinds) { + if (!kb.key) continue + const sig = signature(kb.key, kb.ctrl, kb.meta, kb.shift, kb.alt) + if (map.has(sig)) continue + map.set(sig, option) + } + } + return map + }) const run = (id: string, source?: "palette" | "keybind" | "slash") => { for (const option of options()) { @@ -239,24 +274,18 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex const handleKeyDown = (event: KeyboardEvent) => { if (suspended() || dialog.active) return - const paletteKeybinds = parseKeybind(settings.keybinds.get(PALETTE_ID) ?? DEFAULT_PALETTE_KEYBIND) - if (matchKeybind(paletteKeybinds, event)) { + const sig = signatureFromEvent(event) + + if (palette().has(sig)) { event.preventDefault() showPalette() return } - for (const option of options()) { - if (option.disabled) continue - if (!option.keybind) continue - - const keybinds = parseKeybind(option.keybind) - if (matchKeybind(keybinds, event)) { - event.preventDefault() - option.onSelect?.("keybind") - return - } - } + const option = keymap().get(sig) + if (!option) return + event.preventDefault() + option.onSelect?.("keybind") } onMount(() => { @@ -270,9 +299,9 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex return { register(cb: () => CommandOption[]) { const results = createMemo(cb) - setRegistrations((arr) => [results, ...arr]) + setStore("registrations", (arr) => [results, ...arr]) onCleanup(() => { - setRegistrations((arr) => arr.filter((x) => x !== results)) + setStore("registrations", (arr) => arr.filter((x) => x !== results)) }) }, trigger(id: string, source?: "palette" | "keybind" | "slash") { @@ -294,7 +323,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex }, show: showPalette, keybinds(enabled: boolean) { - setSuspendCount((count) => count + (enabled ? -1 : 1)) + setStore("suspendCount", (count) => count + (enabled ? -1 : 1)) }, suspended, get catalog() { diff --git a/packages/app/src/context/comments.tsx b/packages/app/src/context/comments.tsx index 41123042d8..f555145874 100644 --- a/packages/app/src/context/comments.tsx +++ b/packages/app/src/context/comments.tsx @@ -1,4 +1,4 @@ -import { batch, createMemo, createRoot, createSignal, onCleanup } from "solid-js" +import { batch, createMemo, createRoot, onCleanup } from "solid-js" import { createStore } from "solid-js/store" import { createSimpleContext } from "@opencode-ai/ui/context" import { useParams } from "@solidjs/router" @@ -37,8 +37,16 @@ function createCommentSession(dir: string, id: string | undefined) { }), ) - const [focus, setFocus] = createSignal(null) - const [active, setActive] = createSignal(null) + const [state, setState] = createStore({ + focus: null as CommentFocus | null, + active: null as CommentFocus | null, + }) + + const setFocus = (value: CommentFocus | null | ((value: CommentFocus | null) => CommentFocus | null)) => + setState("focus", value) + + const setActive = (value: CommentFocus | null | ((value: CommentFocus | null) => CommentFocus | null)) => + setState("active", value) const list = (file: string) => store.comments[file] ?? [] @@ -74,10 +82,10 @@ function createCommentSession(dir: string, id: string | undefined) { all, add, remove, - focus: createMemo(() => focus()), + focus: createMemo(() => state.focus), setFocus, clearFocus: () => setFocus(null), - active: createMemo(() => active()), + active: createMemo(() => state.active), setActive, clearActive: () => setActive(null), } diff --git a/packages/app/src/context/file.tsx b/packages/app/src/context/file.tsx index 15e3d14bb5..56804e5767 100644 --- a/packages/app/src/context/file.tsx +++ b/packages/app/src/context/file.tsx @@ -1,7 +1,7 @@ import { createEffect, createMemo, createRoot, onCleanup } from "solid-js" import { createStore, produce } from "solid-js/store" import { createSimpleContext } from "@opencode-ai/ui/context" -import type { FileContent } from "@kilocode/sdk/v2" // kilocode_change +import type { FileContent, FileNode } from "@kilocode/sdk/v2" // kilocode_change import { showToast } from "@opencode-ai/ui/toast" import { useParams } from "@solidjs/router" import { getFilename } from "@opencode-ai/util/path" @@ -39,6 +39,14 @@ export type FileState = { content?: FileContent } +type DirectoryState = { + expanded: boolean + loaded?: boolean + loading?: boolean + error?: string + children?: string[] +} + function stripFileProtocol(input: string) { if (!input.startsWith("file://")) return input return input.slice("file://".length) @@ -57,6 +65,62 @@ function stripQueryAndHash(input: string) { return input } +function unquoteGitPath(input: string) { + if (!input.startsWith('"')) return input + if (!input.endsWith('"')) return input + const body = input.slice(1, -1) + const bytes: number[] = [] + + for (let i = 0; i < body.length; i++) { + const char = body[i]! + if (char !== "\\") { + bytes.push(char.charCodeAt(0)) + continue + } + + const next = body[i + 1] + if (!next) { + bytes.push("\\".charCodeAt(0)) + continue + } + + if (next >= "0" && next <= "7") { + const chunk = body.slice(i + 1, i + 4) + const match = chunk.match(/^[0-7]{1,3}/) + if (!match) { + bytes.push(next.charCodeAt(0)) + i++ + continue + } + bytes.push(parseInt(match[0], 8)) + i += match[0].length + continue + } + + const escaped = + next === "n" + ? "\n" + : next === "r" + ? "\r" + : next === "t" + ? "\t" + : next === "b" + ? "\b" + : next === "f" + ? "\f" + : next === "v" + ? "\v" + : next === "\\" || next === '"' + ? next + : undefined + + bytes.push((escaped ?? next).charCodeAt(0)) + i++ + } + + return new TextDecoder().decode(new Uint8Array(bytes)) +} + export function selectionFromLines(range: SelectedLineRange): FileSelection { const startLine = Math.min(range.start, range.end) const endLine = Math.max(range.start, range.end) @@ -87,6 +151,28 @@ const WORKSPACE_KEY = "__workspace__" const MAX_FILE_VIEW_SESSIONS = 20 const MAX_VIEW_FILES = 500 +const MAX_FILE_CONTENT_ENTRIES = 40 +const MAX_FILE_CONTENT_BYTES = 20 * 1024 * 1024 + +const contentLru = new Map() + +function approxBytes(content: FileContent) { + const patchBytes = + content.patch?.hunks.reduce((total, hunk) => { + return total + hunk.lines.reduce((sum, line) => sum + line.length, 0) + }, 0) ?? 0 + + return (content.content.length + (content.diff?.length ?? 0) + patchBytes) * 2 +} + +function touchContent(path: string, bytes?: number) { + const prev = contentLru.get(path) + if (prev === undefined && bytes === undefined) return + const value = bytes ?? prev ?? 0 + contentLru.delete(path) + contentLru.set(path, value) +} + type ViewSession = ReturnType type ViewCacheEntry = { @@ -197,7 +283,7 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ const root = directory() const prefix = root.endsWith("/") ? root : root + "/" - let path = stripQueryAndHash(stripFileProtocol(input)) + let path = unquoteGitPath(stripQueryAndHash(stripFileProtocol(input))) if (path.startsWith(prefix)) { path = path.slice(prefix.length) @@ -229,6 +315,13 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ } const inflight = new Map>() + const treeInflight = new Map>() + + const search = (query: string, dirs: "true" | "false") => + sdk.client.find.files({ query, dirs }).then( + (x) => (x.data ?? []).map(normalize), + () => [], + ) const [store, setStore] = createStore<{ file: Record @@ -236,10 +329,51 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ file: {}, }) + const [tree, setTree] = createStore<{ + node: Record + dir: Record + }>({ + node: {}, + dir: { "": { expanded: true } }, + }) + + const evictContent = (keep?: Set) => { + const protectedSet = keep ?? new Set() + const total = () => { + return Array.from(contentLru.values()).reduce((sum, bytes) => sum + bytes, 0) + } + + while (contentLru.size > MAX_FILE_CONTENT_ENTRIES || total() > MAX_FILE_CONTENT_BYTES) { + const path = contentLru.keys().next().value + if (!path) return + + if (protectedSet.has(path)) { + touchContent(path) + if (contentLru.size <= protectedSet.size) return + continue + } + + contentLru.delete(path) + if (!store.file[path]) continue + setStore( + "file", + path, + produce((draft) => { + draft.content = undefined + draft.loaded = false + }), + ) + } + } + createEffect(() => { scope() inflight.clear() + treeInflight.clear() + contentLru.clear() setStore("file", {}) + setTree("node", {}) + setTree("dir", { "": { expanded: true } }) }) const viewCache = new Map() @@ -317,15 +451,20 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ .read({ path }) .then((x) => { if (scope() !== directory) return + const content = x.data setStore( "file", path, produce((draft) => { draft.loaded = true draft.loading = false - draft.content = x.data + draft.content = content }), ) + + if (!content) return + touchContent(path, approxBytes(content)) + evictContent(new Set([path])) }) .catch((e) => { if (scope() !== directory) return @@ -351,17 +490,182 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ return promise } + function normalizeDir(input: string) { + return normalize(input).replace(/\/+$/, "") + } + + function ensureDir(path: string) { + if (tree.dir[path]) return + setTree("dir", path, { expanded: false }) + } + + function listDir(input: string, options?: { force?: boolean }) { + const dir = normalizeDir(input) + ensureDir(dir) + + const current = tree.dir[dir] + if (!options?.force && current?.loaded) return Promise.resolve() + + const pending = treeInflight.get(dir) + if (pending) return pending + + setTree( + "dir", + dir, + produce((draft) => { + draft.loading = true + draft.error = undefined + }), + ) + + const directory = scope() + + const promise = sdk.client.file + .list({ path: dir }) + .then((x) => { + if (scope() !== directory) return + const nodes = x.data ?? [] + const prevChildren = tree.dir[dir]?.children ?? [] + const nextChildren = nodes.map((node) => node.path) + const nextSet = new Set(nextChildren) + + setTree( + "node", + produce((draft) => { + const removedDirs: string[] = [] + + for (const child of prevChildren) { + if (nextSet.has(child)) continue + const existing = draft[child] + if (existing?.type === "directory") removedDirs.push(child) + delete draft[child] + } + + if (removedDirs.length > 0) { + const keys = Object.keys(draft) + for (const key of keys) { + for (const removed of removedDirs) { + if (!key.startsWith(removed + "/")) continue + delete draft[key] + break + } + } + } + + for (const node of nodes) { + draft[node.path] = node + } + }), + ) + + setTree( + "dir", + dir, + produce((draft) => { + draft.loaded = true + draft.loading = false + draft.children = nextChildren + }), + ) + }) + .catch((e) => { + if (scope() !== directory) return + setTree( + "dir", + dir, + produce((draft) => { + draft.loading = false + draft.error = e.message + }), + ) + showToast({ + variant: "error", + title: language.t("toast.file.listFailed.title"), + description: e.message, + }) + }) + .finally(() => { + treeInflight.delete(dir) + }) + + treeInflight.set(dir, promise) + return promise + } + + function expandDir(input: string) { + const dir = normalizeDir(input) + ensureDir(dir) + setTree("dir", dir, "expanded", true) + void listDir(dir) + } + + function collapseDir(input: string) { + const dir = normalizeDir(input) + ensureDir(dir) + setTree("dir", dir, "expanded", false) + } + + function dirState(input: string) { + const dir = normalizeDir(input) + return tree.dir[dir] + } + + function children(input: string) { + const dir = normalizeDir(input) + const ids = tree.dir[dir]?.children + if (!ids) return [] + const out: FileNode[] = [] + for (const id of ids) { + const node = tree.node[id] + if (node) out.push(node) + } + return out + } + const stop = sdk.event.listen((e) => { const event = e.details if (event.type !== "file.watcher.updated") return const path = normalize(event.properties.file) if (!path) return if (path.startsWith(".git/")) return - if (!store.file[path]) return - load(path, { force: true }) + + if (store.file[path]) { + load(path, { force: true }) + } + + const kind = event.properties.event + if (kind === "change") { + const dir = (() => { + if (path === "") return "" + const node = tree.node[path] + if (node?.type !== "directory") return + return path + })() + if (dir === undefined) return + if (!tree.dir[dir]?.loaded) return + listDir(dir, { force: true }) + return + } + if (kind !== "add" && kind !== "unlink") return + + const parent = path.split("/").slice(0, -1).join("/") + if (!tree.dir[parent]?.loaded) return + + listDir(parent, { force: true }) }) - const get = (input: string) => store.file[normalize(input)] + const get = (input: string) => { + const path = normalize(input) + const file = store.file[path] + const content = file?.content + if (!content) return file + if (contentLru.has(path)) { + touchContent(path) + return file + } + touchContent(path, approxBytes(content)) + return file + } const scrollTop = (input: string) => view().scrollTop(normalize(input)) const scrollLeft = (input: string) => view().scrollLeft(normalize(input)) @@ -392,6 +696,21 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ normalize, tab, pathFromTab, + tree: { + list: listDir, + refresh: (input: string) => listDir(input, { force: true }), + state: dirState, + children, + expand: expandDir, + collapse: collapseDir, + toggle(input: string) { + if (dirState(input)?.expanded) { + collapseDir(input) + return + } + expandDir(input) + }, + }, get, load, scrollTop, @@ -400,10 +719,8 @@ export const { use: useFile, provider: FileProvider } = createSimpleContext({ setScrollLeft, selectedLines, setSelectedLines, - searchFiles: (query: string) => - sdk.client.find.files({ query, dirs: "false" }).then((x) => (x.data ?? []).map(normalize)), - searchFilesAndDirectories: (query: string) => - sdk.client.find.files({ query, dirs: "true" }).then((x) => (x.data ?? []).map(normalize)), + searchFiles: (query: string) => search(query, "false"), + searchFilesAndDirectories: (query: string) => search(query, "true"), } }, }) diff --git a/packages/app/src/context/global-sync.tsx b/packages/app/src/context/global-sync.tsx index a6fc336f63..70e6c88c1e 100644 --- a/packages/app/src/context/global-sync.tsx +++ b/packages/app/src/context/global-sync.tsx @@ -25,7 +25,7 @@ import { createStore, produce, reconcile, type SetStoreFunction, type Store } fr import { Binary } from "@opencode-ai/util/binary" import { retry } from "@opencode-ai/util/retry" import { useGlobalSDK } from "./global-sdk" -import { ErrorPage, type InitError } from "../pages/error" +import type { InitError } from "../pages/error" import { batch, createContext, @@ -190,7 +190,74 @@ function createGlobalSync() { config: {}, reload: undefined, }) - let bootstrapQueue: string[] = [] + + const queued = new Set() + let root = false + let running = false + let timer: ReturnType | undefined + + const paused = () => untrack(() => globalStore.reload) !== undefined + + const tick = () => new Promise((resolve) => setTimeout(resolve, 0)) + + const take = (count: number) => { + if (queued.size === 0) return [] as string[] + const items: string[] = [] + for (const item of queued) { + queued.delete(item) + items.push(item) + if (items.length >= count) break + } + return items + } + + const schedule = () => { + if (timer) return + timer = setTimeout(() => { + timer = undefined + void drain() + }, 0) + } + + const push = (directory: string) => { + if (!directory) return + queued.add(directory) + if (paused()) return + schedule() + } + + const refresh = () => { + root = true + if (paused()) return + schedule() + } + + async function drain() { + if (running) return + running = true + try { + while (true) { + if (paused()) return + + if (root) { + root = false + await bootstrap() + await tick() + continue + } + + const dirs = take(2) + if (dirs.length === 0) return + + await Promise.all(dirs.map((dir) => bootstrapInstance(dir))) + await tick() + } + } finally { + running = false + if (paused()) return + if (root || queued.size) schedule() + } + } createEffect(() => { if (!projectCacheReady()) return @@ -212,14 +279,8 @@ function createGlobalSync() { createEffect(() => { if (globalStore.reload !== "complete") return - if (bootstrapQueue.length) { - for (const directory of bootstrapQueue) { - bootstrapInstance(directory) - } - bootstrap() - } - bootstrapQueue = [] setGlobalStore("reload", undefined) + refresh() }) const children: Record, SetStoreFunction]> = {} @@ -227,6 +288,65 @@ function createGlobalSync() { const sessionLoads = new Map>() const sessionMeta = new Map() + const sessionRecentWindow = 4 * 60 * 60 * 1000 + const sessionRecentLimit = 50 + + function sessionUpdatedAt(session: Session) { + return session.time.updated ?? session.time.created + } + + function compareSessionRecent(a: Session, b: Session) { + const aUpdated = sessionUpdatedAt(a) + const bUpdated = sessionUpdatedAt(b) + if (aUpdated !== bUpdated) return bUpdated - aUpdated + return a.id.localeCompare(b.id) + } + + function takeRecentSessions(sessions: Session[], limit: number, cutoff: number) { + if (limit <= 0) return [] as Session[] + const selected: Session[] = [] + const seen = new Set() + for (const session of sessions) { + if (!session?.id) continue + if (seen.has(session.id)) continue + seen.add(session.id) + + if (sessionUpdatedAt(session) <= cutoff) continue + + const index = selected.findIndex((x) => compareSessionRecent(session, x) < 0) + if (index === -1) selected.push(session) + if (index !== -1) selected.splice(index, 0, session) + if (selected.length > limit) selected.pop() + } + return selected + } + + function trimSessions(input: Session[], options: { limit: number; permission: Record }) { + const limit = Math.max(0, options.limit) + const cutoff = Date.now() - sessionRecentWindow + const all = input + .filter((s) => !!s?.id) + .filter((s) => !s.time?.archived) + .sort((a, b) => a.id.localeCompare(b.id)) + + const roots = all.filter((s) => !s.parentID) + const children = all.filter((s) => !!s.parentID) + + const base = roots.slice(0, limit) + const recent = takeRecentSessions(roots.slice(limit), sessionRecentLimit, cutoff) + const keepRoots = [...base, ...recent] + + const keepRootIds = new Set(keepRoots.map((s) => s.id)) + const keepChildren = children.filter((s) => { + if (s.parentID && keepRootIds.has(s.parentID)) return true + const perms = options.permission[s.id] ?? [] + if (perms.length > 0) return true + return sessionUpdatedAt(s) > cutoff + }) + + return [...keepRoots, ...keepChildren].sort((a, b) => a.id.localeCompare(b.id)) + } + function ensureChild(directory: string) { if (!directory) console.error("No directory provided") if (!children[directory]) { @@ -325,7 +445,13 @@ function createGlobalSync() { const [store, setStore] = child(directory, { bootstrap: false }) const meta = sessionMeta.get(directory) - if (meta && meta.limit >= store.limit) return + if (meta && meta.limit >= store.limit) { + const next = trimSessions(store.session, { limit: store.limit, permission: store.permission }) + if (next.length !== store.session.length) { + setStore("session", reconcile(next, { key: "id" })) + } + return + } const promise = globalSDK.client.session .list({ directory, roots: true }) @@ -339,21 +465,9 @@ function createGlobalSync() { // a request is in-flight still get the expanded result. const limit = store.limit - const sandboxWorkspace = globalStore.project.some((p) => (p.sandboxes ?? []).includes(directory)) - if (sandboxWorkspace) { - setStore("sessionTotal", nonArchived.length) - setStore("session", reconcile(nonArchived, { key: "id" })) - sessionMeta.set(directory, { limit }) - return - } + const children = store.session.filter((s) => !!s.parentID) + const sessions = trimSessions([...nonArchived, ...children], { limit, permission: store.permission }) - const fourHoursAgo = Date.now() - 4 * 60 * 60 * 1000 - // Include up to the limit, plus any updated in the last 4 hours - const sessions = nonArchived.filter((s, i) => { - if (i < limit) return true - const updated = new Date(s.time?.updated ?? s.time?.created).getTime() - return updated > fourHoursAgo - }) // Store total session count (used for "load more" pagination) setStore("sessionTotal", nonArchived.length) setStore("session", reconcile(sessions, { key: "id" })) @@ -495,6 +609,37 @@ function createGlobalSync() { return promise } + function purgeMessageParts(setStore: SetStoreFunction, messageID: string | undefined) { + if (!messageID) return + setStore( + produce((draft) => { + delete draft.part[messageID] + }), + ) + } + + function purgeSessionData(store: Store, setStore: SetStoreFunction, sessionID: string | undefined) { + if (!sessionID) return + + const messages = store.message[sessionID] + const messageIDs = (messages ?? []).map((m) => m.id).filter((id): id is string => !!id) + + setStore( + produce((draft) => { + delete draft.message[sessionID] + delete draft.session_diff[sessionID] + delete draft.todo[sessionID] + delete draft.permission[sessionID] + delete draft.question[sessionID] + delete draft.session_status[sessionID] + + for (const messageID of messageIDs) { + delete draft.part[messageID] + } + }), + ) + } + const unsub = globalSDK.event.listen((e) => { const directory = e.name const event = e.details @@ -502,9 +647,8 @@ function createGlobalSync() { if (directory === "global") { switch (event?.type) { case "global.disposed": { - if (globalStore.reload) return - bootstrap() - break + refresh() + return } case "project.updated": { const result = Binary.search(globalStore.project, event.properties.id, (s) => s.id) @@ -528,35 +672,66 @@ function createGlobalSync() { if (!existing) return const [store, setStore] = existing + + const cleanupSessionCaches = (sessionID: string) => { + if (!sessionID) return + + const hasAny = + store.message[sessionID] !== undefined || + store.session_diff[sessionID] !== undefined || + store.todo[sessionID] !== undefined || + store.permission[sessionID] !== undefined || + store.question[sessionID] !== undefined || + store.session_status[sessionID] !== undefined + + if (!hasAny) return + + setStore( + produce((draft) => { + const messages = draft.message[sessionID] + if (messages) { + for (const message of messages) { + const id = message?.id + if (!id) continue + delete draft.part[id] + } + } + + delete draft.message[sessionID] + delete draft.session_diff[sessionID] + delete draft.todo[sessionID] + delete draft.permission[sessionID] + delete draft.question[sessionID] + delete draft.session_status[sessionID] + }), + ) + } + switch (event.type) { case "server.instance.disposed": { - if (globalStore.reload) { - bootstrapQueue.push(directory) - return - } - bootstrapInstance(directory) - break + push(directory) + return } case "session.created": { - const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) + const info = event.properties.info + const result = Binary.search(store.session, info.id, (s) => s.id) if (result.found) { - setStore("session", result.index, reconcile(event.properties.info)) + setStore("session", result.index, reconcile(info)) break } - setStore( - "session", - produce((draft) => { - draft.splice(result.index, 0, event.properties.info) - }), - ) - if (!event.properties.info.parentID) { - setStore("sessionTotal", store.sessionTotal + 1) + const next = store.session.slice() + next.splice(result.index, 0, info) + const trimmed = trimSessions(next, { limit: store.limit, permission: store.permission }) + setStore("session", reconcile(trimmed, { key: "id" })) + if (!info.parentID) { + setStore("sessionTotal", (value) => value + 1) } break } case "session.updated": { - const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) - if (event.properties.info.time.archived) { + const info = event.properties.info + const result = Binary.search(store.session, info.id, (s) => s.id) + if (info.time.archived) { if (result.found) { setStore( "session", @@ -565,24 +740,24 @@ function createGlobalSync() { }), ) } - if (event.properties.info.parentID) break + cleanupSessionCaches(info.id) + if (info.parentID) break setStore("sessionTotal", (value) => Math.max(0, value - 1)) break } if (result.found) { - setStore("session", result.index, reconcile(event.properties.info)) + setStore("session", result.index, reconcile(info)) break } - setStore( - "session", - produce((draft) => { - draft.splice(result.index, 0, event.properties.info) - }), - ) + const next = store.session.slice() + next.splice(result.index, 0, info) + const trimmed = trimSessions(next, { limit: store.limit, permission: store.permission }) + setStore("session", reconcile(trimmed, { key: "id" })) break } case "session.deleted": { - const result = Binary.search(store.session, event.properties.info.id, (s) => s.id) + const sessionID = event.properties.info.id + const result = Binary.search(store.session, sessionID, (s) => s.id) if (result.found) { setStore( "session", @@ -591,6 +766,7 @@ function createGlobalSync() { }), ) } + cleanupSessionCaches(sessionID) if (event.properties.info.parentID) break setStore("sessionTotal", (value) => Math.max(0, value - 1)) break @@ -626,18 +802,22 @@ function createGlobalSync() { break } case "message.removed": { - const messages = store.message[event.properties.sessionID] - if (!messages) break - const result = Binary.search(messages, event.properties.messageID, (m) => m.id) - if (result.found) { - setStore( - "message", - event.properties.sessionID, - produce((draft) => { - draft.splice(result.index, 1) - }), - ) - } + const sessionID = event.properties.sessionID + const messageID = event.properties.messageID + + setStore( + produce((draft) => { + const messages = draft.message[sessionID] + if (messages) { + const result = Binary.search(messages, messageID, (m) => m.id) + if (result.found) { + messages.splice(result.index, 1) + } + } + + delete draft.part[messageID] + }), + ) break } case "message.part.updated": { @@ -662,15 +842,19 @@ function createGlobalSync() { break } case "message.part.removed": { - const parts = store.part[event.properties.messageID] + const messageID = event.properties.messageID + const parts = store.part[messageID] if (!parts) break const result = Binary.search(parts, event.properties.partID, (p) => p.id) if (result.found) { setStore( - "part", - event.properties.messageID, produce((draft) => { - draft.splice(result.index, 1) + const list = draft.part[messageID] + if (!list) return + const next = Binary.search(list, event.properties.partID, (p) => p.id) + if (!next.found) return + list.splice(next.index, 1) + if (list.length === 0) delete draft.part[messageID] }), ) } @@ -767,6 +951,10 @@ function createGlobalSync() { } }) onCleanup(unsub) + onCleanup(() => { + if (!timer) return + clearTimeout(timer) + }) async function bootstrap() { const health = await globalSDK.client.global @@ -774,18 +962,23 @@ function createGlobalSync() { .then((x) => x.data) .catch(() => undefined) if (!health?.healthy) { - setGlobalStore("error", new Error(language.t("error.globalSync.connectFailed", { url: globalSDK.url }))) + showToast({ + variant: "error", + title: language.t("dialog.server.add.error"), + description: language.t("error.globalSync.connectFailed", { url: globalSDK.url }), + }) + setGlobalStore("ready", true) return } - return Promise.all([ + const tasks = [ retry(() => globalSDK.client.path.get().then((x) => { setGlobalStore("path", x.data!) }), ), retry(() => - globalSDK.client.config.get().then((x) => { + globalSDK.client.global.config.get().then((x) => { setGlobalStore("config", x.data!) }), ), @@ -809,9 +1002,22 @@ function createGlobalSync() { setGlobalStore("provider_auth", x.data ?? {}) }), ), - ]) - .then(() => setGlobalStore("ready", true)) - .catch((e) => setGlobalStore("error", e)) + ] + + const results = await Promise.allSettled(tasks) + const errors = results.filter((r): r is PromiseRejectedResult => r.status === "rejected").map((r) => r.reason) + + if (errors.length) { + const message = errors[0] instanceof Error ? errors[0].message : String(errors[0]) + const more = errors.length > 1 ? ` (+${errors.length - 1} more)` : "" + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: message + more, + }) + } + + setGlobalStore("ready", true) } onMount(() => { @@ -855,13 +1061,13 @@ function createGlobalSync() { }, child, bootstrap, - updateConfig: async (config: Config) => { + updateConfig: (config: Config) => { setGlobalStore("reload", "pending") - const response = await globalSDK.client.config.update({ config }) - setTimeout(() => { - setGlobalStore("reload", "complete") - }, 1000) - return response + return globalSDK.client.global.config.update({ config }).finally(() => { + setTimeout(() => { + setGlobalStore("reload", "complete") + }, 1000) + }) }, project: { loadSessions, @@ -877,9 +1083,6 @@ export function GlobalSyncProvider(props: ParentProps) { const value = createGlobalSync() return ( - - - {props.children} diff --git a/packages/app/src/context/highlights.tsx b/packages/app/src/context/highlights.tsx new file mode 100644 index 0000000000..cc4c021beb --- /dev/null +++ b/packages/app/src/context/highlights.tsx @@ -0,0 +1,225 @@ +import { createEffect, createSignal, onCleanup } from "solid-js" +import { createStore } from "solid-js/store" +import { createSimpleContext } from "@opencode-ai/ui/context" +import { useDialog } from "@opencode-ai/ui/context/dialog" +import { usePlatform } from "@/context/platform" +import { useSettings } from "@/context/settings" +import { persisted } from "@/utils/persist" +import { DialogReleaseNotes, type Highlight } from "@/components/dialog-release-notes" + +const CHANGELOG_URL = "https://opencode.ai/changelog.json" + +type Store = { + version?: string +} + +type ParsedRelease = { + tag?: string + highlights: Highlight[] +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value) +} + +function getText(value: unknown): string | undefined { + if (typeof value === "string") { + const text = value.trim() + return text.length > 0 ? text : undefined + } + + if (typeof value === "number") return String(value) + return +} + +function normalizeVersion(value: string | undefined) { + const text = value?.trim() + if (!text) return + return text.startsWith("v") || text.startsWith("V") ? text.slice(1) : text +} + +function parseMedia(value: unknown, alt: string): Highlight["media"] | undefined { + if (!isRecord(value)) return + const type = getText(value.type)?.toLowerCase() + const src = getText(value.src) ?? getText(value.url) + if (!src) return + if (type !== "image" && type !== "video") return + + return { type, src, alt } +} + +function parseHighlight(value: unknown): Highlight | undefined { + if (!isRecord(value)) return + + const title = getText(value.title) + if (!title) return + + const description = getText(value.description) ?? getText(value.shortDescription) + if (!description) return + + const media = parseMedia(value.media, title) + return { title, description, media } +} + +function parseRelease(value: unknown): ParsedRelease | undefined { + if (!isRecord(value)) return + const tag = getText(value.tag) ?? getText(value.tag_name) ?? getText(value.name) + + if (!Array.isArray(value.highlights)) { + return { tag, highlights: [] } + } + + const highlights = value.highlights.flatMap((group) => { + if (!isRecord(group)) return [] + + const source = getText(group.source) + if (!source) return [] + if (!source.toLowerCase().includes("desktop")) return [] + + if (Array.isArray(group.items)) { + return group.items.map((item) => parseHighlight(item)).filter((item): item is Highlight => item !== undefined) + } + + const item = parseHighlight(group) + if (!item) return [] + return [item] + }) + + return { tag, highlights } +} + +function parseChangelog(value: unknown): ParsedRelease[] | undefined { + if (Array.isArray(value)) { + return value.map(parseRelease).filter((release): release is ParsedRelease => release !== undefined) + } + + if (!isRecord(value)) return + if (!Array.isArray(value.releases)) return + + return value.releases.map(parseRelease).filter((release): release is ParsedRelease => release !== undefined) +} + +function sliceHighlights(input: { releases: ParsedRelease[]; current?: string; previous?: string }) { + const current = normalizeVersion(input.current) + const previous = normalizeVersion(input.previous) + const releases = input.releases + + const start = (() => { + if (!current) return 0 + const index = releases.findIndex((release) => normalizeVersion(release.tag) === current) + return index === -1 ? 0 : index + })() + + const end = (() => { + if (!previous) return releases.length + const index = releases.findIndex((release, i) => i >= start && normalizeVersion(release.tag) === previous) + return index === -1 ? releases.length : index + })() + + const highlights = releases.slice(start, end).flatMap((release) => release.highlights) + const seen = new Set() + const unique = highlights.filter((highlight) => { + const key = [highlight.title, highlight.description, highlight.media?.type ?? "", highlight.media?.src ?? ""].join( + "\n", + ) + if (seen.has(key)) return false + seen.add(key) + return true + }) + return unique.slice(0, 5) +} + +export const { use: useHighlights, provider: HighlightsProvider } = createSimpleContext({ + name: "Highlights", + gate: false, + init: () => { + const platform = usePlatform() + const dialog = useDialog() + const settings = useSettings() + const [store, setStore, _, ready] = persisted("highlights.v1", createStore({ version: undefined })) + + const [from, setFrom] = createSignal(undefined) + const [to, setTo] = createSignal(undefined) + const [timer, setTimer] = createSignal | undefined>(undefined) + const state = { started: false } + + const markSeen = () => { + if (!platform.version) return + setStore("version", platform.version) + } + + createEffect(() => { + if (state.started) return + if (!ready()) return + if (!settings.ready()) return + if (!platform.version) return + state.started = true + + const previous = store.version + if (!previous) { + setStore("version", platform.version) + return + } + + if (previous === platform.version) return + + setFrom(previous) + setTo(platform.version) + + if (!settings.general.releaseNotes()) { + markSeen() + return + } + + const fetcher = platform.fetch ?? fetch + const controller = new AbortController() + onCleanup(() => { + controller.abort() + const id = timer() + if (id === undefined) return + clearTimeout(id) + }) + + fetcher(CHANGELOG_URL, { + signal: controller.signal, + headers: { Accept: "application/json" }, + }) + .then((response) => (response.ok ? (response.json() as Promise) : undefined)) + .then((json) => { + if (!json) return + const releases = parseChangelog(json) + if (!releases) return + if (releases.length === 0) return + const highlights = sliceHighlights({ + releases, + current: platform.version, + previous, + }) + + if (controller.signal.aborted) return + + if (highlights.length === 0) { + markSeen() + return + } + + const timer = setTimeout(() => { + markSeen() + dialog.show(() => ) + }, 500) + setTimer(timer) + }) + .catch(() => undefined) + }) + + return { + ready, + from, + to, + get last() { + return store.version + }, + markSeen, + } + }, +}) diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx index da10e4773a..1b93c9b051 100644 --- a/packages/app/src/context/language.tsx +++ b/packages/app/src/context/language.tsx @@ -17,6 +17,7 @@ import { dict as ru } from "@/i18n/ru" import { dict as ar } from "@/i18n/ar" import { dict as no } from "@/i18n/no" import { dict as br } from "@/i18n/br" +import { dict as th } from "@/i18n/th" import { dict as uiEn } from "@opencode-ai/ui/i18n/en" import { dict as uiZh } from "@opencode-ai/ui/i18n/zh" import { dict as uiZht } from "@opencode-ai/ui/i18n/zht" @@ -31,13 +32,45 @@ import { dict as uiRu } from "@opencode-ai/ui/i18n/ru" import { dict as uiAr } from "@opencode-ai/ui/i18n/ar" import { dict as uiNo } from "@opencode-ai/ui/i18n/no" import { dict as uiBr } from "@opencode-ai/ui/i18n/br" +import { dict as uiTh } from "@opencode-ai/ui/i18n/th" -export type Locale = "en" | "zh" | "zht" | "ko" | "de" | "es" | "fr" | "da" | "ja" | "pl" | "ru" | "ar" | "no" | "br" +export type Locale = + | "en" + | "zh" + | "zht" + | "ko" + | "de" + | "es" + | "fr" + | "da" + | "ja" + | "pl" + | "ru" + | "ar" + | "no" + | "br" + | "th" type RawDictionary = typeof en & typeof uiEn type Dictionary = i18n.Flatten -const LOCALES: readonly Locale[] = ["en", "zh", "zht", "ko", "de", "es", "fr", "da", "ja", "pl", "ru", "ar", "no", "br"] +const LOCALES: readonly Locale[] = [ + "en", + "zh", + "zht", + "ko", + "de", + "es", + "fr", + "da", + "ja", + "pl", + "ru", + "ar", + "no", + "br", + "th", +] function detectLocale(): Locale { if (typeof navigator !== "object") return "en" @@ -65,6 +98,7 @@ function detectLocale(): Locale { ) return "no" if (language.toLowerCase().startsWith("pt")) return "br" + if (language.toLowerCase().startsWith("th")) return "th" } return "en" @@ -94,6 +128,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont if (store.locale === "ar") return "ar" if (store.locale === "no") return "no" if (store.locale === "br") return "br" + if (store.locale === "th") return "th" return "en" }) @@ -118,6 +153,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont if (locale() === "ar") return { ...base, ...i18n.flatten({ ...ar, ...uiAr }) } if (locale() === "no") return { ...base, ...i18n.flatten({ ...no, ...uiNo }) } if (locale() === "br") return { ...base, ...i18n.flatten({ ...br, ...uiBr }) } + if (locale() === "th") return { ...base, ...i18n.flatten({ ...th, ...uiTh }) } return { ...base, ...i18n.flatten({ ...ko, ...uiKo }) } }) @@ -138,6 +174,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont ar: "language.ar", no: "language.no", br: "language.br", + th: "language.th", } const label = (value: Locale) => t(labelKey[value]) diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx index 55ba4de6fe..0713e90cf9 100644 --- a/packages/app/src/context/layout.tsx +++ b/packages/app/src/context/layout.tsx @@ -51,16 +51,37 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const migrate = (value: unknown) => { if (!isRecord(value)) return value + const sidebar = value.sidebar - if (!isRecord(sidebar)) return value - if (typeof sidebar.workspaces !== "boolean") return value - return { - ...value, - sidebar: { + const migratedSidebar = (() => { + if (!isRecord(sidebar)) return sidebar + if (typeof sidebar.workspaces !== "boolean") return sidebar + return { ...sidebar, workspaces: {}, workspacesDefault: sidebar.workspaces, - }, + } + })() + + const fileTree = value.fileTree + const migratedFileTree = (() => { + if (!isRecord(fileTree)) return fileTree + if (fileTree.tab === "changes" || fileTree.tab === "all") return fileTree + + const width = typeof fileTree.width === "number" ? fileTree.width : 344 + return { + ...fileTree, + opened: true, + width: width === 260 ? 344 : width, + tab: "changes", + } + })() + + if (migratedSidebar === sidebar && migratedFileTree === fileTree) return value + return { + ...value, + sidebar: migratedSidebar, + fileTree: migratedFileTree, } } @@ -80,7 +101,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, review: { diffStyle: "split" as ReviewDiffStyle, - panelOpened: true, + }, + fileTree: { + opened: true, + width: 344, + tab: "changes" as "changes" | "all", }, session: { width: 600, @@ -218,7 +243,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( } function enrich(project: { worktree: string; expanded: boolean }) { - const [childStore] = globalSync.child(project.worktree) + const [childStore] = globalSync.child(project.worktree, { bootstrap: false }) const projectID = childStore.project const metadata = projectID ? globalSync.data.project.find((x) => x.id === projectID) @@ -449,6 +474,46 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setStore("review", "diffStyle", diffStyle) }, }, + fileTree: { + opened: createMemo(() => store.fileTree?.opened ?? true), + width: createMemo(() => store.fileTree?.width ?? 344), + tab: createMemo(() => store.fileTree?.tab ?? "changes"), + setTab(tab: "changes" | "all") { + if (!store.fileTree) { + setStore("fileTree", { opened: true, width: 344, tab }) + return + } + setStore("fileTree", "tab", tab) + }, + open() { + if (!store.fileTree) { + setStore("fileTree", { opened: true, width: 344, tab: "changes" }) + return + } + setStore("fileTree", "opened", true) + }, + close() { + if (!store.fileTree) { + setStore("fileTree", { opened: false, width: 344, tab: "changes" }) + return + } + setStore("fileTree", "opened", false) + }, + toggle() { + if (!store.fileTree) { + setStore("fileTree", { opened: true, width: 344, tab: "changes" }) + return + } + setStore("fileTree", "opened", (x) => !x) + }, + resize(width: number) { + if (!store.fileTree) { + setStore("fileTree", { opened: true, width, tab: "changes" }) + return + } + setStore("fileTree", "width", width) + }, + }, session: { width: createMemo(() => store.session?.width ?? 600), resize(width: number) { @@ -490,7 +555,6 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const s = createMemo(() => store.sessionView[key()] ?? { scroll: {} }) const terminalOpened = createMemo(() => store.terminal?.opened ?? false) - const reviewPanelOpened = createMemo(() => store.review?.panelOpened ?? true) function setTerminalOpened(next: boolean) { const current = store.terminal @@ -504,18 +568,6 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setStore("terminal", "opened", next) } - function setReviewPanelOpened(next: boolean) { - const current = store.review - if (!current) { - setStore("review", { diffStyle: "split" as ReviewDiffStyle, panelOpened: next }) - return - } - - const value = current.panelOpened ?? true - if (value === next) return - setStore("review", "panelOpened", next) - } - return { scroll(tab: string) { return scroll.scroll(key(), tab) @@ -535,18 +587,6 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( setTerminalOpened(!terminalOpened()) }, }, - reviewPanel: { - opened: reviewPanelOpened, - open() { - setReviewPanelOpened(true) - }, - close() { - setReviewPanelOpened(false) - }, - toggle() { - setReviewPanelOpened(!reviewPanelOpened()) - }, - }, review: { open: createMemo(() => s().reviewOpen), setOpen(open: string[]) { @@ -584,10 +624,11 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( const tabs = createMemo(() => store.sessionTabs[key()] ?? { all: [] }) return { tabs, - active: createMemo(() => tabs().active), - all: createMemo(() => tabs().all), + active: createMemo(() => (tabs().active === "review" ? undefined : tabs().active)), + all: createMemo(() => tabs().all.filter((tab) => tab !== "review")), setActive(tab: string | undefined) { const session = key() + if (tab === "review") return if (!store.sessionTabs[session]) { setStore("sessionTabs", session, { all: [], active: tab }) } else { @@ -596,25 +637,18 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext( }, setAll(all: string[]) { const session = key() + const next = all.filter((tab) => tab !== "review") if (!store.sessionTabs[session]) { - setStore("sessionTabs", session, { all, active: undefined }) + setStore("sessionTabs", session, { all: next, active: undefined }) } else { - setStore("sessionTabs", session, "all", all) + setStore("sessionTabs", session, "all", next) } }, async open(tab: string) { + if (tab === "review") return const session = key() const current = store.sessionTabs[session] ?? { all: [] } - if (tab === "review") { - if (!store.sessionTabs[session]) { - setStore("sessionTabs", session, { all: [], active: tab }) - return - } - setStore("sessionTabs", session, "active", tab) - return - } - if (tab === "context") { const all = [tab, ...current.all.filter((x) => x !== tab)] if (!store.sessionTabs[session]) { diff --git a/packages/app/src/context/local.tsx b/packages/app/src/context/local.tsx index a6069de2fe..f51bb69309 100644 --- a/packages/app/src/context/local.tsx +++ b/packages/app/src/context/local.tsx @@ -1,49 +1,20 @@ -import { createStore, produce, reconcile } from "solid-js/store" -import { batch, createEffect, createMemo, onCleanup } from "solid-js" -import { filter, firstBy, flat, groupBy, mapValues, pipe, uniqueBy, values } from "remeda" -import type { FileContent, FileNode, Model, Provider, File as FileStatus } from "@kilocode/sdk/v2" // kilocode_change +import { createStore } from "solid-js/store" +import { batch, createMemo } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { useSDK } from "./sdk" import { useSync } from "./sync" import { base64Encode } from "@opencode-ai/util/encode" import { useProviders } from "@/hooks/use-providers" -import { DateTime } from "luxon" -import { Persist, persisted } from "@/utils/persist" -import { showToast } from "@opencode-ai/ui/toast" -import { useLanguage } from "@/context/language" +import { useModels } from "@/context/models" -export type LocalFile = FileNode & - Partial<{ - loaded: boolean - pinned: boolean - expanded: boolean - content: FileContent - selection: { startLine: number; startChar: number; endLine: number; endChar: number } - scrollTop: number - view: "raw" | "diff-unified" | "diff-split" - folded: string[] - selectedChange: number - status: FileStatus - }> -export type TextSelection = LocalFile["selection"] -export type View = LocalFile["view"] - -export type LocalModel = Omit & { - provider: Provider - latest?: boolean -} export type ModelKey = { providerID: string; modelID: string } -export type FileContext = { type: "file"; path: string; selection?: TextSelection } -export type ContextItem = FileContext - export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ name: "Local", init: () => { const sdk = useSDK() const sync = useSync() const providers = useProviders() - const language = useLanguage() function isModelValid(model: ModelKey) { const provider = providers.all().find((x) => x.id === model.providerID) @@ -112,18 +83,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ })() const model = (() => { - const [store, setStore, _, modelReady] = persisted( - Persist.global("model", ["model.v1"]), - createStore<{ - user: (ModelKey & { visibility: "show" | "hide"; favorite?: boolean })[] - recent: ModelKey[] - variant?: Record - }>({ - user: [], - recent: [], - variant: {}, - }), - ) + const models = useModels() const [ephemeral, setEphemeral] = createStore<{ model: Record @@ -131,57 +91,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ model: {}, }) - const available = createMemo(() => - providers.connected().flatMap((p) => - Object.values(p.models).map((m) => ({ - ...m, - provider: p, - })), - ), - ) - - const latest = createMemo(() => - pipe( - available(), - filter((x) => Math.abs(DateTime.fromISO(x.release_date).diffNow().as("months")) < 6), - groupBy((x) => x.provider.id), - mapValues((models) => - pipe( - models, - groupBy((x) => x.family), - values(), - (groups) => - groups.flatMap((g) => { - const first = firstBy(g, [(x) => x.release_date, "desc"]) - return first ? [{ modelID: first.id, providerID: first.provider.id }] : [] - }), - ), - ), - values(), - flat(), - ), - ) - - const latestSet = createMemo(() => new Set(latest().map((x) => `${x.providerID}:${x.modelID}`))) - - const userVisibilityMap = createMemo(() => { - const map = new Map() - for (const item of store.user) { - map.set(`${item.providerID}:${item.modelID}`, item.visibility) - } - return map - }) - - const list = createMemo(() => - available().map((m) => ({ - ...m, - name: m.name.replace("(latest)", "").trim(), - latest: m.name.includes("(latest)"), - })), - ) - - const find = (key: ModelKey) => list().find((m) => m.id === key?.modelID && m.provider.id === key.providerID) - const fallbackModel = createMemo(() => { if (sync.data.config.model) { const [providerID, modelID] = sync.data.config.model.split("/") @@ -193,7 +102,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } } - for (const item of store.recent) { + for (const item of models.recent.list()) { if (isModelValid(item)) { return item } @@ -225,10 +134,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ fallbackModel, ) if (!key) return undefined - return find(key) + return models.find(key) }) - const recent = createMemo(() => store.recent.map(find).filter(Boolean)) + const recent = createMemo(() => models.recent.list().map(models.find).filter(Boolean)) const cycle = (direction: 1 | -1) => { const recentList = recent() @@ -253,54 +162,32 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ }) } - function updateVisibility(model: ModelKey, visibility: "show" | "hide") { - const index = store.user.findIndex((x) => x.modelID === model.modelID && x.providerID === model.providerID) - if (index >= 0) { - setStore("user", index, { visibility }) - } else { - setStore("user", store.user.length, { ...model, visibility }) - } - } - return { - ready: modelReady, + ready: models.ready, current, recent, - list, + list: models.list, cycle, set(model: ModelKey | undefined, options?: { recent?: boolean }) { batch(() => { const currentAgent = agent.current() const next = model ?? fallbackModel() if (currentAgent) setEphemeral("model", currentAgent.name, next) - if (model) updateVisibility(model, "show") - if (options?.recent && model) { - const uniq = uniqueBy([model, ...store.recent], (x) => x.providerID + x.modelID) - if (uniq.length > 5) uniq.pop() - setStore("recent", uniq) - } + if (model) models.setVisibility(model, true) + if (options?.recent && model) models.recent.push(model) }) }, visible(model: ModelKey) { - const key = `${model.providerID}:${model.modelID}` - const visibility = userVisibilityMap().get(key) - if (visibility === "hide") return false - if (visibility === "show") return true - if (latestSet().has(key)) return true - // For models without valid release_date (e.g. custom models), show by default - const m = find(model) - if (!m?.release_date || !DateTime.fromISO(m.release_date).isValid) return true - return false + return models.visible(model) }, setVisibility(model: ModelKey, visible: boolean) { - updateVisibility(model, visible ? "show" : "hide") + models.setVisibility(model, visible) }, variant: { current() { const m = current() if (!m) return undefined - const key = `${m.provider.id}/${m.id}` - return store.variant?.[key] + return models.variant.get({ providerID: m.provider.id, modelID: m.id }) }, list() { const m = current() @@ -311,12 +198,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ set(value: string | undefined) { const m = current() if (!m) return - const key = `${m.provider.id}/${m.id}` - if (!store.variant) { - setStore("variant", { [key]: value }) - } else { - setStore("variant", key, value) - } + models.variant.set({ providerID: m.provider.id, modelID: m.id }, value) }, cycle() { const variants = this.list() @@ -337,247 +219,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ } })() - const file = (() => { - const [store, setStore] = createStore<{ - node: Record - }>({ - node: {}, // Object.fromEntries(sync.data.node.map((x) => [x.path, x])), - }) - - const scope = createMemo(() => sdk.directory) - createEffect(() => { - scope() - setStore("node", {}) - }) - - // const changeset = createMemo(() => new Set(sync.data.changes.map((f) => f.path))) - // const changes = createMemo(() => Array.from(changeset()).sort((a, b) => a.localeCompare(b))) - - // createEffect((prev: FileStatus[]) => { - // const removed = prev.filter((p) => !sync.data.changes.find((c) => c.path === p.path)) - // for (const p of removed) { - // setStore( - // "node", - // p.path, - // produce((draft) => { - // draft.status = undefined - // draft.view = "raw" - // }), - // ) - // load(p.path) - // } - // for (const p of sync.data.changes) { - // if (store.node[p.path] === undefined) { - // fetch(p.path).then(() => { - // if (store.node[p.path] === undefined) return - // setStore("node", p.path, "status", p) - // }) - // } else { - // setStore("node", p.path, "status", p) - // } - // } - // return sync.data.changes - // }, sync.data.changes) - - // const changed = (path: string) => { - // const node = store.node[path] - // if (node?.status) return true - // const set = changeset() - // if (set.has(path)) return true - // for (const p of set) { - // if (p.startsWith(path ? path + "/" : "")) return true - // } - // return false - // } - - // const resetNode = (path: string) => { - // setStore("node", path, { - // loaded: undefined, - // pinned: undefined, - // content: undefined, - // selection: undefined, - // scrollTop: undefined, - // folded: undefined, - // view: undefined, - // selectedChange: undefined, - // }) - // } - - const relative = (path: string) => path.replace(sync.data.path.directory + "/", "") - - const load = async (path: string) => { - const directory = scope() - const client = sdk.client - const relativePath = relative(path) - await client.file - .read({ path: relativePath }) - .then((x) => { - if (scope() !== directory) return - if (!store.node[relativePath]) return - setStore( - "node", - relativePath, - produce((draft) => { - draft.loaded = true - draft.content = x.data - }), - ) - }) - .catch((e) => { - if (scope() !== directory) return - showToast({ - variant: "error", - title: language.t("toast.file.loadFailed.title"), - description: e.message, - }) - }) - } - - const fetch = async (path: string) => { - const relativePath = relative(path) - const parent = relativePath.split("/").slice(0, -1).join("/") - if (parent) { - await list(parent) - } - } - - const init = async (path: string) => { - const relativePath = relative(path) - if (!store.node[relativePath]) await fetch(path) - if (store.node[relativePath]?.loaded) return - return load(relativePath) - } - - const open = async (path: string, options?: { pinned?: boolean; view?: LocalFile["view"] }) => { - const relativePath = relative(path) - if (!store.node[relativePath]) await fetch(path) - // setStore("opened", (x) => { - // if (x.includes(relativePath)) return x - // return [ - // ...opened() - // .filter((x) => x.pinned) - // .map((x) => x.path), - // relativePath, - // ] - // }) - // setStore("active", relativePath) - // context.addActive() - if (options?.pinned) setStore("node", path, "pinned", true) - if (options?.view && store.node[relativePath].view === undefined) setStore("node", path, "view", options.view) - if (store.node[relativePath]?.loaded) return - return load(relativePath) - } - - const list = async (path: string) => { - const directory = scope() - const client = sdk.client - return client.file - .list({ path: path + "/" }) - .then((x) => { - if (scope() !== directory) return - setStore( - "node", - produce((draft) => { - x.data!.forEach((node) => { - if (node.path in draft) return - draft[node.path] = node - }) - }), - ) - }) - .catch(() => {}) - } - - const searchFiles = (query: string) => sdk.client.find.files({ query, dirs: "false" }).then((x) => x.data!) - const searchFilesAndDirectories = (query: string) => - sdk.client.find.files({ query, dirs: "true" }).then((x) => x.data!) - - const unsub = sdk.event.listen((e) => { - const event = e.details - switch (event.type) { - case "file.watcher.updated": - const relativePath = relative(event.properties.file) - if (relativePath.startsWith(".git/")) return - if (store.node[relativePath]) load(relativePath) - break - } - }) - onCleanup(unsub) - - return { - node: async (path: string) => { - if (!store.node[path] || !store.node[path].loaded) { - await init(path) - } - return store.node[path] - }, - update: (path: string, node: LocalFile) => setStore("node", path, reconcile(node)), - open, - load, - init, - expand(path: string) { - setStore("node", path, "expanded", true) - if (store.node[path]?.loaded) return - setStore("node", path, "loaded", true) - list(path) - }, - collapse(path: string) { - setStore("node", path, "expanded", false) - }, - select(path: string, selection: TextSelection | undefined) { - setStore("node", path, "selection", selection) - }, - scroll(path: string, scrollTop: number) { - setStore("node", path, "scrollTop", scrollTop) - }, - view(path: string): View { - const n = store.node[path] - return n && n.view ? n.view : "raw" - }, - setView(path: string, view: View) { - setStore("node", path, "view", view) - }, - unfold(path: string, key: string) { - setStore("node", path, "folded", (xs) => { - const a = xs ?? [] - if (a.includes(key)) return a - return [...a, key] - }) - }, - fold(path: string, key: string) { - setStore("node", path, "folded", (xs) => (xs ?? []).filter((k) => k !== key)) - }, - folded(path: string) { - const n = store.node[path] - return n && n.folded ? n.folded : [] - }, - changeIndex(path: string) { - return store.node[path]?.selectedChange - }, - setChangeIndex(path: string, index: number | undefined) { - setStore("node", path, "selectedChange", index) - }, - // changes, - // changed, - children(path: string) { - return Object.values(store.node).filter( - (x) => - x.path.startsWith(path) && - x.path !== path && - !x.path.replace(new RegExp(`^${path + "/"}`), "").includes("/"), - ) - }, - searchFiles, - searchFilesAndDirectories, - relative, - } - })() - const result = { slug: createMemo(() => base64Encode(sdk.directory)), model, agent, - file, } return result }, diff --git a/packages/app/src/context/models.tsx b/packages/app/src/context/models.tsx new file mode 100644 index 0000000000..fee3c10c6d --- /dev/null +++ b/packages/app/src/context/models.tsx @@ -0,0 +1,140 @@ +import { createMemo } from "solid-js" +import { createStore } from "solid-js/store" +import { DateTime } from "luxon" +import { filter, firstBy, flat, groupBy, mapValues, pipe, uniqueBy, values } from "remeda" +import { createSimpleContext } from "@opencode-ai/ui/context" +import { useProviders } from "@/hooks/use-providers" +import { Persist, persisted } from "@/utils/persist" + +export type ModelKey = { providerID: string; modelID: string } + +type Visibility = "show" | "hide" +type User = ModelKey & { visibility: Visibility; favorite?: boolean } +type Store = { + user: User[] + recent: ModelKey[] + variant?: Record +} + +export const { use: useModels, provider: ModelsProvider } = createSimpleContext({ + name: "Models", + init: () => { + const providers = useProviders() + + const [store, setStore, _, ready] = persisted( + Persist.global("model", ["model.v1"]), + createStore({ + user: [], + recent: [], + variant: {}, + }), + ) + + const available = createMemo(() => + providers.connected().flatMap((p) => + Object.values(p.models).map((m) => ({ + ...m, + provider: p, + })), + ), + ) + + const latest = createMemo(() => + pipe( + available(), + filter((x) => Math.abs(DateTime.fromISO(x.release_date).diffNow().as("months")) < 6), + groupBy((x) => x.provider.id), + mapValues((models) => + pipe( + models, + groupBy((x) => x.family), + values(), + (groups) => + groups.flatMap((g) => { + const first = firstBy(g, [(x) => x.release_date, "desc"]) + return first ? [{ modelID: first.id, providerID: first.provider.id }] : [] + }), + ), + ), + values(), + flat(), + ), + ) + + const latestSet = createMemo(() => new Set(latest().map((x) => `${x.providerID}:${x.modelID}`))) + + const visibility = createMemo(() => { + const map = new Map() + for (const item of store.user) map.set(`${item.providerID}:${item.modelID}`, item.visibility) + return map + }) + + const list = createMemo(() => + available().map((m) => ({ + ...m, + name: m.name.replace("(latest)", "").trim(), + latest: m.name.includes("(latest)"), + })), + ) + + const find = (key: ModelKey) => list().find((m) => m.id === key.modelID && m.provider.id === key.providerID) + + function update(model: ModelKey, state: Visibility) { + const index = store.user.findIndex((x) => x.modelID === model.modelID && x.providerID === model.providerID) + if (index >= 0) { + setStore("user", index, { visibility: state }) + return + } + setStore("user", store.user.length, { ...model, visibility: state }) + } + + const visible = (model: ModelKey) => { + const key = `${model.providerID}:${model.modelID}` + const state = visibility().get(key) + if (state === "hide") return false + if (state === "show") return true + if (latestSet().has(key)) return true + const m = find(model) + if (!m?.release_date || !DateTime.fromISO(m.release_date).isValid) return true + return false + } + + const setVisibility = (model: ModelKey, state: boolean) => { + update(model, state ? "show" : "hide") + } + + const push = (model: ModelKey) => { + const uniq = uniqueBy([model, ...store.recent], (x) => x.providerID + x.modelID) + if (uniq.length > 5) uniq.pop() + setStore("recent", uniq) + } + + const variantKey = (model: ModelKey) => `${model.providerID}/${model.modelID}` + const getVariant = (model: ModelKey) => store.variant?.[variantKey(model)] + + const setVariant = (model: ModelKey, value: string | undefined) => { + const key = variantKey(model) + if (!store.variant) { + setStore("variant", { [key]: value }) + return + } + setStore("variant", key, value) + } + + return { + ready, + list, + find, + visible, + setVisibility, + recent: { + list: createMemo(() => store.recent), + push, + }, + variant: { + get: getVariant, + set: setVariant, + }, + } + }, +}) diff --git a/packages/app/src/context/notification.tsx b/packages/app/src/context/notification.tsx index 99dcc5308e..c86da1c999 100644 --- a/packages/app/src/context/notification.tsx +++ b/packages/app/src/context/notification.tsx @@ -1,5 +1,5 @@ import { createStore } from "solid-js/store" -import { createEffect, onCleanup } from "solid-js" +import { createEffect, createMemo, onCleanup } from "solid-js" import { useParams } from "@solidjs/router" import { createSimpleContext } from "@opencode-ai/ui/context" import { useGlobalSDK } from "./global-sdk" @@ -8,7 +8,8 @@ import { usePlatform } from "@/context/platform" import { useLanguage } from "@/context/language" import { useSettings } from "@/context/settings" import { Binary } from "@opencode-ai/util/binary" -import { base64Decode, base64Encode } from "@opencode-ai/util/encode" +import { base64Encode } from "@opencode-ai/util/encode" +import { decode64 } from "@/utils/base64" import { EventSessionError } from "@kilocode/sdk/v2" // kilocode_change import { Persist, persisted } from "@/utils/persist" import { playSound, soundSrc } from "@/utils/sound" @@ -52,6 +53,14 @@ export const { use: useNotification, provider: NotificationProvider } = createSi const settings = useSettings() const language = useLanguage() + const empty: Notification[] = [] + + const currentDirectory = createMemo(() => { + return decode64(params.dir) + }) + + const currentSession = createMemo(() => params.id) + const [store, setStore, _, ready] = persisted( Persist.global("notification", ["notification.v1"]), createStore({ @@ -72,13 +81,59 @@ export const { use: useNotification, provider: NotificationProvider } = createSi setStore("list", (list) => pruneNotifications([...list, notification])) } + const index = createMemo(() => { + const sessionAll = new Map() + const sessionUnseen = new Map() + const projectAll = new Map() + const projectUnseen = new Map() + + for (const notification of store.list) { + const session = notification.session + if (session) { + const list = sessionAll.get(session) + if (list) list.push(notification) + else sessionAll.set(session, [notification]) + if (!notification.viewed) { + const unseen = sessionUnseen.get(session) + if (unseen) unseen.push(notification) + else sessionUnseen.set(session, [notification]) + } + } + + const directory = notification.directory + if (directory) { + const list = projectAll.get(directory) + if (list) list.push(notification) + else projectAll.set(directory, [notification]) + if (!notification.viewed) { + const unseen = projectUnseen.get(directory) + if (unseen) unseen.push(notification) + else projectUnseen.set(directory, [notification]) + } + } + } + + return { + session: { + all: sessionAll, + unseen: sessionUnseen, + }, + project: { + all: projectAll, + unseen: projectUnseen, + }, + } + }) + const unsub = globalSDK.event.listen((e) => { - const directory = e.name const event = e.details + if (event.type !== "session.idle" && event.type !== "session.error") return + + const directory = e.name const time = Date.now() - const activeDirectory = params.dir ? base64Decode(params.dir) : undefined - const activeSession = params.id const viewed = (sessionID?: string) => { + const activeDirectory = currentDirectory() + const activeSession = currentSession() if (!activeDirectory) return false if (!activeSession) return false if (!sessionID) return false @@ -88,7 +143,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi switch (event.type) { case "session.idle": { const sessionID = event.properties.sessionID - const [syncStore] = globalSync.child(directory) + const [syncStore] = globalSync.child(directory, { bootstrap: false }) const match = Binary.search(syncStore.session, sessionID, (s) => s.id) const session = match.found ? syncStore.session[match.index] : undefined if (session?.parentID) break @@ -115,7 +170,7 @@ export const { use: useNotification, provider: NotificationProvider } = createSi } case "session.error": { const sessionID = event.properties.sessionID - const [syncStore] = globalSync.child(directory) + const [syncStore] = globalSync.child(directory, { bootstrap: false }) const match = sessionID ? Binary.search(syncStore.session, sessionID, (s) => s.id) : undefined const session = sessionID && match?.found ? syncStore.session[match.index] : undefined if (session?.parentID) break @@ -148,10 +203,10 @@ export const { use: useNotification, provider: NotificationProvider } = createSi ready, session: { all(session: string) { - return store.list.filter((n) => n.session === session) + return index().session.all.get(session) ?? empty }, unseen(session: string) { - return store.list.filter((n) => n.session === session && !n.viewed) + return index().session.unseen.get(session) ?? empty }, markViewed(session: string) { setStore("list", (n) => n.session === session, "viewed", true) @@ -159,10 +214,10 @@ export const { use: useNotification, provider: NotificationProvider } = createSi }, project: { all(directory: string) { - return store.list.filter((n) => n.directory === directory) + return index().project.all.get(directory) ?? empty }, unseen(directory: string) { - return store.list.filter((n) => n.directory === directory && !n.viewed) + return index().project.unseen.get(directory) ?? empty }, markViewed(directory: string) { setStore("list", (n) => n.directory === directory, "viewed", true) diff --git a/packages/app/src/context/permission.tsx b/packages/app/src/context/permission.tsx index 0b570a9954..3454ba3bfa 100644 --- a/packages/app/src/context/permission.tsx +++ b/packages/app/src/context/permission.tsx @@ -6,7 +6,8 @@ import { Persist, persisted } from "@/utils/persist" import { useGlobalSDK } from "@/context/global-sdk" import { useGlobalSync } from "./global-sync" import { useParams } from "@solidjs/router" -import { base64Decode, base64Encode } from "@opencode-ai/util/encode" +import { base64Encode } from "@opencode-ai/util/encode" +import { decode64 } from "@/utils/base64" type PermissionRespondFn = (input: { sessionID: string @@ -53,7 +54,7 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple const globalSync = useGlobalSync() const permissionsEnabled = createMemo(() => { - const directory = params.dir ? base64Decode(params.dir) : undefined + const directory = decode64(params.dir) if (!directory) return false const [store] = globalSync.child(directory) return hasAutoAcceptPermissionConfig(store.config.permission) @@ -66,7 +67,21 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple }), ) - const responded = new Set() + const MAX_RESPONDED = 1000 + const RESPONDED_TTL_MS = 60 * 60 * 1000 + const responded = new Map() + + function pruneResponded(now: number) { + for (const [id, ts] of responded) { + if (now - ts < RESPONDED_TTL_MS) break + responded.delete(id) + } + + for (const id of responded.keys()) { + if (responded.size <= MAX_RESPONDED) break + responded.delete(id) + } + } const respond: PermissionRespondFn = (input) => { globalSDK.client.permission.respond(input).catch(() => { @@ -75,8 +90,12 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple } function respondOnce(permission: PermissionRequest, directory?: string) { - if (responded.has(permission.id)) return - responded.add(permission.id) + const now = Date.now() + const hit = responded.has(permission.id) + responded.delete(permission.id) + responded.set(permission.id, now) + pruneResponded(now) + if (hit) return respond({ sessionID: permission.sessionID, permissionID: permission.id, diff --git a/packages/app/src/context/platform.tsx b/packages/app/src/context/platform.tsx index 89056b2c84..f6fb157f06 100644 --- a/packages/app/src/context/platform.tsx +++ b/packages/app/src/context/platform.tsx @@ -17,6 +17,12 @@ export type Platform = { /** Restart the app */ restart(): Promise + /** Navigate back in history */ + back(): void + + /** Navigate forward in history */ + forward(): void + /** Send a system notification (optional deep link) */ notify(title: string, description?: string, href?: string): Promise @@ -41,11 +47,11 @@ export type Platform = { /** Fetch override */ fetch?: typeof fetch - /** Get the configured default server URL (desktop only) */ - getDefaultServerUrl?(): Promise + /** Get the configured default server URL (platform-specific) */ + getDefaultServerUrl?(): Promise | string | null - /** Set the default server URL to use on app startup (desktop only) */ - setDefaultServerUrl?(url: string | null): Promise + /** Set the default server URL to use on app startup (platform-specific) */ + setDefaultServerUrl?(url: string | null): Promise | void /** Parse markdown to HTML using native parser (desktop only, returns unprocessed code blocks) */ parseMarkdown?(markdown: string): Promise diff --git a/packages/app/src/context/server.tsx b/packages/app/src/context/server.tsx index 7e71f20478..e0716422ad 100644 --- a/packages/app/src/context/server.tsx +++ b/packages/app/src/context/server.tsx @@ -1,6 +1,6 @@ import { createOpencodeClient } from "@kilocode/sdk/v2/client" // kilocode_change import { createSimpleContext } from "@opencode-ai/ui/context" -import { batch, createEffect, createMemo, createSignal, onCleanup } from "solid-js" +import { batch, createEffect, createMemo, onCleanup } from "solid-js" import { createStore } from "solid-js/store" import { usePlatform } from "@/context/platform" import { Persist, persisted } from "@/utils/persist" @@ -40,12 +40,17 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( }), ) - const [active, setActiveRaw] = createSignal("") + const [state, setState] = createStore({ + active: "", + healthy: undefined as boolean | undefined, + }) + + const healthy = () => state.healthy function setActive(input: string) { const url = normalizeServerUrl(input) if (!url) return - setActiveRaw(url) + setState("active", url) } function add(input: string) { @@ -54,7 +59,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( const fallback = normalizeServerUrl(props.defaultUrl) if (fallback && url === fallback) { - setActiveRaw(url) + setState("active", url) return } @@ -62,7 +67,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( if (!store.list.includes(url)) { setStore("list", store.list.length, url) } - setActiveRaw(url) + setState("active", url) }) } @@ -71,31 +76,30 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( if (!url) return const list = store.list.filter((x) => x !== url) - const next = active() === url ? (list[0] ?? normalizeServerUrl(props.defaultUrl) ?? "") : active() + const next = state.active === url ? (list[0] ?? normalizeServerUrl(props.defaultUrl) ?? "") : state.active batch(() => { setStore("list", list) - setActiveRaw(next) + setState("active", next) }) } createEffect(() => { if (!ready()) return - if (active()) return + if (state.active) return const url = normalizeServerUrl(props.defaultUrl) if (!url) return - setActiveRaw(url) + setState("active", url) }) - const isReady = createMemo(() => ready() && !!active()) - - const [healthy, setHealthy] = createSignal(undefined) + const isReady = createMemo(() => ready() && !!state.active) const check = (url: string) => { + const signal = (AbortSignal as unknown as { timeout?: (ms: number) => AbortSignal }).timeout?.(3000) const sdk = createOpencodeClient({ baseUrl: url, fetch: platform.fetch, - signal: AbortSignal.timeout(3000), + signal, }) return sdk.global .health() @@ -104,10 +108,10 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( } createEffect(() => { - const url = active() + const url = state.active if (!url) return - setHealthy(undefined) + setState("healthy", undefined) let alive = true let busy = false @@ -118,7 +122,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( void check(url) .then((next) => { if (!alive) return - setHealthy(next) + setState("healthy", next) }) .finally(() => { busy = false @@ -134,7 +138,7 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( }) }) - const origin = createMemo(() => projectsKey(active())) + const origin = createMemo(() => projectsKey(state.active)) const projectsList = createMemo(() => store.projects[origin()] ?? []) const isLocal = createMemo(() => origin() === "local") @@ -143,10 +147,10 @@ export const { use: useServer, provider: ServerProvider } = createSimpleContext( healthy, isLocal, get url() { - return active() + return state.active }, get name() { - return serverDisplayName(active()) + return serverDisplayName(state.active) }, get list() { return store.list diff --git a/packages/app/src/context/settings.tsx b/packages/app/src/context/settings.tsx index d976cbc496..19b3846f84 100644 --- a/packages/app/src/context/settings.tsx +++ b/packages/app/src/context/settings.tsx @@ -18,6 +18,10 @@ export interface SoundSettings { export interface Settings { general: { autoSave: boolean + releaseNotes: boolean + } + updates: { + startup: boolean } appearance: { fontSize: number @@ -34,6 +38,10 @@ export interface Settings { const defaultSettings: Settings = { general: { autoSave: true, + releaseNotes: true, + }, + updates: { + startup: true, }, appearance: { fontSize: 14, @@ -97,6 +105,16 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont setAutoSave(value: boolean) { setStore("general", "autoSave", value) }, + releaseNotes: createMemo(() => store.general?.releaseNotes ?? defaultSettings.general.releaseNotes), + setReleaseNotes(value: boolean) { + setStore("general", "releaseNotes", value) + }, + }, + updates: { + startup: createMemo(() => store.updates?.startup ?? defaultSettings.updates.startup), + setStartup(value: boolean) { + setStore("updates", "startup", value) + }, }, appearance: { fontSize: createMemo(() => store.appearance?.fontSize ?? defaultSettings.appearance.fontSize), diff --git a/packages/app/src/context/sync.tsx b/packages/app/src/context/sync.tsx index 4ba0541966..8b0f08008e 100644 --- a/packages/app/src/context/sync.tsx +++ b/packages/app/src/context/sync.tsx @@ -16,7 +16,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ const sdk = useSDK() type Child = ReturnType<(typeof globalSync)["child"]> - type Store = Child[0] type Setter = Child[1] const current = createMemo(() => globalSync.child(sdk.directory)) @@ -43,18 +42,6 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ return Math.ceil(count / chunk) * chunk } - const hydrateMessages = (directory: string, store: Store, sessionID: string) => { - const key = keyFor(directory, sessionID) - if (meta.limit[key] !== undefined) return - - const messages = store.message[sessionID] - if (!messages) return - - const limit = limitFor(messages.length) - setMeta("limit", key, limit) - setMeta("complete", key, messages.length < limit) - } - const loadMessages = async (input: { directory: string client: typeof sdk.client @@ -150,21 +137,20 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ const directory = sdk.directory const client = sdk.client const [store, setStore] = globalSync.child(directory) + const key = keyFor(directory, sessionID) const hasSession = (() => { const match = Binary.search(store.session, sessionID, (s) => s.id) return match.found })() - hydrateMessages(directory, store, sessionID) - const hasMessages = store.message[sessionID] !== undefined - if (hasSession && hasMessages) return - - const key = keyFor(directory, sessionID) + const hydrated = meta.limit[key] !== undefined + if (hasSession && hasMessages && hydrated) return const pending = inflight.get(key) if (pending) return pending - const limit = meta.limit[key] ?? chunk + const count = store.message[sessionID]?.length ?? 0 + const limit = hydrated ? (meta.limit[key] ?? chunk) : limitFor(count) const sessionReq = hasSession ? Promise.resolve() @@ -184,15 +170,16 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({ ) }) - const messagesReq = hasMessages - ? Promise.resolve() - : loadMessages({ - directory, - client, - setStore, - sessionID, - limit, - }) + const messagesReq = + hasMessages && hydrated + ? Promise.resolve() + : loadMessages({ + directory, + client, + setStore, + sessionID, + limit, + }) const promise = Promise.all([sessionReq, messagesReq]) .then(() => {}) diff --git a/packages/app/src/context/terminal.tsx b/packages/app/src/context/terminal.tsx index 439b196c63..e01b8bc4de 100644 --- a/packages/app/src/context/terminal.tsx +++ b/packages/app/src/context/terminal.tsx @@ -155,8 +155,9 @@ function createTerminalSession(sdk: ReturnType, dir: string, sess batch(() => { setStore("all", index, { - ...pty, - ...clone.data, + id: clone.data.id, + title: clone.data.title ?? pty.title, + titleNumber: pty.titleNumber, }) if (active) { setStore("active", clone.data.id) diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index df8547636b..aa52fa1e7c 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -6,6 +6,8 @@ import { dict as en } from "@/i18n/en" import { dict as zh } from "@/i18n/zh" import pkg from "../package.json" +const DEFAULT_SERVER_URL_KEY = "opencode.settings.dat:defaultServerUrl" + const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { const locale = (() => { @@ -29,6 +31,12 @@ const platform: Platform = { openLink(url: string) { window.open(url, "_blank") }, + back() { + window.history.back() + }, + forward() { + window.history.forward() + }, restart: async () => { window.location.reload() }, @@ -62,6 +70,26 @@ const platform: Platform = { }) .catch(() => undefined) }, + getDefaultServerUrl: () => { + if (typeof localStorage === "undefined") return null + try { + return localStorage.getItem(DEFAULT_SERVER_URL_KEY) + } catch { + return null + } + }, + setDefaultServerUrl: (url) => { + if (typeof localStorage === "undefined") return + try { + if (url) { + localStorage.setItem(DEFAULT_SERVER_URL_KEY, url) + return + } + localStorage.removeItem(DEFAULT_SERVER_URL_KEY) + } catch { + return + } + }, } render( diff --git a/packages/app/src/hooks/use-providers.ts b/packages/app/src/hooks/use-providers.ts index ab0b86f831..215c863fb9 100644 --- a/packages/app/src/hooks/use-providers.ts +++ b/packages/app/src/hooks/use-providers.ts @@ -1,25 +1,16 @@ import { useGlobalSync } from "@/context/global-sync" -import { base64Decode } from "@opencode-ai/util/encode" +import { decode64 } from "@/utils/base64" import { useParams } from "@solidjs/router" import { createMemo } from "solid-js" // kilocode_change start - Preferred providers list (order determines display priority) -export const preferredProviders = [ - "kilo", - "opencode", - "anthropic", - "github-copilot", - "openai", - "google", - "openrouter", - "vercel", -] +export const preferredProviders = ["kilo", "anthropic", "github-copilot", "openai", "google", "openrouter", "vercel"] // kilocode_change end export function useProviders() { const globalSync = useGlobalSync() const params = useParams() - const currentDirectory = createMemo(() => base64Decode(params.dir ?? "")) + const currentDirectory = createMemo(() => decode64(params.dir) ?? "") const providers = createMemo(() => { if (currentDirectory()) { const [projectStore] = globalSync.child(currentDirectory()) diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index 593307e0fb..e6b4aa532c 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "سمة", "command.category.language": "لغة", "command.category.file": "ملف", + "command.category.context": "سياق", "command.category.terminal": "محطة طرفية", "command.category.model": "نموذج", "command.category.mcp": "MCP", @@ -42,7 +43,10 @@ export const dict = { "command.session.new": "جلسة جديدة", "command.file.open": "فتح ملف", "command.file.open.description": "البحث في الملفات والأوامر", + "command.context.addSelection": "إضافة التحديد إلى السياق", + "command.context.addSelection.description": "إضافة الأسطر المحددة من الملف الحالي", "command.terminal.toggle": "تبديل المحطة الطرفية", + "command.fileTree.toggle": "تبديل شجرة الملفات", "command.review.toggle": "تبديل المراجعة", "command.terminal.new": "محطة طرفية جديدة", "command.terminal.new.description": "إنشاء علامة تبويب جديدة للمحطة الطرفية", @@ -102,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "نماذج مجانية مقدمة من Kilo CLI", "dialog.model.unpaid.addMore.title": "إضافة المزيد من النماذج من موفرين مشهورين", - "dialog.provider.viewAll": "عرض جميع الموفرين", + "dialog.provider.viewAll": "عرض المزيد من الموفرين", "provider.connect.title": "اتصال {{provider}}", "provider.connect.title.anthropicProMax": "تسجيل الدخول باستخدام Claude Pro/Max", @@ -139,6 +143,8 @@ export const dict = { "provider.connect.toast.connected.title": "تم توصيل {{provider}}", "provider.connect.toast.connected.description": "نماذج {{provider}} متاحة الآن للاستخدام.", + "provider.disconnect.toast.disconnected.title": "تم فصل {{provider}}", + "provider.disconnect.toast.disconnected.description": "لم تعد نماذج {{provider}} متاحة.", "model.tag.free": "مجاني", "model.tag.latest": "الأحدث", "model.provider.anthropic": "Anthropic", @@ -161,6 +167,8 @@ export const dict = { "common.loading": "جارٍ التحميل", "common.loading.ellipsis": "...", "common.cancel": "إلغاء", + "common.connect": "اتصال", + "common.disconnect": "قطع الاتصال", "common.submit": "إرسال", "common.save": "حفظ", "common.saving": "جارٍ الحفظ...", @@ -169,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "أدخل أمر shell...", "prompt.placeholder.normal": 'اسأل أي شيء... "{{example}}"', + "prompt.placeholder.summarizeComments": "لخّص التعليقات…", + "prompt.placeholder.summarizeComment": "لخّص التعليق…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc للخروج", @@ -272,6 +282,9 @@ export const dict = { "dialog.project.edit.color": "لون", "dialog.project.edit.color.select": "اختر لون {{color}}", + "dialog.project.edit.worktree.startup": "سكريبت بدء تشغيل مساحة العمل", + "dialog.project.edit.worktree.startup.description": "يتم تشغيله بعد إنشاء مساحة عمل جديدة (شجرة عمل).", + "dialog.project.edit.worktree.startup.placeholder": "مثال: bun install", "context.breakdown.title": "تفصيل السياق", "context.breakdown.note": 'تفصيل تقريبي لرموز الإدخال. يشمل "أخرى" تعريفات الأدوات والنفقات العامة.', "context.breakdown.system": "النظام", @@ -320,6 +333,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "لغة", "toast.language.description": "تم التبديل إلى {{language}}", @@ -337,6 +351,9 @@ export const dict = { "toast.file.loadFailed.title": "فشل تحميل الملف", + "toast.file.listFailed.title": "فشل سرد الملفات", + "toast.context.noLineSelection.title": "لا يوجد تحديد للأسطر", + "toast.context.noLineSelection.description": "حدد نطاق أسطر في تبويب ملف أولاً.", "toast.session.share.copyFailed.title": "فشل نسخ عنوان URL إلى الحافظة", "toast.session.share.success.title": "تمت مشاركة الجلسة", "toast.session.share.success.description": "تم نسخ عنوان URL للمشاركة إلى الحافظة!", @@ -410,8 +427,13 @@ export const dict = { "session.tab.context": "سياق", "session.panel.reviewAndFiles": "المراجعة والملفات", "session.review.filesChanged": "تم تغيير {{count}} ملفات", + "session.review.change.one": "تغيير", + "session.review.change.other": "تغييرات", "session.review.loadingChanges": "جارٍ تحميل التغييرات...", "session.review.empty": "لا توجد تغييرات في هذه الجلسة بعد", + "session.review.noChanges": "لا توجد تغييرات", + "session.files.selectToOpen": "اختر ملفًا لفتحه", + "session.files.all": "كل الملفات", "session.messages.renderEarlier": "عرض الرسائل السابقة", "session.messages.loadingEarlier": "جارٍ تحميل الرسائل السابقة...", "session.messages.loadEarlier": "تحميل الرسائل السابقة", @@ -485,12 +507,15 @@ export const dict = { "sidebar.project.recentSessions": "الجلسات الحديثة", "sidebar.project.viewAllSessions": "عرض جميع الجلسات", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "سطح المكتب", + "settings.section.server": "الخادم", "settings.tab.general": "عام", "settings.tab.shortcuts": "اختصارات", "settings.general.section.appearance": "المظهر", "settings.general.section.notifications": "إشعارات النظام", + "settings.general.section.updates": "التحديثات", "settings.general.section.sounds": "المؤثرات الصوتية", "settings.general.row.language.title": "اللغة", @@ -501,12 +526,25 @@ export const dict = { "settings.general.row.theme.description": "تخصيص سمة Kilo CLI.", "settings.general.row.font.title": "الخط", "settings.general.row.font.description": "تخصيص الخط الأحادي المستخدم في كتل التعليمات البرمجية", + + "settings.general.row.releaseNotes.title": "ملاحظات الإصدار", + "settings.general.row.releaseNotes.description": 'عرض نوافذ "ما الجديد" المنبثقة بعد التحديثات', + + "settings.updates.row.startup.title": "التحقق من التحديثات عند بدء التشغيل", + "settings.updates.row.startup.description": "التحقق تلقائيًا من التحديثات عند تشغيل OpenCode", + "settings.updates.row.check.title": "التحقق من التحديثات", + "settings.updates.row.check.description": "التحقق يدويًا من التحديثات وتثبيتها إذا كانت متاحة", + "settings.updates.action.checkNow": "تحقق الآن", + "settings.updates.action.checking": "جارٍ التحقق...", + "settings.updates.toast.latest.title": "أنت على آخر إصدار", + "settings.updates.toast.latest.description": "أنت تستخدم أحدث إصدار من OpenCode.", "font.option.ibmPlexMono": "IBM Plex Mono", "font.option.cascadiaCode": "Cascadia Code", "font.option.firaCode": "Fira Code", "font.option.hack": "Hack", "font.option.inconsolata": "Inconsolata", "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", "font.option.jetbrainsMono": "JetBrains Mono", "font.option.mesloLgs": "Meslo LGS", "font.option.robotoMono": "Roboto Mono", @@ -592,6 +630,13 @@ export const dict = { "settings.providers.title": "الموفرون", "settings.providers.description": "ستكون إعدادات الموفر قابلة للتكوين هنا.", + "settings.providers.section.connected": "الموفرون المتصلون", + "settings.providers.connected.empty": "لا يوجد موفرون متصلون", + "settings.providers.section.popular": "الموفرون الشائعون", + "settings.providers.tag.environment": "البيئة", + "settings.providers.tag.config": "التكوين", + "settings.providers.tag.custom": "مخصص", + "settings.providers.tag.other": "أخرى", "settings.models.title": "النماذج", "settings.models.description": "ستكون إعدادات النموذج قابلة للتكوين هنا.", "settings.agents.title": "الوكلاء", @@ -659,6 +704,7 @@ export const dict = { "workspace.reset.failed.title": "فشل إعادة تعيين مساحة العمل", "workspace.reset.success.title": "تمت إعادة تعيين مساحة العمل", "workspace.reset.success.description": "مساحة العمل تطابق الآن الفرع الافتراضي.", + "workspace.error.stillPreparing": "مساحة العمل لا تزال قيد الإعداد", "workspace.status.checking": "التحقق من التغييرات غير المدمجة...", "workspace.status.error": "تعذر التحقق من حالة git.", "workspace.status.clean": "لم يتم اكتشاف تغييرات غير مدمجة.", diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index 09dad7236c..d8125a3052 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Tema", "command.category.language": "Idioma", "command.category.file": "Arquivo", + "command.category.context": "Contexto", "command.category.terminal": "Terminal", "command.category.model": "Modelo", "command.category.mcp": "MCP", @@ -42,7 +43,10 @@ export const dict = { "command.session.new": "Nova sessão", "command.file.open": "Abrir arquivo", "command.file.open.description": "Buscar arquivos e comandos", + "command.context.addSelection": "Adicionar seleção ao contexto", + "command.context.addSelection.description": "Adicionar as linhas selecionadas do arquivo atual", "command.terminal.toggle": "Alternar terminal", + "command.fileTree.toggle": "Alternar árvore de arquivos", "command.review.toggle": "Alternar revisão", "command.terminal.new": "Novo terminal", "command.terminal.new.description": "Criar uma nova aba de terminal", @@ -102,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Modelos gratuitos fornecidos pelo Kilo CLI", "dialog.model.unpaid.addMore.title": "Adicionar mais modelos de provedores populares", - "dialog.provider.viewAll": "Ver todos os provedores", + "dialog.provider.viewAll": "Ver mais provedores", "provider.connect.title": "Conectar {{provider}}", "provider.connect.title.anthropicProMax": "Entrar com Claude Pro/Max", @@ -139,6 +143,8 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} conectado", "provider.connect.toast.connected.description": "Modelos do {{provider}} agora estão disponíveis para uso.", + "provider.disconnect.toast.disconnected.title": "{{provider}} desconectado", + "provider.disconnect.toast.disconnected.description": "Os modelos de {{provider}} não estão mais disponíveis.", "model.tag.free": "Grátis", "model.tag.latest": "Mais recente", "model.provider.anthropic": "Anthropic", @@ -161,6 +167,8 @@ export const dict = { "common.loading": "Carregando", "common.loading.ellipsis": "...", "common.cancel": "Cancelar", + "common.connect": "Conectar", + "common.disconnect": "Desconectar", "common.submit": "Enviar", "common.save": "Salvar", "common.saving": "Salvando...", @@ -169,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Digite comando do shell...", "prompt.placeholder.normal": 'Pergunte qualquer coisa... "{{example}}"', + "prompt.placeholder.summarizeComments": "Resumir comentários…", + "prompt.placeholder.summarizeComment": "Resumir comentário…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc para sair", @@ -225,6 +235,8 @@ export const dict = { "dialog.mcp.description": "{{enabled}} de {{total}} habilitados", "dialog.mcp.empty": "Nenhum MCP configurado", + "dialog.lsp.empty": "LSPs detectados automaticamente pelos tipos de arquivo", + "dialog.plugins.empty": "Plugins configurados em opencode.json", "mcp.status.connected": "conectado", "mcp.status.failed": "falhou", "mcp.status.needs_auth": "precisa de autenticação", @@ -253,6 +265,12 @@ export const dict = { "dialog.server.default.clear": "Limpar", "dialog.server.action.remove": "Remover servidor", + "dialog.server.menu.edit": "Editar", + "dialog.server.menu.default": "Definir como padrão", + "dialog.server.menu.defaultRemove": "Remover padrão", + "dialog.server.menu.delete": "Excluir", + "dialog.server.current": "Servidor atual", + "dialog.server.status.default": "Padrão", "dialog.project.edit.title": "Editar projeto", "dialog.project.edit.name": "Nome", "dialog.project.edit.icon": "Ícone", @@ -314,6 +332,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Idioma", "toast.language.description": "Alterado para {{language}}", @@ -331,6 +350,9 @@ export const dict = { "toast.file.loadFailed.title": "Falha ao carregar arquivo", + "toast.file.listFailed.title": "Falha ao listar arquivos", + "toast.context.noLineSelection.title": "Nenhuma seleção de linhas", + "toast.context.noLineSelection.description": "Selecione primeiro um intervalo de linhas em uma aba de arquivo.", "toast.session.share.copyFailed.title": "Falha ao copiar URL para a área de transferência", "toast.session.share.success.title": "Sessão compartilhada", "toast.session.share.success.description": "URL compartilhada copiada para a área de transferência!", @@ -406,8 +428,13 @@ export const dict = { "session.tab.context": "Contexto", "session.panel.reviewAndFiles": "Revisão e arquivos", "session.review.filesChanged": "{{count}} Arquivos Alterados", + "session.review.change.one": "Alteração", + "session.review.change.other": "Alterações", "session.review.loadingChanges": "Carregando alterações...", "session.review.empty": "Nenhuma alteração nesta sessão ainda", + "session.review.noChanges": "Sem alterações", + "session.files.selectToOpen": "Selecione um arquivo para abrir", + "session.files.all": "Todos os arquivos", "session.messages.renderEarlier": "Renderizar mensagens anteriores", "session.messages.loadingEarlier": "Carregando mensagens anteriores...", "session.messages.loadEarlier": "Carregar mensagens anteriores", @@ -484,12 +511,15 @@ export const dict = { "sidebar.project.recentSessions": "Sessões recentes", "sidebar.project.viewAllSessions": "Ver todas as sessões", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", + "settings.section.server": "Servidor", "settings.tab.general": "Geral", "settings.tab.shortcuts": "Atalhos", "settings.general.section.appearance": "Aparência", "settings.general.section.notifications": "Notificações do sistema", + "settings.general.section.updates": "Atualizações", "settings.general.section.sounds": "Efeitos sonoros", "settings.general.row.language.title": "Idioma", @@ -500,12 +530,25 @@ export const dict = { "settings.general.row.theme.description": "Personalize como o Kilo CLI é tematizado.", "settings.general.row.font.title": "Fonte", "settings.general.row.font.description": "Personalize a fonte monoespaçada usada em blocos de código", + + "settings.general.row.releaseNotes.title": "Notas da versão", + "settings.general.row.releaseNotes.description": 'Mostrar pop-ups de "Novidades" após atualizações', + + "settings.updates.row.startup.title": "Verificar atualizações ao iniciar", + "settings.updates.row.startup.description": "Verificar atualizações automaticamente quando o OpenCode iniciar", + "settings.updates.row.check.title": "Verificar atualizações", + "settings.updates.row.check.description": "Verificar atualizações manualmente e instalar se houver", + "settings.updates.action.checkNow": "Verificar agora", + "settings.updates.action.checking": "Verificando...", + "settings.updates.toast.latest.title": "Você está atualizado", + "settings.updates.toast.latest.description": "Você está usando a versão mais recente do OpenCode.", "font.option.ibmPlexMono": "IBM Plex Mono", "font.option.cascadiaCode": "Cascadia Code", "font.option.firaCode": "Fira Code", "font.option.hack": "Hack", "font.option.inconsolata": "Inconsolata", "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", "font.option.jetbrainsMono": "JetBrains Mono", "font.option.mesloLgs": "Meslo LGS", "font.option.robotoMono": "Roboto Mono", @@ -593,6 +636,13 @@ export const dict = { "settings.providers.title": "Provedores", "settings.providers.description": "Configurações de provedores estarão disponíveis aqui.", + "settings.providers.section.connected": "Provedores conectados", + "settings.providers.connected.empty": "Nenhum provedor conectado", + "settings.providers.section.popular": "Provedores populares", + "settings.providers.tag.environment": "Ambiente", + "settings.providers.tag.config": "Configuração", + "settings.providers.tag.custom": "Personalizado", + "settings.providers.tag.other": "Outro", "settings.models.title": "Modelos", "settings.models.description": "Configurações de modelos estarão disponíveis aqui.", "settings.agents.title": "Agentes", @@ -660,6 +710,7 @@ export const dict = { "workspace.reset.failed.title": "Falha ao redefinir espaço de trabalho", "workspace.reset.success.title": "Espaço de trabalho redefinido", "workspace.reset.success.description": "Espaço de trabalho agora corresponde ao branch padrão.", + "workspace.error.stillPreparing": "O espaço de trabalho ainda está sendo preparado", "workspace.status.checking": "Verificando alterações não mescladas...", "workspace.status.error": "Não foi possível verificar o status do git.", "workspace.status.clean": "Nenhuma alteração não mesclada detectada.", diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index 5f10112b81..43500c871c 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Tema", "command.category.language": "Sprog", "command.category.file": "Fil", + "command.category.context": "Kontekst", "command.category.terminal": "Terminal", "command.category.model": "Model", "command.category.mcp": "MCP", @@ -15,6 +16,7 @@ export const dict = { "command.category.permissions": "Tilladelser", "command.category.workspace": "Arbejdsområde", + "command.category.settings": "Indstillinger", "theme.scheme.system": "System", "theme.scheme.light": "Lys", "theme.scheme.dark": "Mørk", @@ -23,6 +25,7 @@ export const dict = { "command.project.open": "Åbn projekt", "command.provider.connect": "Tilslut udbyder", "command.server.switch": "Skift server", + "command.settings.open": "Åbn indstillinger", "command.session.previous": "Forrige session", "command.session.next": "Næste session", "command.session.archive": "Arkivér session", @@ -40,7 +43,10 @@ export const dict = { "command.session.new": "Ny session", "command.file.open": "Åbn fil", "command.file.open.description": "Søg i filer og kommandoer", + "command.context.addSelection": "Tilføj markering til kontekst", + "command.context.addSelection.description": "Tilføj markerede linjer fra den aktuelle fil", "command.terminal.toggle": "Skift terminal", + "command.fileTree.toggle": "Skift filtræ", "command.review.toggle": "Skift gennemgang", "command.terminal.new": "Ny terminal", "command.terminal.new.description": "Opret en ny terminalfane", @@ -100,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Gratis modeller leveret af Kilo CLI", "dialog.model.unpaid.addMore.title": "Tilføj flere modeller fra populære udbydere", - "dialog.provider.viewAll": "Vis alle udbydere", + "dialog.provider.viewAll": "Vis flere udbydere", "provider.connect.title": "Forbind {{provider}}", "provider.connect.title.anthropicProMax": "Log ind med Claude Pro/Max", @@ -137,13 +143,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} forbundet", "provider.connect.toast.connected.description": "{{provider}} modeller er nu tilgængelige.", + "provider.disconnect.toast.disconnected.title": "{{provider}} frakoblet", + "provider.disconnect.toast.disconnected.description": "Modeller fra {{provider}} er ikke længere tilgængelige.", "model.tag.free": "Gratis", "model.tag.latest": "Nyeste", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "tekst", + "model.input.image": "billede", + "model.input.audio": "lyd", + "model.input.video": "video", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Tillader: {{inputs}}", + "model.tooltip.reasoning.allowed": "Tillader tænkning", + "model.tooltip.reasoning.none": "Ingen tænkning", + "model.tooltip.context": "Kontekstgrænse {{limit}}", "common.search.placeholder": "Søg", "common.goBack": "Gå tilbage", "common.loading": "Indlæser", + "common.loading.ellipsis": "...", "common.cancel": "Annuller", + "common.connect": "Forbind", + "common.disconnect": "Frakobl", "common.submit": "Indsend", "common.save": "Gem", "common.saving": "Gemmer...", @@ -152,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Indtast shell-kommando...", "prompt.placeholder.normal": 'Spørg om hvad som helst... "{{example}}"', + "prompt.placeholder.summarizeComments": "Opsummér kommentarer…", + "prompt.placeholder.summarizeComment": "Opsummér kommentar…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc for at afslutte", @@ -255,6 +282,9 @@ export const dict = { "dialog.project.edit.color": "Farve", "dialog.project.edit.color.select": "Vælg farven {{color}}", + "dialog.project.edit.worktree.startup": "Opstartsscript for arbejdsområde", + "dialog.project.edit.worktree.startup.description": "Køres efter oprettelse af et nyt arbejdsområde (worktree).", + "dialog.project.edit.worktree.startup.placeholder": "f.eks. bun install", "context.breakdown.title": "Kontekstfordeling", "context.breakdown.note": 'Omtrentlig fordeling af input-tokens. "Andre" inkluderer værktøjsdefinitioner og overhead.', @@ -304,6 +334,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Sprog", "toast.language.description": "Skiftede til {{language}}", @@ -321,6 +352,9 @@ export const dict = { "toast.file.loadFailed.title": "Kunne ikke indlæse fil", + "toast.file.listFailed.title": "Kunne ikke liste filer", + "toast.context.noLineSelection.title": "Ingen linjevalg", + "toast.context.noLineSelection.description": "Vælg først et linjeinterval i en filfane.", "toast.session.share.copyFailed.title": "Kunne ikke kopiere URL til udklipsholder", "toast.session.share.success.title": "Session delt", "toast.session.share.success.description": "Delings-URL kopieret til udklipsholder!", @@ -395,13 +429,19 @@ export const dict = { "session.tab.context": "Kontekst", "session.panel.reviewAndFiles": "Gennemgang og filer", "session.review.filesChanged": "{{count}} Filer ændret", + "session.review.change.one": "Ændring", + "session.review.change.other": "Ændringer", "session.review.loadingChanges": "Indlæser ændringer...", "session.review.empty": "Ingen ændringer i denne session endnu", + "session.review.noChanges": "Ingen ændringer", + "session.files.selectToOpen": "Vælg en fil at åbne", + "session.files.all": "Alle filer", "session.messages.renderEarlier": "Vis tidligere beskeder", "session.messages.loadingEarlier": "Indlæser tidligere beskeder...", "session.messages.loadEarlier": "Indlæs tidligere beskeder", "session.messages.loading": "Indlæser beskeder...", + "session.messages.jumpToLatest": "Gå til seneste", "session.context.addToContext": "Tilføj {{selection}} til kontekst", "session.new.worktree.main": "Hovedgren", @@ -443,6 +483,8 @@ export const dict = { "terminal.title.numbered": "Terminal {{number}}", "terminal.close": "Luk terminal", + "terminal.connectionLost.title": "Forbindelse mistet", + "terminal.connectionLost.description": "Terminalforbindelsen blev afbrudt. Dette kan ske, når serveren genstarter.", "common.closeTab": "Luk fane", "common.dismiss": "Afvis", "common.requestFailed": "Forespørgsel mislykkedes", @@ -456,6 +498,8 @@ export const dict = { "common.edit": "Rediger", "common.loadMore": "Indlæs flere", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "Skift menu", "sidebar.nav.projectsAndSessions": "Projekter og sessioner", "sidebar.settings": "Indstillinger", "sidebar.help": "Hjælp", @@ -467,12 +511,15 @@ export const dict = { "sidebar.project.recentSessions": "Seneste sessioner", "sidebar.project.viewAllSessions": "Vis alle sessioner", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", + "settings.section.server": "Server", "settings.tab.general": "Generelt", "settings.tab.shortcuts": "Genveje", "settings.general.section.appearance": "Udseende", "settings.general.section.notifications": "Systemmeddelelser", + "settings.general.section.updates": "Opdateringer", "settings.general.section.sounds": "Lydeffekter", "settings.general.row.language.title": "Sprog", @@ -484,6 +531,75 @@ export const dict = { "settings.general.row.font.title": "Skrifttype", "settings.general.row.font.description": "Tilpas mono-skrifttypen brugt i kodeblokke", + "settings.general.row.releaseNotes.title": "Udgivelsesnoter", + "settings.general.row.releaseNotes.description": 'Vis "Hvad er nyt"-popups efter opdateringer', + + "settings.updates.row.startup.title": "Tjek for opdateringer ved opstart", + "settings.updates.row.startup.description": "Tjek automatisk for opdateringer, når OpenCode starter", + "settings.updates.row.check.title": "Tjek for opdateringer", + "settings.updates.row.check.description": "Tjek manuelt for opdateringer og installer, hvis tilgængelig", + "settings.updates.action.checkNow": "Tjek nu", + "settings.updates.action.checking": "Tjekker...", + "settings.updates.toast.latest.title": "Du er opdateret", + "settings.updates.toast.latest.description": "Du kører den nyeste version af OpenCode.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Alarm 01", + "sound.option.alert02": "Alarm 02", + "sound.option.alert03": "Alarm 03", + "sound.option.alert04": "Alarm 04", + "sound.option.alert05": "Alarm 05", + "sound.option.alert06": "Alarm 06", + "sound.option.alert07": "Alarm 07", + "sound.option.alert08": "Alarm 08", + "sound.option.alert09": "Alarm 09", + "sound.option.alert10": "Alarm 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Nej 01", + "sound.option.nope02": "Nej 02", + "sound.option.nope03": "Nej 03", + "sound.option.nope04": "Nej 04", + "sound.option.nope05": "Nej 05", + "sound.option.nope06": "Nej 06", + "sound.option.nope07": "Nej 07", + "sound.option.nope08": "Nej 08", + "sound.option.nope09": "Nej 09", + "sound.option.nope10": "Nej 10", + "sound.option.nope11": "Nej 11", + "sound.option.nope12": "Nej 12", + "sound.option.yup01": "Ja 01", + "sound.option.yup02": "Ja 02", + "sound.option.yup03": "Ja 03", + "sound.option.yup04": "Ja 04", + "sound.option.yup05": "Ja 05", + "sound.option.yup06": "Ja 06", "settings.general.notifications.agent.title": "Agent", "settings.general.notifications.agent.description": "Vis systemmeddelelse når agenten er færdig eller kræver opmærksomhed", @@ -519,6 +635,13 @@ export const dict = { "settings.providers.title": "Udbydere", "settings.providers.description": "Udbyderindstillinger vil kunne konfigureres her.", + "settings.providers.section.connected": "Forbundne udbydere", + "settings.providers.connected.empty": "Ingen forbundne udbydere", + "settings.providers.section.popular": "Populære udbydere", + "settings.providers.tag.environment": "Miljø", + "settings.providers.tag.config": "Konfiguration", + "settings.providers.tag.custom": "Brugerdefineret", + "settings.providers.tag.other": "Andet", "settings.models.title": "Modeller", "settings.models.description": "Modelindstillinger vil kunne konfigureres her.", "settings.agents.title": "Agenter", @@ -586,6 +709,7 @@ export const dict = { "workspace.reset.failed.title": "Kunne ikke nulstille arbejdsområde", "workspace.reset.success.title": "Arbejdsområde nulstillet", "workspace.reset.success.description": "Arbejdsområdet matcher nu hovedgrenen.", + "workspace.error.stillPreparing": "Arbejdsområdet er stadig ved at blive klargjort", "workspace.status.checking": "Tjekker for uflettede ændringer...", "workspace.status.error": "Kunne ikke bekræfte git-status.", "workspace.status.clean": "Ingen uflettede ændringer fundet.", diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index e6ac6fb202..d35cc01c22 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -12,6 +12,7 @@ export const dict = { "command.category.theme": "Thema", "command.category.language": "Sprache", "command.category.file": "Datei", + "command.category.context": "Kontext", "command.category.terminal": "Terminal", "command.category.model": "Modell", "command.category.mcp": "MCP", @@ -19,6 +20,7 @@ export const dict = { "command.category.permissions": "Berechtigungen", "command.category.workspace": "Arbeitsbereich", + "command.category.settings": "Einstellungen", "theme.scheme.system": "System", "theme.scheme.light": "Hell", "theme.scheme.dark": "Dunkel", @@ -27,6 +29,7 @@ export const dict = { "command.project.open": "Projekt öffnen", "command.provider.connect": "Anbieter verbinden", "command.server.switch": "Server wechseln", + "command.settings.open": "Einstellungen öffnen", "command.session.previous": "Vorherige Sitzung", "command.session.next": "Nächste Sitzung", "command.session.archive": "Sitzung archivieren", @@ -44,7 +47,10 @@ export const dict = { "command.session.new": "Neue Sitzung", "command.file.open": "Datei öffnen", "command.file.open.description": "Dateien und Befehle durchsuchen", + "command.context.addSelection": "Auswahl zum Kontext hinzufügen", + "command.context.addSelection.description": "Ausgewählte Zeilen aus der aktuellen Datei hinzufügen", "command.terminal.toggle": "Terminal umschalten", + "command.fileTree.toggle": "Dateibaum umschalten", "command.review.toggle": "Überprüfung umschalten", "command.terminal.new": "Neues Terminal", "command.terminal.new.description": "Neuen Terminal-Tab erstellen", @@ -104,7 +110,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Kostenlose Modelle von Kilo CLI", "dialog.model.unpaid.addMore.title": "Weitere Modelle von beliebten Anbietern hinzufügen", - "dialog.provider.viewAll": "Alle Anbieter anzeigen", + "dialog.provider.viewAll": "Mehr Anbieter anzeigen", "provider.connect.title": "{{provider}} verbinden", "provider.connect.title.anthropicProMax": "Mit Claude Pro/Max anmelden", @@ -141,13 +147,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} verbunden", "provider.connect.toast.connected.description": "{{provider}} Modelle sind jetzt verfügbar.", + "provider.disconnect.toast.disconnected.title": "{{provider}} getrennt", + "provider.disconnect.toast.disconnected.description": "Die {{provider}}-Modelle sind nicht mehr verfügbar.", "model.tag.free": "Kostenlos", "model.tag.latest": "Neueste", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "Text", + "model.input.image": "Bild", + "model.input.audio": "Audio", + "model.input.video": "Video", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Erlaubt: {{inputs}}", + "model.tooltip.reasoning.allowed": "Erlaubt Reasoning", + "model.tooltip.reasoning.none": "Kein Reasoning", + "model.tooltip.context": "Kontextlimit {{limit}}", "common.search.placeholder": "Suchen", "common.goBack": "Zurück", "common.loading": "Laden", + "common.loading.ellipsis": "...", "common.cancel": "Abbrechen", + "common.connect": "Verbinden", + "common.disconnect": "Trennen", "common.submit": "Absenden", "common.save": "Speichern", "common.saving": "Speichert...", @@ -156,6 +181,8 @@ export const dict = { "prompt.placeholder.shell": "Shell-Befehl eingeben...", "prompt.placeholder.normal": 'Fragen Sie alles... "{{example}}"', + "prompt.placeholder.summarizeComments": "Kommentare zusammenfassen…", + "prompt.placeholder.summarizeComment": "Kommentar zusammenfassen…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc zum Verlassen", @@ -260,6 +287,10 @@ export const dict = { "dialog.project.edit.color": "Farbe", "dialog.project.edit.color.select": "{{color}}-Farbe auswählen", + "dialog.project.edit.worktree.startup": "Startup-Skript für Arbeitsbereich", + "dialog.project.edit.worktree.startup.description": + "Wird nach dem Erstellen eines neuen Arbeitsbereichs (Worktree) ausgeführt.", + "dialog.project.edit.worktree.startup.placeholder": "z. B. bun install", "context.breakdown.title": "Kontext-Aufschlüsselung", "context.breakdown.note": 'Ungefähre Aufschlüsselung der Eingabe-Token. "Andere" beinhaltet Werkzeugdefinitionen und Overhead.', @@ -309,6 +340,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Sprache", "toast.language.description": "Zu {{language}} gewechselt", @@ -326,6 +358,9 @@ export const dict = { "toast.file.loadFailed.title": "Datei konnte nicht geladen werden", + "toast.file.listFailed.title": "Dateien konnten nicht aufgelistet werden", + "toast.context.noLineSelection.title": "Keine Zeilenauswahl", + "toast.context.noLineSelection.description": "Wählen Sie zuerst einen Zeilenbereich in einem Datei-Tab aus.", "toast.session.share.copyFailed.title": "URL konnte nicht in die Zwischenablage kopiert werden", "toast.session.share.success.title": "Sitzung geteilt", "toast.session.share.success.description": "Teilen-URL in die Zwischenablage kopiert!", @@ -402,13 +437,19 @@ export const dict = { "session.tab.context": "Kontext", "session.panel.reviewAndFiles": "Überprüfung und Dateien", "session.review.filesChanged": "{{count}} Dateien geändert", + "session.review.change.one": "Änderung", + "session.review.change.other": "Änderungen", "session.review.loadingChanges": "Lade Änderungen...", "session.review.empty": "Noch keine Änderungen in dieser Sitzung", + "session.review.noChanges": "Keine Änderungen", + "session.files.selectToOpen": "Datei zum Öffnen auswählen", + "session.files.all": "Alle Dateien", "session.messages.renderEarlier": "Frühere Nachrichten rendern", "session.messages.loadingEarlier": "Lade frühere Nachrichten...", "session.messages.loadEarlier": "Frühere Nachrichten laden", "session.messages.loading": "Lade Nachrichten...", + "session.messages.jumpToLatest": "Zum neuesten springen", "session.context.addToContext": "{{selection}} zum Kontext hinzufügen", "session.new.worktree.main": "Haupt-Branch", @@ -450,6 +491,9 @@ export const dict = { "terminal.title.numbered": "Terminal {{number}}", "terminal.close": "Terminal schließen", + "terminal.connectionLost.title": "Verbindung verloren", + "terminal.connectionLost.description": + "Die Terminalverbindung wurde unterbrochen. Das kann passieren, wenn der Server neu startet.", "common.closeTab": "Tab schließen", "common.dismiss": "Verwerfen", "common.requestFailed": "Anfrage fehlgeschlagen", @@ -463,6 +507,8 @@ export const dict = { "common.edit": "Bearbeiten", "common.loadMore": "Mehr laden", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "Menü umschalten", "sidebar.nav.projectsAndSessions": "Projekte und Sitzungen", "sidebar.settings": "Einstellungen", "sidebar.help": "Hilfe", @@ -475,12 +521,15 @@ export const dict = { "sidebar.project.recentSessions": "Letzte Sitzungen", "sidebar.project.viewAllSessions": "Alle Sitzungen anzeigen", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Desktop", + "settings.section.server": "Server", "settings.tab.general": "Allgemein", "settings.tab.shortcuts": "Tastenkombinationen", "settings.general.section.appearance": "Erscheinungsbild", "settings.general.section.notifications": "Systembenachrichtigungen", + "settings.general.section.updates": "Updates", "settings.general.section.sounds": "Soundeffekte", "settings.general.row.language.title": "Sprache", @@ -492,6 +541,75 @@ export const dict = { "settings.general.row.font.title": "Schriftart", "settings.general.row.font.description": "Die in Codeblöcken verwendete Monospace-Schriftart anpassen", + "settings.general.row.releaseNotes.title": "Versionshinweise", + "settings.general.row.releaseNotes.description": '"Neuigkeiten"-Pop-ups nach Updates anzeigen', + + "settings.updates.row.startup.title": "Beim Start nach Updates suchen", + "settings.updates.row.startup.description": "Beim Start von OpenCode automatisch nach Updates suchen", + "settings.updates.row.check.title": "Nach Updates suchen", + "settings.updates.row.check.description": "Manuell nach Updates suchen und installieren, wenn verfügbar", + "settings.updates.action.checkNow": "Jetzt prüfen", + "settings.updates.action.checking": "Wird geprüft...", + "settings.updates.toast.latest.title": "Du bist auf dem neuesten Stand", + "settings.updates.toast.latest.description": "Du verwendest die aktuelle Version von OpenCode.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Alarm 01", + "sound.option.alert02": "Alarm 02", + "sound.option.alert03": "Alarm 03", + "sound.option.alert04": "Alarm 04", + "sound.option.alert05": "Alarm 05", + "sound.option.alert06": "Alarm 06", + "sound.option.alert07": "Alarm 07", + "sound.option.alert08": "Alarm 08", + "sound.option.alert09": "Alarm 09", + "sound.option.alert10": "Alarm 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Nein 01", + "sound.option.nope02": "Nein 02", + "sound.option.nope03": "Nein 03", + "sound.option.nope04": "Nein 04", + "sound.option.nope05": "Nein 05", + "sound.option.nope06": "Nein 06", + "sound.option.nope07": "Nein 07", + "sound.option.nope08": "Nein 08", + "sound.option.nope09": "Nein 09", + "sound.option.nope10": "Nein 10", + "sound.option.nope11": "Nein 11", + "sound.option.nope12": "Nein 12", + "sound.option.yup01": "Ja 01", + "sound.option.yup02": "Ja 02", + "sound.option.yup03": "Ja 03", + "sound.option.yup04": "Ja 04", + "sound.option.yup05": "Ja 05", + "sound.option.yup06": "Ja 06", "settings.general.notifications.agent.title": "Agent", "settings.general.notifications.agent.description": "Systembenachrichtigung anzeigen, wenn der Agent fertig ist oder Aufmerksamkeit benötigt", @@ -528,6 +646,13 @@ export const dict = { "settings.providers.title": "Anbieter", "settings.providers.description": "Anbietereinstellungen können hier konfiguriert werden.", + "settings.providers.section.connected": "Verbundene Anbieter", + "settings.providers.connected.empty": "Keine verbundenen Anbieter", + "settings.providers.section.popular": "Beliebte Anbieter", + "settings.providers.tag.environment": "Umgebung", + "settings.providers.tag.config": "Konfiguration", + "settings.providers.tag.custom": "Benutzerdefiniert", + "settings.providers.tag.other": "Andere", "settings.models.title": "Modelle", "settings.models.description": "Modelleinstellungen können hier konfiguriert werden.", "settings.agents.title": "Agenten", @@ -595,6 +720,7 @@ export const dict = { "workspace.reset.failed.title": "Arbeitsbereich konnte nicht zurückgesetzt werden", "workspace.reset.success.title": "Arbeitsbereich zurückgesetzt", "workspace.reset.success.description": "Der Arbeitsbereich entspricht jetzt dem Standard-Branch.", + "workspace.error.stillPreparing": "Arbeitsbereich wird noch vorbereitet", "workspace.status.checking": "Suche nach nicht zusammengeführten Änderungen...", "workspace.status.error": "Git-Status konnte nicht überprüft werden.", "workspace.status.clean": "Keine nicht zusammengeführten Änderungen erkannt.", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index c4f6adbe51..90e19fe2ce 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Theme", "command.category.language": "Language", "command.category.file": "File", + "command.category.context": "Context", "command.category.terminal": "Terminal", "command.category.model": "Model", "command.category.mcp": "MCP", @@ -42,7 +43,10 @@ export const dict = { "command.session.new": "New session", "command.file.open": "Open file", "command.file.open.description": "Search files and commands", + "command.context.addSelection": "Add selection to context", + "command.context.addSelection.description": "Add selected lines from the current file", "command.terminal.toggle": "Toggle terminal", + "command.fileTree.toggle": "Toggle file tree", "command.review.toggle": "Toggle review", "command.terminal.new": "New terminal", "command.terminal.new.description": "Create a new terminal tab", @@ -89,9 +93,13 @@ export const dict = { "dialog.provider.group.other": "Other", "dialog.provider.tag.recommended": "Recommended", "dialog.provider.kilo.note": "Access 500+ AI models", - "dialog.provider.anthropic.note": "Connect with Claude Pro/Max or API key", - "dialog.provider.openai.note": "Connect with ChatGPT Pro/Plus or API key", - "dialog.provider.copilot.note": "Connect with Copilot or API key", + "dialog.provider.opencode.note": "Connect with OpenCode Zen or API key", // kilocode_change + "dialog.provider.anthropic.note": "Direct access to Claude models, including Pro and Max", + "dialog.provider.copilot.note": "Claude models for coding assistance", + "dialog.provider.openai.note": "GPT models for fast, capable general AI tasks", + "dialog.provider.google.note": "Gemini models for fast, structured responses", + "dialog.provider.openrouter.note": "Access all supported models from one provider", + "dialog.provider.vercel.note": "Unified access to AI models with smart routing", "dialog.model.select.title": "Select model", "dialog.model.search.placeholder": "Search models", @@ -102,7 +110,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Free models provided by Kilo CLI", "dialog.model.unpaid.addMore.title": "Add more models from popular providers", - "dialog.provider.viewAll": "View all providers", + "dialog.provider.viewAll": "Show more providers", "provider.connect.title": "Connect {{provider}}", "provider.connect.title.anthropicProMax": "Login with Claude Pro/Max", @@ -139,6 +147,9 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} connected", "provider.connect.toast.connected.description": "{{provider}} models are now available to use.", + "provider.disconnect.toast.disconnected.title": "{{provider}} disconnected", + "provider.disconnect.toast.disconnected.description": "{{provider}} models are no longer available.", + "model.tag.free": "Free", "model.tag.latest": "Latest", "model.provider.anthropic": "Anthropic", @@ -157,10 +168,13 @@ export const dict = { "model.tooltip.context": "Context limit {{limit}}", "common.search.placeholder": "Search", - "common.goBack": "Go back", + "common.goBack": "Back", + "common.goForward": "Forward", "common.loading": "Loading", "common.loading.ellipsis": "...", "common.cancel": "Cancel", + "common.connect": "Connect", + "common.disconnect": "Disconnect", "common.submit": "Submit", "common.save": "Save", "common.saving": "Saving...", @@ -169,6 +183,8 @@ export const dict = { "prompt.placeholder.shell": "Enter shell command...", "prompt.placeholder.normal": 'Ask anything... "{{example}}"', + "prompt.placeholder.summarizeComments": "Summarize comments…", + "prompt.placeholder.summarizeComment": "Summarize comment…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc to exit", @@ -323,6 +339,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Language", "toast.language.description": "Switched to {{language}}", @@ -339,6 +356,10 @@ export const dict = { "toast.model.none.description": "Connect a provider to summarize this session", "toast.file.loadFailed.title": "Failed to load file", + "toast.file.listFailed.title": "Failed to list files", + + "toast.context.noLineSelection.title": "No line selection", + "toast.context.noLineSelection.description": "Select a line range in a file tab first.", "toast.session.share.copyFailed.title": "Failed to copy URL to clipboard", "toast.session.share.success.title": "Session shared", @@ -414,8 +435,15 @@ export const dict = { "session.tab.context": "Context", "session.panel.reviewAndFiles": "Review and files", "session.review.filesChanged": "{{count}} Files Changed", + "session.review.change.one": "Change", + "session.review.change.other": "Changes", "session.review.loadingChanges": "Loading changes...", "session.review.empty": "No changes in this session yet", + "session.review.noChanges": "No changes", + + "session.files.selectToOpen": "Select a file to open", + "session.files.all": "All files", + "session.messages.renderEarlier": "Render earlier messages", "session.messages.loadingEarlier": "Loading earlier messages...", "session.messages.loadEarlier": "Load earlier messages", @@ -492,12 +520,16 @@ export const dict = { "sidebar.project.recentSessions": "Recent sessions", "sidebar.project.viewAllSessions": "View all sessions", + "app.name.desktop": "OpenCode Desktop", + "settings.section.desktop": "Desktop", + "settings.section.server": "Server", "settings.tab.general": "General", "settings.tab.shortcuts": "Shortcuts", "settings.general.section.appearance": "Appearance", "settings.general.section.notifications": "System notifications", + "settings.general.section.updates": "Updates", "settings.general.section.sounds": "Sound effects", "settings.general.row.language.title": "Language", @@ -508,6 +540,18 @@ export const dict = { "settings.general.row.theme.description": "Customise how Kilo CLI is themed.", "settings.general.row.font.title": "Font", "settings.general.row.font.description": "Customise the mono font used in code blocks", + + "settings.general.row.releaseNotes.title": "Release notes", + "settings.general.row.releaseNotes.description": "Show What's New popups after updates", + + "settings.updates.row.startup.title": "Check for updates on startup", + "settings.updates.row.startup.description": "Automatically check for updates when OpenCode launches", + "settings.updates.row.check.title": "Check for updates", + "settings.updates.row.check.description": "Manually check for updates and install if available", + "settings.updates.action.checkNow": "Check now", + "settings.updates.action.checking": "Checking...", + "settings.updates.toast.latest.title": "You're up to date", + "settings.updates.toast.latest.description": "You're running the latest version of OpenCode.", "font.option.ibmPlexMono": "IBM Plex Mono", "font.option.cascadiaCode": "Cascadia Code", "font.option.firaCode": "Fira Code", @@ -601,6 +645,13 @@ export const dict = { "settings.providers.title": "Providers", "settings.providers.description": "Provider settings will be configurable here.", + "settings.providers.section.connected": "Connected providers", + "settings.providers.connected.empty": "No connected providers", + "settings.providers.section.popular": "Popular providers", + "settings.providers.tag.environment": "Environment", + "settings.providers.tag.config": "Config", + "settings.providers.tag.custom": "Custom", + "settings.providers.tag.other": "Other", "settings.models.title": "Models", "settings.models.description": "Model settings will be configurable here.", "settings.agents.title": "Agents", @@ -667,6 +718,7 @@ export const dict = { "workspace.reset.failed.title": "Failed to reset workspace", "workspace.reset.success.title": "Workspace reset", "workspace.reset.success.description": "Workspace now matches the default branch.", + "workspace.error.stillPreparing": "Workspace is still preparing", "workspace.status.checking": "Checking for unmerged changes...", "workspace.status.error": "Unable to verify git status.", "workspace.status.clean": "No unmerged changes detected.", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 6ca5a10099..c5c15dbc8a 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Tema", "command.category.language": "Idioma", "command.category.file": "Archivo", + "command.category.context": "Contexto", "command.category.terminal": "Terminal", "command.category.model": "Modelo", "command.category.mcp": "MCP", @@ -15,6 +16,7 @@ export const dict = { "command.category.permissions": "Permisos", "command.category.workspace": "Espacio de trabajo", + "command.category.settings": "Ajustes", "theme.scheme.system": "Sistema", "theme.scheme.light": "Claro", "theme.scheme.dark": "Oscuro", @@ -23,6 +25,7 @@ export const dict = { "command.project.open": "Abrir proyecto", "command.provider.connect": "Conectar proveedor", "command.server.switch": "Cambiar servidor", + "command.settings.open": "Abrir ajustes", "command.session.previous": "Sesión anterior", "command.session.next": "Siguiente sesión", "command.session.archive": "Archivar sesión", @@ -40,7 +43,10 @@ export const dict = { "command.session.new": "Nueva sesión", "command.file.open": "Abrir archivo", "command.file.open.description": "Buscar archivos y comandos", + "command.context.addSelection": "Añadir selección al contexto", + "command.context.addSelection.description": "Añadir las líneas seleccionadas del archivo actual", "command.terminal.toggle": "Alternar terminal", + "command.fileTree.toggle": "Alternar árbol de archivos", "command.review.toggle": "Alternar revisión", "command.terminal.new": "Nueva terminal", "command.terminal.new.description": "Crear una nueva pestaña de terminal", @@ -100,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Modelos gratuitos proporcionados por Kilo CLI", "dialog.model.unpaid.addMore.title": "Añadir más modelos de proveedores populares", - "dialog.provider.viewAll": "Ver todos los proveedores", + "dialog.provider.viewAll": "Ver más proveedores", "provider.connect.title": "Conectar {{provider}}", "provider.connect.title.anthropicProMax": "Iniciar sesión con Claude Pro/Max", @@ -137,13 +143,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} conectado", "provider.connect.toast.connected.description": "Los modelos de {{provider}} ahora están disponibles para usar.", + "provider.disconnect.toast.disconnected.title": "{{provider}} desconectado", + "provider.disconnect.toast.disconnected.description": "Los modelos de {{provider}} ya no están disponibles.", "model.tag.free": "Gratis", "model.tag.latest": "Último", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "texto", + "model.input.image": "imagen", + "model.input.audio": "audio", + "model.input.video": "video", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Permite: {{inputs}}", + "model.tooltip.reasoning.allowed": "Permite razonamiento", + "model.tooltip.reasoning.none": "Sin razonamiento", + "model.tooltip.context": "Límite de contexto {{limit}}", "common.search.placeholder": "Buscar", "common.goBack": "Volver", "common.loading": "Cargando", + "common.loading.ellipsis": "...", "common.cancel": "Cancelar", + "common.connect": "Conectar", + "common.disconnect": "Desconectar", "common.submit": "Enviar", "common.save": "Guardar", "common.saving": "Guardando...", @@ -152,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Introduce comando de shell...", "prompt.placeholder.normal": 'Pregunta cualquier cosa... "{{example}}"', + "prompt.placeholder.summarizeComments": "Resumir comentarios…", + "prompt.placeholder.summarizeComment": "Resumir comentario…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc para salir", @@ -255,6 +282,10 @@ export const dict = { "dialog.project.edit.color": "Color", "dialog.project.edit.color.select": "Seleccionar color {{color}}", + "dialog.project.edit.worktree.startup": "Script de inicio del espacio de trabajo", + "dialog.project.edit.worktree.startup.description": + "Se ejecuta después de crear un nuevo espacio de trabajo (árbol de trabajo).", + "dialog.project.edit.worktree.startup.placeholder": "p. ej. bun install", "context.breakdown.title": "Desglose de Contexto", "context.breakdown.note": 'Desglose aproximado de tokens de entrada. "Otro" incluye definiciones de herramientas y sobrecarga.', @@ -304,6 +335,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Idioma", "toast.language.description": "Cambiado a {{language}}", @@ -321,6 +353,9 @@ export const dict = { "toast.file.loadFailed.title": "Fallo al cargar archivo", + "toast.file.listFailed.title": "Fallo al listar archivos", + "toast.context.noLineSelection.title": "Sin selección de líneas", + "toast.context.noLineSelection.description": "Primero selecciona un rango de líneas en una pestaña de archivo.", "toast.session.share.copyFailed.title": "Fallo al copiar URL al portapapeles", "toast.session.share.success.title": "Sesión compartida", "toast.session.share.success.description": "¡URL compartida copiada al portapapeles!", @@ -396,13 +431,19 @@ export const dict = { "session.tab.context": "Contexto", "session.panel.reviewAndFiles": "Revisión y archivos", "session.review.filesChanged": "{{count}} Archivos Cambiados", + "session.review.change.one": "Cambio", + "session.review.change.other": "Cambios", "session.review.loadingChanges": "Cargando cambios...", "session.review.empty": "No hay cambios en esta sesión aún", + "session.review.noChanges": "Sin cambios", + "session.files.selectToOpen": "Selecciona un archivo para abrir", + "session.files.all": "Todos los archivos", "session.messages.renderEarlier": "Renderizar mensajes anteriores", "session.messages.loadingEarlier": "Cargando mensajes anteriores...", "session.messages.loadEarlier": "Cargar mensajes anteriores", "session.messages.loading": "Cargando mensajes...", + "session.messages.jumpToLatest": "Ir al último", "session.context.addToContext": "Añadir {{selection}} al contexto", "session.new.worktree.main": "Rama principal", @@ -444,6 +485,9 @@ export const dict = { "terminal.title.numbered": "Terminal {{number}}", "terminal.close": "Cerrar terminal", + "terminal.connectionLost.title": "Conexión perdida", + "terminal.connectionLost.description": + "La conexión del terminal se interrumpió. Esto puede ocurrir cuando el servidor se reinicia.", "common.closeTab": "Cerrar pestaña", "common.dismiss": "Descartar", "common.requestFailed": "Solicitud fallida", @@ -457,6 +501,8 @@ export const dict = { "common.edit": "Editar", "common.loadMore": "Cargar más", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "Alternar menú", "sidebar.nav.projectsAndSessions": "Proyectos y sesiones", "sidebar.settings": "Ajustes", "sidebar.help": "Ayuda", @@ -468,12 +514,15 @@ export const dict = { "sidebar.project.recentSessions": "Sesiones recientes", "sidebar.project.viewAllSessions": "Ver todas las sesiones", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Escritorio", + "settings.section.server": "Servidor", "settings.tab.general": "General", "settings.tab.shortcuts": "Atajos", "settings.general.section.appearance": "Apariencia", "settings.general.section.notifications": "Notificaciones del sistema", + "settings.general.section.updates": "Actualizaciones", "settings.general.section.sounds": "Efectos de sonido", "settings.general.row.language.title": "Idioma", @@ -485,6 +534,76 @@ export const dict = { "settings.general.row.font.title": "Fuente", "settings.general.row.font.description": "Personaliza la fuente mono usada en bloques de código", + "settings.general.row.releaseNotes.title": "Notas de la versión", + "settings.general.row.releaseNotes.description": + 'Mostrar ventanas emergentes de "Novedades" después de las actualizaciones', + + "settings.updates.row.startup.title": "Buscar actualizaciones al iniciar", + "settings.updates.row.startup.description": "Buscar actualizaciones automáticamente cuando se inicia OpenCode", + "settings.updates.row.check.title": "Buscar actualizaciones", + "settings.updates.row.check.description": "Buscar actualizaciones manualmente e instalarlas si hay alguna", + "settings.updates.action.checkNow": "Buscar ahora", + "settings.updates.action.checking": "Buscando...", + "settings.updates.toast.latest.title": "Estás al día", + "settings.updates.toast.latest.description": "Estás usando la última versión de OpenCode.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Alerta 01", + "sound.option.alert02": "Alerta 02", + "sound.option.alert03": "Alerta 03", + "sound.option.alert04": "Alerta 04", + "sound.option.alert05": "Alerta 05", + "sound.option.alert06": "Alerta 06", + "sound.option.alert07": "Alerta 07", + "sound.option.alert08": "Alerta 08", + "sound.option.alert09": "Alerta 09", + "sound.option.alert10": "Alerta 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "No 01", + "sound.option.nope02": "No 02", + "sound.option.nope03": "No 03", + "sound.option.nope04": "No 04", + "sound.option.nope05": "No 05", + "sound.option.nope06": "No 06", + "sound.option.nope07": "No 07", + "sound.option.nope08": "No 08", + "sound.option.nope09": "No 09", + "sound.option.nope10": "No 10", + "sound.option.nope11": "No 11", + "sound.option.nope12": "No 12", + "sound.option.yup01": "Sí 01", + "sound.option.yup02": "Sí 02", + "sound.option.yup03": "Sí 03", + "sound.option.yup04": "Sí 04", + "sound.option.yup05": "Sí 05", + "sound.option.yup06": "Sí 06", "settings.general.notifications.agent.title": "Agente", "settings.general.notifications.agent.description": "Mostrar notificación del sistema cuando el agente termine o necesite atención", @@ -522,6 +641,13 @@ export const dict = { "settings.providers.title": "Proveedores", "settings.providers.description": "La configuración de proveedores estará disponible aquí.", + "settings.providers.section.connected": "Proveedores conectados", + "settings.providers.connected.empty": "No hay proveedores conectados", + "settings.providers.section.popular": "Proveedores populares", + "settings.providers.tag.environment": "Entorno", + "settings.providers.tag.config": "Configuración", + "settings.providers.tag.custom": "Personalizado", + "settings.providers.tag.other": "Otro", "settings.models.title": "Modelos", "settings.models.description": "La configuración de modelos estará disponible aquí.", "settings.agents.title": "Agentes", @@ -589,6 +715,7 @@ export const dict = { "workspace.reset.failed.title": "Fallo al restablecer espacio de trabajo", "workspace.reset.success.title": "Espacio de trabajo restablecido", "workspace.reset.success.description": "El espacio de trabajo ahora coincide con la rama predeterminada.", + "workspace.error.stillPreparing": "El espacio de trabajo aún se está preparando", "workspace.status.checking": "Comprobando cambios no fusionados...", "workspace.status.error": "No se pudo verificar el estado de git.", "workspace.status.clean": "No se detectaron cambios no fusionados.", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index f8d1846ad4..fd9f7710a6 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Thème", "command.category.language": "Langue", "command.category.file": "Fichier", + "command.category.context": "Contexte", "command.category.terminal": "Terminal", "command.category.model": "Modèle", "command.category.mcp": "MCP", @@ -15,6 +16,7 @@ export const dict = { "command.category.permissions": "Permissions", "command.category.workspace": "Espace de travail", + "command.category.settings": "Paramètres", "theme.scheme.system": "Système", "theme.scheme.light": "Clair", "theme.scheme.dark": "Sombre", @@ -23,6 +25,7 @@ export const dict = { "command.project.open": "Ouvrir un projet", "command.provider.connect": "Connecter un fournisseur", "command.server.switch": "Changer de serveur", + "command.settings.open": "Ouvrir les paramètres", "command.session.previous": "Session précédente", "command.session.next": "Session suivante", "command.session.archive": "Archiver la session", @@ -40,7 +43,10 @@ export const dict = { "command.session.new": "Nouvelle session", "command.file.open": "Ouvrir un fichier", "command.file.open.description": "Rechercher des fichiers et des commandes", + "command.context.addSelection": "Ajouter la sélection au contexte", + "command.context.addSelection.description": "Ajouter les lignes sélectionnées du fichier actuel", "command.terminal.toggle": "Basculer le terminal", + "command.fileTree.toggle": "Basculer l'arborescence des fichiers", "command.review.toggle": "Basculer la revue", "command.terminal.new": "Nouveau terminal", "command.terminal.new.description": "Créer un nouvel onglet de terminal", @@ -100,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Modèles gratuits fournis par Kilo CLI", "dialog.model.unpaid.addMore.title": "Ajouter plus de modèles de fournisseurs populaires", - "dialog.provider.viewAll": "Voir tous les fournisseurs", + "dialog.provider.viewAll": "Voir plus de fournisseurs", "provider.connect.title": "Connecter {{provider}}", "provider.connect.title.anthropicProMax": "Connexion avec Claude Pro/Max", @@ -137,13 +143,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} connecté", "provider.connect.toast.connected.description": "Les modèles {{provider}} sont maintenant disponibles.", + "provider.disconnect.toast.disconnected.title": "{{provider}} déconnecté", + "provider.disconnect.toast.disconnected.description": "Les modèles {{provider}} ne sont plus disponibles.", "model.tag.free": "Gratuit", "model.tag.latest": "Dernier", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "texte", + "model.input.image": "image", + "model.input.audio": "audio", + "model.input.video": "vidéo", + "model.input.pdf": "pdf", + "model.tooltip.allows": "Autorise : {{inputs}}", + "model.tooltip.reasoning.allowed": "Autorise le raisonnement", + "model.tooltip.reasoning.none": "Sans raisonnement", + "model.tooltip.context": "Limite de contexte {{limit}}", "common.search.placeholder": "Rechercher", "common.goBack": "Retour", "common.loading": "Chargement", + "common.loading.ellipsis": "...", "common.cancel": "Annuler", + "common.connect": "Connecter", + "common.disconnect": "Déconnecter", "common.submit": "Soumettre", "common.save": "Enregistrer", "common.saving": "Enregistrement...", @@ -152,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Entrez une commande shell...", "prompt.placeholder.normal": 'Demandez n\'importe quoi... "{{example}}"', + "prompt.placeholder.summarizeComments": "Résumer les commentaires…", + "prompt.placeholder.summarizeComment": "Résumer le commentaire…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "esc pour quitter", @@ -255,6 +282,10 @@ export const dict = { "dialog.project.edit.color": "Couleur", "dialog.project.edit.color.select": "Sélectionner la couleur {{color}}", + "dialog.project.edit.worktree.startup": "Script de démarrage de l'espace de travail", + "dialog.project.edit.worktree.startup.description": + "S'exécute après la création d'un nouvel espace de travail (arbre de travail).", + "dialog.project.edit.worktree.startup.placeholder": "p. ex. bun install", "context.breakdown.title": "Répartition du contexte", "context.breakdown.note": "Répartition approximative des jetons d'entrée. \"Autre\" inclut les définitions d'outils et les frais généraux.", @@ -304,6 +335,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Langue", "toast.language.description": "Passé à {{language}}", @@ -323,6 +355,9 @@ export const dict = { "toast.file.loadFailed.title": "Échec du chargement du fichier", + "toast.file.listFailed.title": "Échec de la liste des fichiers", + "toast.context.noLineSelection.title": "Aucune sélection de lignes", + "toast.context.noLineSelection.description": "Sélectionnez d'abord une plage de lignes dans un onglet de fichier.", "toast.session.share.copyFailed.title": "Échec de la copie de l'URL dans le presse-papiers", "toast.session.share.success.title": "Session partagée", "toast.session.share.success.description": "URL de partage copiée dans le presse-papiers !", @@ -401,13 +436,19 @@ export const dict = { "session.tab.context": "Contexte", "session.panel.reviewAndFiles": "Revue et fichiers", "session.review.filesChanged": "{{count}} fichiers modifiés", + "session.review.change.one": "Modification", + "session.review.change.other": "Modifications", "session.review.loadingChanges": "Chargement des modifications...", "session.review.empty": "Aucune modification dans cette session pour l'instant", + "session.review.noChanges": "Aucune modification", + "session.files.selectToOpen": "Sélectionnez un fichier à ouvrir", + "session.files.all": "Tous les fichiers", "session.messages.renderEarlier": "Afficher les messages précédents", "session.messages.loadingEarlier": "Chargement des messages précédents...", "session.messages.loadEarlier": "Charger les messages précédents", "session.messages.loading": "Chargement des messages...", + "session.messages.jumpToLatest": "Aller au dernier", "session.context.addToContext": "Ajouter {{selection}} au contexte", "session.new.worktree.main": "Branche principale", @@ -449,6 +490,9 @@ export const dict = { "terminal.title.numbered": "Terminal {{number}}", "terminal.close": "Fermer le terminal", + "terminal.connectionLost.title": "Connexion perdue", + "terminal.connectionLost.description": + "La connexion au terminal a été interrompue. Cela peut arriver lorsque le serveur redémarre.", "common.closeTab": "Fermer l'onglet", "common.dismiss": "Ignorer", "common.requestFailed": "La demande a échoué", @@ -462,6 +506,8 @@ export const dict = { "common.edit": "Modifier", "common.loadMore": "Charger plus", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "Basculer le menu", "sidebar.nav.projectsAndSessions": "Projets et sessions", "sidebar.settings": "Paramètres", "sidebar.help": "Aide", @@ -475,12 +521,15 @@ export const dict = { "sidebar.project.recentSessions": "Sessions récentes", "sidebar.project.viewAllSessions": "Voir toutes les sessions", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Bureau", + "settings.section.server": "Serveur", "settings.tab.general": "Général", "settings.tab.shortcuts": "Raccourcis", "settings.general.section.appearance": "Apparence", "settings.general.section.notifications": "Notifications système", + "settings.general.section.updates": "Mises à jour", "settings.general.section.sounds": "Effets sonores", "settings.general.row.language.title": "Langue", @@ -492,6 +541,75 @@ export const dict = { "settings.general.row.font.title": "Police", "settings.general.row.font.description": "Personnaliser la police mono utilisée dans les blocs de code", + "settings.general.row.releaseNotes.title": "Notes de version", + "settings.general.row.releaseNotes.description": 'Afficher des pop-ups "Quoi de neuf" après les mises à jour', + + "settings.updates.row.startup.title": "Vérifier les mises à jour au démarrage", + "settings.updates.row.startup.description": "Vérifier automatiquement les mises à jour au lancement d'OpenCode", + "settings.updates.row.check.title": "Vérifier les mises à jour", + "settings.updates.row.check.description": "Vérifier manuellement les mises à jour et installer si disponible", + "settings.updates.action.checkNow": "Vérifier maintenant", + "settings.updates.action.checking": "Vérification...", + "settings.updates.toast.latest.title": "Vous êtes à jour", + "settings.updates.toast.latest.description": "Vous utilisez la dernière version d'OpenCode.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Alerte 01", + "sound.option.alert02": "Alerte 02", + "sound.option.alert03": "Alerte 03", + "sound.option.alert04": "Alerte 04", + "sound.option.alert05": "Alerte 05", + "sound.option.alert06": "Alerte 06", + "sound.option.alert07": "Alerte 07", + "sound.option.alert08": "Alerte 08", + "sound.option.alert09": "Alerte 09", + "sound.option.alert10": "Alerte 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Non 01", + "sound.option.nope02": "Non 02", + "sound.option.nope03": "Non 03", + "sound.option.nope04": "Non 04", + "sound.option.nope05": "Non 05", + "sound.option.nope06": "Non 06", + "sound.option.nope07": "Non 07", + "sound.option.nope08": "Non 08", + "sound.option.nope09": "Non 09", + "sound.option.nope10": "Non 10", + "sound.option.nope11": "Non 11", + "sound.option.nope12": "Non 12", + "sound.option.yup01": "Oui 01", + "sound.option.yup02": "Oui 02", + "sound.option.yup03": "Oui 03", + "sound.option.yup04": "Oui 04", + "sound.option.yup05": "Oui 05", + "sound.option.yup06": "Oui 06", "settings.general.notifications.agent.title": "Agent", "settings.general.notifications.agent.description": "Afficher une notification système lorsque l'agent a terminé ou nécessite une attention", @@ -528,6 +646,13 @@ export const dict = { "settings.providers.title": "Fournisseurs", "settings.providers.description": "Les paramètres des fournisseurs seront configurables ici.", + "settings.providers.section.connected": "Fournisseurs connectés", + "settings.providers.connected.empty": "Aucun fournisseur connecté", + "settings.providers.section.popular": "Fournisseurs populaires", + "settings.providers.tag.environment": "Environnement", + "settings.providers.tag.config": "Configuration", + "settings.providers.tag.custom": "Personnalisé", + "settings.providers.tag.other": "Autre", "settings.models.title": "Modèles", "settings.models.description": "Les paramètres des modèles seront configurables ici.", "settings.agents.title": "Agents", @@ -596,6 +721,7 @@ export const dict = { "workspace.reset.failed.title": "Échec de la réinitialisation de l'espace de travail", "workspace.reset.success.title": "Espace de travail réinitialisé", "workspace.reset.success.description": "L'espace de travail correspond maintenant à la branche par défaut.", + "workspace.error.stillPreparing": "L'espace de travail est encore en cours de préparation", "workspace.status.checking": "Vérification des modifications non fusionnées...", "workspace.status.error": "Impossible de vérifier le statut git.", "workspace.status.clean": "Aucune modification non fusionnée détectée.", diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index be77cf7f58..2400e011dc 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "テーマ", "command.category.language": "言語", "command.category.file": "ファイル", + "command.category.context": "コンテキスト", "command.category.terminal": "ターミナル", "command.category.model": "モデル", "command.category.mcp": "MCP", @@ -15,6 +16,7 @@ export const dict = { "command.category.permissions": "権限", "command.category.workspace": "ワークスペース", + "command.category.settings": "設定", "theme.scheme.system": "システム", "theme.scheme.light": "ライト", "theme.scheme.dark": "ダーク", @@ -23,6 +25,7 @@ export const dict = { "command.project.open": "プロジェクトを開く", "command.provider.connect": "プロバイダーに接続", "command.server.switch": "サーバーの切り替え", + "command.settings.open": "設定を開く", "command.session.previous": "前のセッション", "command.session.next": "次のセッション", "command.session.archive": "セッションをアーカイブ", @@ -40,7 +43,10 @@ export const dict = { "command.session.new": "新しいセッション", "command.file.open": "ファイルを開く", "command.file.open.description": "ファイルとコマンドを検索", + "command.context.addSelection": "選択範囲をコンテキストに追加", + "command.context.addSelection.description": "現在のファイルから選択した行を追加", "command.terminal.toggle": "ターミナルの切り替え", + "command.fileTree.toggle": "ファイルツリーを切り替え", "command.review.toggle": "レビューの切り替え", "command.terminal.new": "新しいターミナル", "command.terminal.new.description": "新しいターミナルタブを作成", @@ -100,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Kilo CLIが提供する無料モデル", "dialog.model.unpaid.addMore.title": "人気のプロバイダーからモデルを追加", - "dialog.provider.viewAll": "すべてのプロバイダーを表示", + "dialog.provider.viewAll": "さらにプロバイダーを表示", "provider.connect.title": "{{provider}}を接続", "provider.connect.title.anthropicProMax": "Claude Pro/Maxでログイン", @@ -136,13 +142,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}}が接続されました", "provider.connect.toast.connected.description": "{{provider}}モデルが使用可能になりました。", + "provider.disconnect.toast.disconnected.title": "{{provider}}が切断されました", + "provider.disconnect.toast.disconnected.description": "{{provider}}のモデルは利用できなくなりました。", "model.tag.free": "無料", "model.tag.latest": "最新", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "テキスト", + "model.input.image": "画像", + "model.input.audio": "音声", + "model.input.video": "動画", + "model.input.pdf": "pdf", + "model.tooltip.allows": "対応: {{inputs}}", + "model.tooltip.reasoning.allowed": "推論を許可", + "model.tooltip.reasoning.none": "推論なし", + "model.tooltip.context": "コンテキスト上限 {{limit}}", "common.search.placeholder": "検索", "common.goBack": "戻る", "common.loading": "読み込み中", + "common.loading.ellipsis": "...", "common.cancel": "キャンセル", + "common.connect": "接続", + "common.disconnect": "切断", "common.submit": "送信", "common.save": "保存", "common.saving": "保存中...", @@ -151,6 +176,8 @@ export const dict = { "prompt.placeholder.shell": "シェルコマンドを入力...", "prompt.placeholder.normal": '何でも聞いてください... "{{example}}"', + "prompt.placeholder.summarizeComments": "コメントを要約…", + "prompt.placeholder.summarizeComment": "コメントを要約…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "escで終了", @@ -254,6 +281,10 @@ export const dict = { "dialog.project.edit.color": "色", "dialog.project.edit.color.select": "{{color}}の色を選択", + "dialog.project.edit.worktree.startup": "ワークスペース起動スクリプト", + "dialog.project.edit.worktree.startup.description": + "新しいワークスペース (ワークツリー) を作成した後に実行されます。", + "dialog.project.edit.worktree.startup.placeholder": "例: bun install", "context.breakdown.title": "コンテキストの内訳", "context.breakdown.note": '入力トークンのおおよその内訳です。"その他"にはツールの定義やオーバーヘッドが含まれます。', "context.breakdown.system": "システム", @@ -302,6 +333,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "言語", "toast.language.description": "{{language}}に切り替えました", @@ -319,6 +351,9 @@ export const dict = { "toast.file.loadFailed.title": "ファイルの読み込みに失敗しました", + "toast.file.listFailed.title": "ファイル一覧の取得に失敗しました", + "toast.context.noLineSelection.title": "行が選択されていません", + "toast.context.noLineSelection.description": "まずファイルタブで行範囲を選択してください。", "toast.session.share.copyFailed.title": "URLのコピーに失敗しました", "toast.session.share.success.title": "セッションを共有しました", "toast.session.share.success.description": "共有URLをクリップボードにコピーしました!", @@ -393,13 +428,19 @@ export const dict = { "session.tab.context": "コンテキスト", "session.panel.reviewAndFiles": "レビューとファイル", "session.review.filesChanged": "{{count}} ファイル変更", + "session.review.change.one": "変更", + "session.review.change.other": "変更", "session.review.loadingChanges": "変更を読み込み中...", "session.review.empty": "このセッションでの変更はまだありません", + "session.review.noChanges": "変更なし", + "session.files.selectToOpen": "開くファイルを選択", + "session.files.all": "すべてのファイル", "session.messages.renderEarlier": "以前のメッセージを表示", "session.messages.loadingEarlier": "以前のメッセージを読み込み中...", "session.messages.loadEarlier": "以前のメッセージを読み込む", "session.messages.loading": "メッセージを読み込み中...", + "session.messages.jumpToLatest": "最新へジャンプ", "session.context.addToContext": "{{selection}}をコンテキストに追加", "session.new.worktree.main": "メインブランチ", @@ -441,6 +482,9 @@ export const dict = { "terminal.title.numbered": "ターミナル {{number}}", "terminal.close": "ターミナルを閉じる", + "terminal.connectionLost.title": "接続が失われました", + "terminal.connectionLost.description": + "ターミナルの接続が中断されました。これはサーバーが再起動したときに発生することがあります。", "common.closeTab": "タブを閉じる", "common.dismiss": "閉じる", "common.requestFailed": "リクエスト失敗", @@ -454,6 +498,8 @@ export const dict = { "common.edit": "編集", "common.loadMore": "さらに読み込む", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "メニューを切り替え", "sidebar.nav.projectsAndSessions": "プロジェクトとセッション", "sidebar.settings": "設定", "sidebar.help": "ヘルプ", @@ -465,12 +511,15 @@ export const dict = { "sidebar.project.recentSessions": "最近のセッション", "sidebar.project.viewAllSessions": "すべてのセッションを表示", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "デスクトップ", + "settings.section.server": "サーバー", "settings.tab.general": "一般", "settings.tab.shortcuts": "ショートカット", "settings.general.section.appearance": "外観", "settings.general.section.notifications": "システム通知", + "settings.general.section.updates": "アップデート", "settings.general.section.sounds": "効果音", "settings.general.row.language.title": "言語", @@ -482,6 +531,75 @@ export const dict = { "settings.general.row.font.title": "フォント", "settings.general.row.font.description": "コードブロックで使用する等幅フォントをカスタマイズします", + "settings.general.row.releaseNotes.title": "リリースノート", + "settings.general.row.releaseNotes.description": "アップデート後に「新機能」ポップアップを表示", + + "settings.updates.row.startup.title": "起動時にアップデートを確認", + "settings.updates.row.startup.description": "OpenCode の起動時に自動でアップデートを確認します", + "settings.updates.row.check.title": "アップデートを確認", + "settings.updates.row.check.description": "手動でアップデートを確認し、利用可能ならインストールします", + "settings.updates.action.checkNow": "今すぐ確認", + "settings.updates.action.checking": "確認中...", + "settings.updates.toast.latest.title": "最新です", + "settings.updates.toast.latest.description": "OpenCode は最新バージョンです。", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "アラート 01", + "sound.option.alert02": "アラート 02", + "sound.option.alert03": "アラート 03", + "sound.option.alert04": "アラート 04", + "sound.option.alert05": "アラート 05", + "sound.option.alert06": "アラート 06", + "sound.option.alert07": "アラート 07", + "sound.option.alert08": "アラート 08", + "sound.option.alert09": "アラート 09", + "sound.option.alert10": "アラート 10", + "sound.option.bipbop01": "ビップボップ 01", + "sound.option.bipbop02": "ビップボップ 02", + "sound.option.bipbop03": "ビップボップ 03", + "sound.option.bipbop04": "ビップボップ 04", + "sound.option.bipbop05": "ビップボップ 05", + "sound.option.bipbop06": "ビップボップ 06", + "sound.option.bipbop07": "ビップボップ 07", + "sound.option.bipbop08": "ビップボップ 08", + "sound.option.bipbop09": "ビップボップ 09", + "sound.option.bipbop10": "ビップボップ 10", + "sound.option.staplebops01": "ステープルボップス 01", + "sound.option.staplebops02": "ステープルボップス 02", + "sound.option.staplebops03": "ステープルボップス 03", + "sound.option.staplebops04": "ステープルボップス 04", + "sound.option.staplebops05": "ステープルボップス 05", + "sound.option.staplebops06": "ステープルボップス 06", + "sound.option.staplebops07": "ステープルボップス 07", + "sound.option.nope01": "いいえ 01", + "sound.option.nope02": "いいえ 02", + "sound.option.nope03": "いいえ 03", + "sound.option.nope04": "いいえ 04", + "sound.option.nope05": "いいえ 05", + "sound.option.nope06": "いいえ 06", + "sound.option.nope07": "いいえ 07", + "sound.option.nope08": "いいえ 08", + "sound.option.nope09": "いいえ 09", + "sound.option.nope10": "いいえ 10", + "sound.option.nope11": "いいえ 11", + "sound.option.nope12": "いいえ 12", + "sound.option.yup01": "はい 01", + "sound.option.yup02": "はい 02", + "sound.option.yup03": "はい 03", + "sound.option.yup04": "はい 04", + "sound.option.yup05": "はい 05", + "sound.option.yup06": "はい 06", "settings.general.notifications.agent.title": "エージェント", "settings.general.notifications.agent.description": "エージェントが完了したか、注意が必要な場合にシステム通知を表示します", @@ -517,6 +635,13 @@ export const dict = { "settings.providers.title": "プロバイダー", "settings.providers.description": "プロバイダー設定はここで構成できます。", + "settings.providers.section.connected": "接続済みプロバイダー", + "settings.providers.connected.empty": "接続済みプロバイダーはありません", + "settings.providers.section.popular": "人気のプロバイダー", + "settings.providers.tag.environment": "環境", + "settings.providers.tag.config": "設定", + "settings.providers.tag.custom": "カスタム", + "settings.providers.tag.other": "その他", "settings.models.title": "モデル", "settings.models.description": "モデル設定はここで構成できます。", "settings.agents.title": "エージェント", @@ -583,6 +708,7 @@ export const dict = { "workspace.reset.failed.title": "ワークスペースのリセットに失敗しました", "workspace.reset.success.title": "ワークスペースをリセットしました", "workspace.reset.success.description": "ワークスペースはデフォルトブランチと一致しています。", + "workspace.error.stillPreparing": "ワークスペースはまだ準備中です", "workspace.status.checking": "未マージの変更を確認中...", "workspace.status.error": "gitステータスを確認できません。", "workspace.status.clean": "未マージの変更は検出されませんでした。", diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index 7067ce4728..d0023199bf 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -12,6 +12,7 @@ export const dict = { "command.category.theme": "테마", "command.category.language": "언어", "command.category.file": "파일", + "command.category.context": "컨텍스트", "command.category.terminal": "터미널", "command.category.model": "모델", "command.category.mcp": "MCP", @@ -19,6 +20,7 @@ export const dict = { "command.category.permissions": "권한", "command.category.workspace": "작업 공간", + "command.category.settings": "설정", "theme.scheme.system": "시스템", "theme.scheme.light": "라이트", "theme.scheme.dark": "다크", @@ -27,6 +29,7 @@ export const dict = { "command.project.open": "프로젝트 열기", "command.provider.connect": "공급자 연결", "command.server.switch": "서버 전환", + "command.settings.open": "설정 열기", "command.session.previous": "이전 세션", "command.session.next": "다음 세션", "command.session.archive": "세션 보관", @@ -44,7 +47,10 @@ export const dict = { "command.session.new": "새 세션", "command.file.open": "파일 열기", "command.file.open.description": "파일 및 명령어 검색", + "command.context.addSelection": "선택 영역을 컨텍스트에 추가", + "command.context.addSelection.description": "현재 파일에서 선택한 줄을 추가", "command.terminal.toggle": "터미널 토글", + "command.fileTree.toggle": "파일 트리 토글", "command.review.toggle": "검토 토글", "command.terminal.new": "새 터미널", "command.terminal.new.description": "새 터미널 탭 생성", @@ -104,7 +110,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Kilo CLI에서 제공하는 무료 모델", "dialog.model.unpaid.addMore.title": "인기 공급자의 모델 추가", - "dialog.provider.viewAll": "모든 공급자 보기", + "dialog.provider.viewAll": "더 많은 공급자 보기", "provider.connect.title": "{{provider}} 연결", "provider.connect.title.anthropicProMax": "Claude Pro/Max로 로그인", @@ -140,13 +146,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} 연결됨", "provider.connect.toast.connected.description": "이제 {{provider}} 모델을 사용할 수 있습니다.", + "provider.disconnect.toast.disconnected.title": "{{provider}} 연결 해제됨", + "provider.disconnect.toast.disconnected.description": "{{provider}} 모델을 더 이상 사용할 수 없습니다.", "model.tag.free": "무료", "model.tag.latest": "최신", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "텍스트", + "model.input.image": "이미지", + "model.input.audio": "오디오", + "model.input.video": "비디오", + "model.input.pdf": "pdf", + "model.tooltip.allows": "지원: {{inputs}}", + "model.tooltip.reasoning.allowed": "추론 허용", + "model.tooltip.reasoning.none": "추론 없음", + "model.tooltip.context": "컨텍스트 제한 {{limit}}", "common.search.placeholder": "검색", "common.goBack": "뒤로 가기", "common.loading": "로딩 중", + "common.loading.ellipsis": "...", "common.cancel": "취소", + "common.connect": "연결", + "common.disconnect": "연결 해제", "common.submit": "제출", "common.save": "저장", "common.saving": "저장 중...", @@ -155,6 +180,8 @@ export const dict = { "prompt.placeholder.shell": "셸 명령어 입력...", "prompt.placeholder.normal": '무엇이든 물어보세요... "{{example}}"', + "prompt.placeholder.summarizeComments": "댓글 요약…", + "prompt.placeholder.summarizeComment": "댓글 요약…", "prompt.mode.shell": "셸", "prompt.mode.shell.exit": "종료하려면 esc", @@ -258,6 +285,9 @@ export const dict = { "dialog.project.edit.color": "색상", "dialog.project.edit.color.select": "{{color}} 색상 선택", + "dialog.project.edit.worktree.startup": "작업 공간 시작 스크립트", + "dialog.project.edit.worktree.startup.description": "새 작업 공간(작업 트리)을 만든 뒤 실행됩니다.", + "dialog.project.edit.worktree.startup.placeholder": "예: bun install", "context.breakdown.title": "컨텍스트 분석", "context.breakdown.note": '입력 토큰의 대략적인 분석입니다. "기타"에는 도구 정의 및 오버헤드가 포함됩니다.', "context.breakdown.system": "시스템", @@ -306,6 +336,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "언어", "toast.language.description": "{{language}}(으)로 전환됨", @@ -323,6 +354,9 @@ export const dict = { "toast.file.loadFailed.title": "파일 로드 실패", + "toast.file.listFailed.title": "파일 목록을 불러오지 못했습니다", + "toast.context.noLineSelection.title": "줄 선택 없음", + "toast.context.noLineSelection.description": "먼저 파일 탭에서 줄 범위를 선택하세요.", "toast.session.share.copyFailed.title": "URL 클립보드 복사 실패", "toast.session.share.success.title": "세션 공유됨", "toast.session.share.success.description": "공유 URL이 클립보드에 복사되었습니다!", @@ -396,13 +430,19 @@ export const dict = { "session.tab.context": "컨텍스트", "session.panel.reviewAndFiles": "검토 및 파일", "session.review.filesChanged": "{{count}}개 파일 변경됨", + "session.review.change.one": "변경", + "session.review.change.other": "변경", "session.review.loadingChanges": "변경 사항 로드 중...", "session.review.empty": "이 세션에 변경 사항이 아직 없습니다", + "session.review.noChanges": "변경 없음", + "session.files.selectToOpen": "열 파일을 선택하세요", + "session.files.all": "모든 파일", "session.messages.renderEarlier": "이전 메시지 렌더링", "session.messages.loadingEarlier": "이전 메시지 로드 중...", "session.messages.loadEarlier": "이전 메시지 로드", "session.messages.loading": "메시지 로드 중...", + "session.messages.jumpToLatest": "최신으로 이동", "session.context.addToContext": "컨텍스트에 {{selection}} 추가", "session.new.worktree.main": "메인 브랜치", @@ -443,6 +483,9 @@ export const dict = { "terminal.title.numbered": "터미널 {{number}}", "terminal.close": "터미널 닫기", + "terminal.connectionLost.title": "연결 끊김", + "terminal.connectionLost.description": + "터미널 연결이 중단되었습니다. 서버가 재시작하면 이런 일이 발생할 수 있습니다.", "common.closeTab": "탭 닫기", "common.dismiss": "닫기", "common.requestFailed": "요청 실패", @@ -456,6 +499,8 @@ export const dict = { "common.edit": "편집", "common.loadMore": "더 불러오기", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "메뉴 토글", "sidebar.nav.projectsAndSessions": "프로젝트 및 세션", "sidebar.settings": "설정", "sidebar.help": "도움말", @@ -467,12 +512,15 @@ export const dict = { "sidebar.project.recentSessions": "최근 세션", "sidebar.project.viewAllSessions": "모든 세션 보기", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "데스크톱", + "settings.section.server": "서버", "settings.tab.general": "일반", "settings.tab.shortcuts": "단축키", "settings.general.section.appearance": "모양", "settings.general.section.notifications": "시스템 알림", + "settings.general.section.updates": "업데이트", "settings.general.section.sounds": "효과음", "settings.general.row.language.title": "언어", @@ -484,6 +532,75 @@ export const dict = { "settings.general.row.font.title": "글꼴", "settings.general.row.font.description": "코드 블록에 사용되는 고정폭 글꼴 사용자 지정", + "settings.general.row.releaseNotes.title": "릴리스 노트", + "settings.general.row.releaseNotes.description": "업데이트 후 '새 소식' 팝업 표시", + + "settings.updates.row.startup.title": "시작 시 업데이트 확인", + "settings.updates.row.startup.description": "OpenCode를 실행할 때 업데이트를 자동으로 확인합니다", + "settings.updates.row.check.title": "업데이트 확인", + "settings.updates.row.check.description": "업데이트를 수동으로 확인하고, 사용 가능하면 설치합니다", + "settings.updates.action.checkNow": "지금 확인", + "settings.updates.action.checking": "확인 중...", + "settings.updates.toast.latest.title": "최신 상태입니다", + "settings.updates.toast.latest.description": "현재 최신 버전의 OpenCode를 사용 중입니다.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "알림 01", + "sound.option.alert02": "알림 02", + "sound.option.alert03": "알림 03", + "sound.option.alert04": "알림 04", + "sound.option.alert05": "알림 05", + "sound.option.alert06": "알림 06", + "sound.option.alert07": "알림 07", + "sound.option.alert08": "알림 08", + "sound.option.alert09": "알림 09", + "sound.option.alert10": "알림 10", + "sound.option.bipbop01": "빕-밥 01", + "sound.option.bipbop02": "빕-밥 02", + "sound.option.bipbop03": "빕-밥 03", + "sound.option.bipbop04": "빕-밥 04", + "sound.option.bipbop05": "빕-밥 05", + "sound.option.bipbop06": "빕-밥 06", + "sound.option.bipbop07": "빕-밥 07", + "sound.option.bipbop08": "빕-밥 08", + "sound.option.bipbop09": "빕-밥 09", + "sound.option.bipbop10": "빕-밥 10", + "sound.option.staplebops01": "스테이플밥스 01", + "sound.option.staplebops02": "스테이플밥스 02", + "sound.option.staplebops03": "스테이플밥스 03", + "sound.option.staplebops04": "스테이플밥스 04", + "sound.option.staplebops05": "스테이플밥스 05", + "sound.option.staplebops06": "스테이플밥스 06", + "sound.option.staplebops07": "스테이플밥스 07", + "sound.option.nope01": "아니오 01", + "sound.option.nope02": "아니오 02", + "sound.option.nope03": "아니오 03", + "sound.option.nope04": "아니오 04", + "sound.option.nope05": "아니오 05", + "sound.option.nope06": "아니오 06", + "sound.option.nope07": "아니오 07", + "sound.option.nope08": "아니오 08", + "sound.option.nope09": "아니오 09", + "sound.option.nope10": "아니오 10", + "sound.option.nope11": "아니오 11", + "sound.option.nope12": "아니오 12", + "sound.option.yup01": "네 01", + "sound.option.yup02": "네 02", + "sound.option.yup03": "네 03", + "sound.option.yup04": "네 04", + "sound.option.yup05": "네 05", + "sound.option.yup06": "네 06", "settings.general.notifications.agent.title": "에이전트", "settings.general.notifications.agent.description": "에이전트가 완료되거나 주의가 필요할 때 시스템 알림 표시", "settings.general.notifications.permissions.title": "권한", @@ -518,6 +635,13 @@ export const dict = { "settings.providers.title": "공급자", "settings.providers.description": "공급자 설정은 여기서 구성할 수 있습니다.", + "settings.providers.section.connected": "연결된 공급자", + "settings.providers.connected.empty": "연결된 공급자 없음", + "settings.providers.section.popular": "인기 공급자", + "settings.providers.tag.environment": "환경", + "settings.providers.tag.config": "구성", + "settings.providers.tag.custom": "사용자 지정", + "settings.providers.tag.other": "기타", "settings.models.title": "모델", "settings.models.description": "모델 설정은 여기서 구성할 수 있습니다.", "settings.agents.title": "에이전트", @@ -584,6 +708,7 @@ export const dict = { "workspace.reset.failed.title": "작업 공간 재설정 실패", "workspace.reset.success.title": "작업 공간 재설정됨", "workspace.reset.success.description": "작업 공간이 이제 기본 브랜치와 일치합니다.", + "workspace.error.stillPreparing": "작업 공간이 아직 준비 중입니다", "workspace.status.checking": "병합되지 않은 변경 사항 확인 중...", "workspace.status.error": "Git 상태를 확인할 수 없습니다.", "workspace.status.clean": "병합되지 않은 변경 사항이 감지되지 않았습니다.", diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index ab247fa250..503cf964cd 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -11,6 +11,7 @@ export const dict = { "command.category.theme": "Tema", "command.category.language": "Språk", "command.category.file": "Fil", + "command.category.context": "Kontekst", "command.category.terminal": "Terminal", "command.category.model": "Modell", "command.category.mcp": "MCP", @@ -45,7 +46,10 @@ export const dict = { "command.session.new": "Ny sesjon", "command.file.open": "Åpne fil", "command.file.open.description": "Søk i filer og kommandoer", + "command.context.addSelection": "Legg til markering i kontekst", + "command.context.addSelection.description": "Legg til valgte linjer fra gjeldende fil", "command.terminal.toggle": "Veksle terminal", + "command.fileTree.toggle": "Veksle filtre", "command.review.toggle": "Veksle gjennomgang", "command.terminal.new": "Ny terminal", "command.terminal.new.description": "Opprett en ny terminalfane", @@ -105,7 +109,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Gratis modeller levert av Kilo CLI", "dialog.model.unpaid.addMore.title": "Legg til flere modeller fra populære leverandører", - "dialog.provider.viewAll": "Vis alle leverandører", + "dialog.provider.viewAll": "Vis flere leverandører", "provider.connect.title": "Koble til {{provider}}", "provider.connect.title.anthropicProMax": "Logg inn med Claude Pro/Max", @@ -142,6 +146,8 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} tilkoblet", "provider.connect.toast.connected.description": "{{provider}}-modeller er nå tilgjengelige.", + "provider.disconnect.toast.disconnected.title": "{{provider}} frakoblet", + "provider.disconnect.toast.disconnected.description": "Modeller fra {{provider}} er ikke lenger tilgjengelige.", "model.tag.free": "Gratis", "model.tag.latest": "Nyeste", "model.provider.anthropic": "Anthropic", @@ -164,6 +170,8 @@ export const dict = { "common.loading": "Laster", "common.loading.ellipsis": "...", "common.cancel": "Avbryt", + "common.connect": "Koble til", + "common.disconnect": "Koble fra", "common.submit": "Send inn", "common.save": "Lagre", "common.saving": "Lagrer...", @@ -172,6 +180,8 @@ export const dict = { "prompt.placeholder.shell": "Skriv inn shell-kommando...", "prompt.placeholder.normal": 'Spør om hva som helst... "{{example}}"', + "prompt.placeholder.summarizeComments": "Oppsummer kommentarer…", + "prompt.placeholder.summarizeComment": "Oppsummer kommentar…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "ESC for å avslutte", @@ -275,6 +285,9 @@ export const dict = { "dialog.project.edit.color": "Farge", "dialog.project.edit.color.select": "Velg fargen {{color}}", + "dialog.project.edit.worktree.startup": "Oppstartsskript for arbeidsområde", + "dialog.project.edit.worktree.startup.description": "Kjører etter at et nytt arbeidsområde (worktree) er opprettet.", + "dialog.project.edit.worktree.startup.placeholder": "f.eks. bun install", "context.breakdown.title": "Kontekstfordeling", "context.breakdown.note": 'Omtrentlig fordeling av input-tokens. "Annet" inkluderer verktøydefinisjoner og overhead.', "context.breakdown.system": "System", @@ -323,6 +336,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Språk", "toast.language.description": "Byttet til {{language}}", @@ -340,6 +354,9 @@ export const dict = { "toast.file.loadFailed.title": "Kunne ikke laste fil", + "toast.file.listFailed.title": "Kunne ikke liste filer", + "toast.context.noLineSelection.title": "Ingen linjevalg", + "toast.context.noLineSelection.description": "Velg først et linjeområde i en filfane.", "toast.session.share.copyFailed.title": "Kunne ikke kopiere URL til utklippstavlen", "toast.session.share.success.title": "Sesjon delt", "toast.session.share.success.description": "Delings-URL kopiert til utklippstavlen!", @@ -414,8 +431,13 @@ export const dict = { "session.tab.context": "Kontekst", "session.panel.reviewAndFiles": "Gjennomgang og filer", "session.review.filesChanged": "{{count}} filer endret", + "session.review.change.one": "Endring", + "session.review.change.other": "Endringer", "session.review.loadingChanges": "Laster endringer...", "session.review.empty": "Ingen endringer i denne sesjonen ennå", + "session.review.noChanges": "Ingen endringer", + "session.files.selectToOpen": "Velg en fil å åpne", + "session.files.all": "Alle filer", "session.messages.renderEarlier": "Vis tidligere meldinger", "session.messages.loadingEarlier": "Laster inn tidligere meldinger...", "session.messages.loadEarlier": "Last inn tidligere meldinger", @@ -473,6 +495,7 @@ export const dict = { "common.learnMore": "Lær mer", "common.rename": "Gi nytt navn", "common.reset": "Tilbakestill", + "common.archive": "Arkiver", "common.delete": "Slett", "common.close": "Lukk", "common.edit": "Rediger", @@ -491,12 +514,15 @@ export const dict = { "sidebar.project.recentSessions": "Nylige sesjoner", "sidebar.project.viewAllSessions": "Vis alle sesjoner", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Skrivebord", + "settings.section.server": "Server", "settings.tab.general": "Generelt", "settings.tab.shortcuts": "Snarveier", "settings.general.section.appearance": "Utseende", "settings.general.section.notifications": "Systemvarsler", + "settings.general.section.updates": "Oppdateringer", "settings.general.section.sounds": "Lydeffekter", "settings.general.row.language.title": "Språk", @@ -508,6 +534,75 @@ export const dict = { "settings.general.row.font.title": "Skrift", "settings.general.row.font.description": "Tilpass mono-skriften som brukes i kodeblokker", + "settings.general.row.releaseNotes.title": "Utgivelsesnotater", + "settings.general.row.releaseNotes.description": 'Vis "Hva er nytt"-vinduer etter oppdateringer', + + "settings.updates.row.startup.title": "Se etter oppdateringer ved oppstart", + "settings.updates.row.startup.description": "Se automatisk etter oppdateringer når OpenCode starter", + "settings.updates.row.check.title": "Se etter oppdateringer", + "settings.updates.row.check.description": "Se etter oppdateringer manuelt og installer hvis tilgjengelig", + "settings.updates.action.checkNow": "Sjekk nå", + "settings.updates.action.checking": "Sjekker...", + "settings.updates.toast.latest.title": "Du er oppdatert", + "settings.updates.toast.latest.description": "Du bruker den nyeste versjonen av OpenCode.", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "Varsel 01", + "sound.option.alert02": "Varsel 02", + "sound.option.alert03": "Varsel 03", + "sound.option.alert04": "Varsel 04", + "sound.option.alert05": "Varsel 05", + "sound.option.alert06": "Varsel 06", + "sound.option.alert07": "Varsel 07", + "sound.option.alert08": "Varsel 08", + "sound.option.alert09": "Varsel 09", + "sound.option.alert10": "Varsel 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Nei 01", + "sound.option.nope02": "Nei 02", + "sound.option.nope03": "Nei 03", + "sound.option.nope04": "Nei 04", + "sound.option.nope05": "Nei 05", + "sound.option.nope06": "Nei 06", + "sound.option.nope07": "Nei 07", + "sound.option.nope08": "Nei 08", + "sound.option.nope09": "Nei 09", + "sound.option.nope10": "Nei 10", + "sound.option.nope11": "Nei 11", + "sound.option.nope12": "Nei 12", + "sound.option.yup01": "Ja 01", + "sound.option.yup02": "Ja 02", + "sound.option.yup03": "Ja 03", + "sound.option.yup04": "Ja 04", + "sound.option.yup05": "Ja 05", + "sound.option.yup06": "Ja 06", "settings.general.notifications.agent.title": "Agent", "settings.general.notifications.agent.description": "Vis systemvarsel når agenten er ferdig eller trenger oppmerksomhet", @@ -543,6 +638,13 @@ export const dict = { "settings.providers.title": "Leverandører", "settings.providers.description": "Leverandørinnstillinger vil kunne konfigureres her.", + "settings.providers.section.connected": "Tilkoblede leverandører", + "settings.providers.connected.empty": "Ingen tilkoblede leverandører", + "settings.providers.section.popular": "Populære leverandører", + "settings.providers.tag.environment": "Miljø", + "settings.providers.tag.config": "Konfigurasjon", + "settings.providers.tag.custom": "Tilpasset", + "settings.providers.tag.other": "Annet", "settings.models.title": "Modeller", "settings.models.description": "Modellinnstillinger vil kunne konfigureres her.", "settings.agents.title": "Agenter", @@ -595,6 +697,10 @@ export const dict = { "settings.permissions.tool.doom_loop.title": "Doom Loop", "settings.permissions.tool.doom_loop.description": "Oppdager gjentatte verktøykall med identisk input", + "session.delete.failed.title": "Kunne ikke slette sesjon", + "session.delete.title": "Slett sesjon", + "session.delete.confirm": 'Slette sesjonen "{{name}}"?', + "session.delete.button": "Slett sesjon", "workspace.new": "Nytt arbeidsområde", "workspace.type.local": "lokal", "workspace.type.sandbox": "sandkasse", @@ -605,6 +711,7 @@ export const dict = { "workspace.reset.failed.title": "Kunne ikke tilbakestille arbeidsområde", "workspace.reset.success.title": "Arbeidsområde tilbakestilt", "workspace.reset.success.description": "Arbeidsområdet samsvarer nå med standardgrenen.", + "workspace.error.stillPreparing": "Arbeidsområdet klargjøres fortsatt", "workspace.status.checking": "Sjekker for ikke-sammenslåtte endringer...", "workspace.status.error": "Kunne ikke bekrefte git-status.", "workspace.status.clean": "Ingen ikke-sammenslåtte endringer oppdaget.", diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index 500b4bb6ed..c93c51ecd8 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Motyw", "command.category.language": "Język", "command.category.file": "Plik", + "command.category.context": "Kontekst", "command.category.terminal": "Terminal", "command.category.model": "Model", "command.category.mcp": "MCP", @@ -42,7 +43,10 @@ export const dict = { "command.session.new": "Nowa sesja", "command.file.open": "Otwórz plik", "command.file.open.description": "Szukaj plików i poleceń", + "command.context.addSelection": "Dodaj zaznaczenie do kontekstu", + "command.context.addSelection.description": "Dodaj zaznaczone linie z bieżącego pliku", "command.terminal.toggle": "Przełącz terminal", + "command.fileTree.toggle": "Przełącz drzewo plików", "command.review.toggle": "Przełącz przegląd", "command.terminal.new": "Nowy terminal", "command.terminal.new.description": "Utwórz nową kartę terminala", @@ -102,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Darmowe modele dostarczane przez Kilo CLI", "dialog.model.unpaid.addMore.title": "Dodaj więcej modeli od popularnych dostawców", - "dialog.provider.viewAll": "Zobacz wszystkich dostawców", + "dialog.provider.viewAll": "Zobacz więcej dostawców", "provider.connect.title": "Połącz {{provider}}", "provider.connect.title.anthropicProMax": "Zaloguj się z Claude Pro/Max", @@ -139,6 +143,8 @@ export const dict = { "provider.connect.toast.connected.title": "Połączono {{provider}}", "provider.connect.toast.connected.description": "Modele {{provider}} są teraz dostępne do użycia.", + "provider.disconnect.toast.disconnected.title": "Rozłączono {{provider}}", + "provider.disconnect.toast.disconnected.description": "Modele {{provider}} nie są już dostępne.", "model.tag.free": "Darmowy", "model.tag.latest": "Najnowszy", "model.provider.anthropic": "Anthropic", @@ -161,6 +167,8 @@ export const dict = { "common.loading": "Ładowanie", "common.loading.ellipsis": "...", "common.cancel": "Anuluj", + "common.connect": "Połącz", + "common.disconnect": "Rozłącz", "common.submit": "Prześlij", "common.save": "Zapisz", "common.saving": "Zapisywanie...", @@ -169,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Wpisz polecenie terminala...", "prompt.placeholder.normal": 'Zapytaj o cokolwiek... "{{example}}"', + "prompt.placeholder.summarizeComments": "Podsumuj komentarze…", + "prompt.placeholder.summarizeComment": "Podsumuj komentarz…", "prompt.mode.shell": "Terminal", "prompt.mode.shell.exit": "esc aby wyjść", @@ -272,6 +282,10 @@ export const dict = { "dialog.project.edit.color": "Kolor", "dialog.project.edit.color.select": "Wybierz kolor {{color}}", + "dialog.project.edit.worktree.startup": "Skrypt uruchamiania przestrzeni roboczej", + "dialog.project.edit.worktree.startup.description": + "Uruchamiany po utworzeniu nowej przestrzeni roboczej (drzewa roboczego).", + "dialog.project.edit.worktree.startup.placeholder": "np. bun install", "context.breakdown.title": "Podział kontekstu", "context.breakdown.note": 'Przybliżony podział tokenów wejściowych. "Inne" obejmuje definicje narzędzi i narzut.', "context.breakdown.system": "System", @@ -320,6 +334,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Język", "toast.language.description": "Przełączono na {{language}}", @@ -337,6 +352,9 @@ export const dict = { "toast.file.loadFailed.title": "Nie udało się załadować pliku", + "toast.file.listFailed.title": "Nie udało się wyświetlić listy plików", + "toast.context.noLineSelection.title": "Brak zaznaczenia linii", + "toast.context.noLineSelection.description": "Najpierw wybierz zakres linii w zakładce pliku.", "toast.session.share.copyFailed.title": "Nie udało się skopiować URL do schowka", "toast.session.share.success.title": "Sesja udostępniona", "toast.session.share.success.description": "Link udostępniania skopiowany do schowka!", @@ -412,8 +430,13 @@ export const dict = { "session.tab.context": "Kontekst", "session.panel.reviewAndFiles": "Przegląd i pliki", "session.review.filesChanged": "Zmieniono {{count}} plików", + "session.review.change.one": "Zmiana", + "session.review.change.other": "Zmiany", "session.review.loadingChanges": "Ładowanie zmian...", "session.review.empty": "Brak zmian w tej sesji", + "session.review.noChanges": "Brak zmian", + "session.files.selectToOpen": "Wybierz plik do otwarcia", + "session.files.all": "Wszystkie pliki", "session.messages.renderEarlier": "Renderuj wcześniejsze wiadomości", "session.messages.loadingEarlier": "Ładowanie wcześniejszych wiadomości...", "session.messages.loadEarlier": "Załaduj wcześniejsze wiadomości", @@ -490,12 +513,15 @@ export const dict = { "sidebar.project.recentSessions": "Ostatnie sesje", "sidebar.project.viewAllSessions": "Zobacz wszystkie sesje", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Pulpit", + "settings.section.server": "Serwer", "settings.tab.general": "Ogólne", "settings.tab.shortcuts": "Skróty", "settings.general.section.appearance": "Wygląd", "settings.general.section.notifications": "Powiadomienia systemowe", + "settings.general.section.updates": "Aktualizacje", "settings.general.section.sounds": "Efekty dźwiękowe", "settings.general.row.language.title": "Język", @@ -506,12 +532,25 @@ export const dict = { "settings.general.row.theme.description": "Dostosuj motyw Kilo CLI.", "settings.general.row.font.title": "Czcionka", "settings.general.row.font.description": "Dostosuj czcionkę mono używaną w blokach kodu", + + "settings.general.row.releaseNotes.title": "Informacje o wydaniu", + "settings.general.row.releaseNotes.description": 'Pokazuj wyskakujące okna "Co nowego" po aktualizacjach', + + "settings.updates.row.startup.title": "Sprawdzaj aktualizacje przy uruchomieniu", + "settings.updates.row.startup.description": "Automatycznie sprawdzaj aktualizacje podczas uruchamiania OpenCode", + "settings.updates.row.check.title": "Sprawdź aktualizacje", + "settings.updates.row.check.description": "Ręcznie sprawdź aktualizacje i zainstaluj, jeśli są dostępne", + "settings.updates.action.checkNow": "Sprawdź teraz", + "settings.updates.action.checking": "Sprawdzanie...", + "settings.updates.toast.latest.title": "Masz najnowszą wersję", + "settings.updates.toast.latest.description": "Korzystasz z najnowszej wersji OpenCode.", "font.option.ibmPlexMono": "IBM Plex Mono", "font.option.cascadiaCode": "Cascadia Code", "font.option.firaCode": "Fira Code", "font.option.hack": "Hack", "font.option.inconsolata": "Inconsolata", "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", "font.option.jetbrainsMono": "JetBrains Mono", "font.option.mesloLgs": "Meslo LGS", "font.option.robotoMono": "Roboto Mono", @@ -599,6 +638,13 @@ export const dict = { "settings.providers.title": "Dostawcy", "settings.providers.description": "Ustawienia dostawców będą tutaj konfigurowalne.", + "settings.providers.section.connected": "Połączeni dostawcy", + "settings.providers.connected.empty": "Brak połączonych dostawców", + "settings.providers.section.popular": "Popularni dostawcy", + "settings.providers.tag.environment": "Środowisko", + "settings.providers.tag.config": "Konfiguracja", + "settings.providers.tag.custom": "Niestandardowe", + "settings.providers.tag.other": "Inne", "settings.models.title": "Modele", "settings.models.description": "Ustawienia modeli będą tutaj konfigurowalne.", "settings.agents.title": "Agenci", @@ -665,6 +711,7 @@ export const dict = { "workspace.reset.failed.title": "Nie udało się zresetować przestrzeni roboczej", "workspace.reset.success.title": "Przestrzeń robocza zresetowana", "workspace.reset.success.description": "Przestrzeń robocza odpowiada teraz domyślnej gałęzi.", + "workspace.error.stillPreparing": "Przestrzeń robocza jest wciąż przygotowywana", "workspace.status.checking": "Sprawdzanie niezscalonych zmian...", "workspace.status.error": "Nie można zweryfikować statusu git.", "workspace.status.clean": "Nie wykryto niezscalonych zmian.", diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index 0675889ea1..403ac382ee 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -8,6 +8,7 @@ export const dict = { "command.category.theme": "Тема", "command.category.language": "Язык", "command.category.file": "Файл", + "command.category.context": "Контекст", "command.category.terminal": "Терминал", "command.category.model": "Модель", "command.category.mcp": "MCP", @@ -42,7 +43,10 @@ export const dict = { "command.session.new": "Новая сессия", "command.file.open": "Открыть файл", "command.file.open.description": "Поиск файлов и команд", + "command.context.addSelection": "Добавить выделение в контекст", + "command.context.addSelection.description": "Добавить выбранные строки из текущего файла", "command.terminal.toggle": "Переключить терминал", + "command.fileTree.toggle": "Переключить дерево файлов", "command.review.toggle": "Переключить обзор", "command.terminal.new": "Новый терминал", "command.terminal.new.description": "Создать новую вкладку терминала", @@ -102,7 +106,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Бесплатные модели от Kilo CLI", "dialog.model.unpaid.addMore.title": "Добавьте больше моделей от популярных провайдеров", - "dialog.provider.viewAll": "Посмотреть всех провайдеров", + "dialog.provider.viewAll": "Показать больше провайдеров", "provider.connect.title": "Подключить {{provider}}", "provider.connect.title.anthropicProMax": "Войти с помощью Claude Pro/Max", @@ -139,6 +143,8 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} подключён", "provider.connect.toast.connected.description": "Модели {{provider}} теперь доступны.", + "provider.disconnect.toast.disconnected.title": "{{provider}} отключён", + "provider.disconnect.toast.disconnected.description": "Модели {{provider}} больше недоступны.", "model.tag.free": "Бесплатно", "model.tag.latest": "Последняя", "model.provider.anthropic": "Anthropic", @@ -161,6 +167,8 @@ export const dict = { "common.loading": "Загрузка", "common.loading.ellipsis": "...", "common.cancel": "Отмена", + "common.connect": "Подключить", + "common.disconnect": "Отключить", "common.submit": "Отправить", "common.save": "Сохранить", "common.saving": "Сохранение...", @@ -169,6 +177,8 @@ export const dict = { "prompt.placeholder.shell": "Введите команду оболочки...", "prompt.placeholder.normal": 'Спросите что угодно... "{{example}}"', + "prompt.placeholder.summarizeComments": "Суммировать комментарии…", + "prompt.placeholder.summarizeComment": "Суммировать комментарий…", "prompt.mode.shell": "Оболочка", "prompt.mode.shell.exit": "esc для выхода", @@ -272,6 +282,10 @@ export const dict = { "dialog.project.edit.color": "Цвет", "dialog.project.edit.color.select": "Выбрать цвет {{color}}", + "dialog.project.edit.worktree.startup": "Скрипт запуска рабочего пространства", + "dialog.project.edit.worktree.startup.description": + "Запускается после создания нового рабочего пространства (worktree).", + "dialog.project.edit.worktree.startup.placeholder": "например, bun install", "context.breakdown.title": "Разбивка контекста", "context.breakdown.note": 'Приблизительная разбивка входных токенов. "Другое" включает определения инструментов и накладные расходы.', @@ -321,6 +335,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "Язык", "toast.language.description": "Переключено на {{language}}", @@ -338,6 +353,9 @@ export const dict = { "toast.file.loadFailed.title": "Не удалось загрузить файл", + "toast.file.listFailed.title": "Не удалось получить список файлов", + "toast.context.noLineSelection.title": "Нет выделения строк", + "toast.context.noLineSelection.description": "Сначала выберите диапазон строк во вкладке файла.", "toast.session.share.copyFailed.title": "Не удалось скопировать URL в буфер обмена", "toast.session.share.success.title": "Сессия опубликована", "toast.session.share.success.description": "URL скопирован в буфер обмена!", @@ -414,8 +432,13 @@ export const dict = { "session.tab.context": "Контекст", "session.panel.reviewAndFiles": "Обзор и файлы", "session.review.filesChanged": "{{count}} файлов изменено", + "session.review.change.one": "Изменение", + "session.review.change.other": "Изменения", "session.review.loadingChanges": "Загрузка изменений...", "session.review.empty": "Изменений в этой сессии пока нет", + "session.review.noChanges": "Нет изменений", + "session.files.selectToOpen": "Выберите файл, чтобы открыть", + "session.files.all": "Все файлы", "session.messages.renderEarlier": "Показать предыдущие сообщения", "session.messages.loadingEarlier": "Загрузка предыдущих сообщений...", "session.messages.loadEarlier": "Загрузить предыдущие сообщения", @@ -493,12 +516,15 @@ export const dict = { "sidebar.project.recentSessions": "Недавние сессии", "sidebar.project.viewAllSessions": "Посмотреть все сессии", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "Приложение", + "settings.section.server": "Сервер", "settings.tab.general": "Основные", "settings.tab.shortcuts": "Горячие клавиши", "settings.general.section.appearance": "Внешний вид", "settings.general.section.notifications": "Системные уведомления", + "settings.general.section.updates": "Обновления", "settings.general.section.sounds": "Звуковые эффекты", "settings.general.row.language.title": "Язык", @@ -509,12 +535,25 @@ export const dict = { "settings.general.row.theme.description": "Настройте оформление Kilo CLI.", "settings.general.row.font.title": "Шрифт", "settings.general.row.font.description": "Настройте моноширинный шрифт для блоков кода", + + "settings.general.row.releaseNotes.title": "Примечания к выпуску", + "settings.general.row.releaseNotes.description": 'Показывать всплывающие окна "Что нового" после обновлений', + + "settings.updates.row.startup.title": "Проверять обновления при запуске", + "settings.updates.row.startup.description": "Автоматически проверять обновления при запуске OpenCode", + "settings.updates.row.check.title": "Проверить обновления", + "settings.updates.row.check.description": "Проверить обновления вручную и установить, если доступны", + "settings.updates.action.checkNow": "Проверить сейчас", + "settings.updates.action.checking": "Проверка...", + "settings.updates.toast.latest.title": "У вас последняя версия", + "settings.updates.toast.latest.description": "Вы используете последнюю версию OpenCode.", "font.option.ibmPlexMono": "IBM Plex Mono", "font.option.cascadiaCode": "Cascadia Code", "font.option.firaCode": "Fira Code", "font.option.hack": "Hack", "font.option.inconsolata": "Inconsolata", "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", "font.option.jetbrainsMono": "JetBrains Mono", "font.option.mesloLgs": "Meslo LGS", "font.option.robotoMono": "Roboto Mono", @@ -602,6 +641,13 @@ export const dict = { "settings.providers.title": "Провайдеры", "settings.providers.description": "Настройки провайдеров будут доступны здесь.", + "settings.providers.section.connected": "Подключённые провайдеры", + "settings.providers.connected.empty": "Нет подключённых провайдеров", + "settings.providers.section.popular": "Популярные провайдеры", + "settings.providers.tag.environment": "Среда", + "settings.providers.tag.config": "Конфигурация", + "settings.providers.tag.custom": "Пользовательский", + "settings.providers.tag.other": "Другое", "settings.models.title": "Модели", "settings.models.description": "Настройки моделей будут доступны здесь.", "settings.agents.title": "Агенты", @@ -669,6 +715,7 @@ export const dict = { "workspace.reset.failed.title": "Не удалось сбросить рабочее пространство", "workspace.reset.success.title": "Рабочее пространство сброшено", "workspace.reset.success.description": "Рабочее пространство теперь соответствует ветке по умолчанию.", + "workspace.error.stillPreparing": "Рабочее пространство всё ещё готовится", "workspace.status.checking": "Проверка наличия неслитых изменений...", "workspace.status.error": "Не удалось проверить статус git.", "workspace.status.clean": "Неслитые изменения не обнаружены.", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts new file mode 100644 index 0000000000..9ccb61ac76 --- /dev/null +++ b/packages/app/src/i18n/th.ts @@ -0,0 +1,718 @@ +export const dict = { + "command.category.suggested": "แนะนำ", + "command.category.view": "มุมมอง", + "command.category.project": "โปรเจกต์", + "command.category.provider": "ผู้ให้บริการ", + "command.category.server": "เซิร์ฟเวอร์", + "command.category.session": "เซสชัน", + "command.category.theme": "ธีม", + "command.category.language": "ภาษา", + "command.category.file": "ไฟล์", + "command.category.context": "บริบท", + "command.category.terminal": "เทอร์มินัล", + "command.category.model": "โมเดล", + "command.category.mcp": "MCP", + "command.category.agent": "เอเจนต์", + "command.category.permissions": "สิทธิ์", + "command.category.workspace": "พื้นที่ทำงาน", + "command.category.settings": "การตั้งค่า", + + "theme.scheme.system": "ระบบ", + "theme.scheme.light": "สว่าง", + "theme.scheme.dark": "มืด", + + "command.sidebar.toggle": "สลับแถบข้าง", + "command.project.open": "เปิดโปรเจกต์", + "command.provider.connect": "เชื่อมต่อผู้ให้บริการ", + "command.server.switch": "สลับเซิร์ฟเวอร์", + "command.settings.open": "เปิดการตั้งค่า", + "command.session.previous": "เซสชันก่อนหน้า", + "command.session.next": "เซสชันถัดไป", + "command.session.archive": "จัดเก็บเซสชัน", + + "command.palette": "คำสั่งค้นหา", + + "command.theme.cycle": "เปลี่ยนธีม", + "command.theme.set": "ใช้ธีม: {{theme}}", + "command.theme.scheme.cycle": "เปลี่ยนโทนสี", + "command.theme.scheme.set": "ใช้โทนสี: {{scheme}}", + + "command.language.cycle": "เปลี่ยนภาษา", + "command.language.set": "ใช้ภาษา: {{language}}", + + "command.session.new": "เซสชันใหม่", + "command.file.open": "เปิดไฟล์", + "command.file.open.description": "ค้นหาไฟล์และคำสั่ง", + "command.context.addSelection": "เพิ่มส่วนที่เลือกไปยังบริบท", + "command.context.addSelection.description": "เพิ่มบรรทัดที่เลือกจากไฟล์ปัจจุบัน", + "command.terminal.toggle": "สลับเทอร์มินัล", + "command.fileTree.toggle": "สลับต้นไม้ไฟล์", + "command.review.toggle": "สลับการตรวจสอบ", + "command.terminal.new": "เทอร์มินัลใหม่", + "command.terminal.new.description": "สร้างแท็บเทอร์มินัลใหม่", + "command.steps.toggle": "สลับขั้นตอน", + "command.steps.toggle.description": "แสดงหรือซ่อนขั้นตอนสำหรับข้อความปัจจุบัน", + "command.message.previous": "ข้อความก่อนหน้า", + "command.message.previous.description": "ไปที่ข้อความผู้ใช้ก่อนหน้า", + "command.message.next": "ข้อความถัดไป", + "command.message.next.description": "ไปที่ข้อความผู้ใช้ถัดไป", + "command.model.choose": "เลือกโมเดล", + "command.model.choose.description": "เลือกโมเดลอื่น", + "command.mcp.toggle": "สลับ MCPs", + "command.mcp.toggle.description": "สลับ MCPs", + "command.agent.cycle": "เปลี่ยนเอเจนต์", + "command.agent.cycle.description": "สลับไปยังเอเจนต์ถัดไป", + "command.agent.cycle.reverse": "เปลี่ยนเอเจนต์ย้อนกลับ", + "command.agent.cycle.reverse.description": "สลับไปยังเอเจนต์ก่อนหน้า", + "command.model.variant.cycle": "เปลี่ยนความพยายามในการคิด", + "command.model.variant.cycle.description": "สลับไปยังระดับความพยายามถัดไป", + "command.permissions.autoaccept.enable": "ยอมรับการแก้ไขโดยอัตโนมัติ", + "command.permissions.autoaccept.disable": "หยุดยอมรับการแก้ไขโดยอัตโนมัติ", + "command.session.undo": "ยกเลิก", + "command.session.undo.description": "ยกเลิกข้อความล่าสุด", + "command.session.redo": "ทำซ้ำ", + "command.session.redo.description": "ทำซ้ำข้อความที่ถูกยกเลิกล่าสุด", + "command.session.compact": "บีบอัดเซสชัน", + "command.session.compact.description": "สรุปเซสชันเพื่อลดขนาดบริบท", + "command.session.fork": "แตกแขนงจากข้อความ", + "command.session.fork.description": "สร้างเซสชันใหม่จากข้อความก่อนหน้า", + "command.session.share": "แชร์เซสชัน", + "command.session.share.description": "แชร์เซสชันนี้และคัดลอก URL ไปยังคลิปบอร์ด", + "command.session.unshare": "ยกเลิกการแชร์เซสชัน", + "command.session.unshare.description": "หยุดการแชร์เซสชันนี้", + + "palette.search.placeholder": "ค้นหาไฟล์และคำสั่ง", + "palette.empty": "ไม่พบผลลัพธ์", + "palette.group.commands": "คำสั่ง", + "palette.group.files": "ไฟล์", + + "dialog.provider.search.placeholder": "ค้นหาผู้ให้บริการ", + "dialog.provider.empty": "ไม่พบผู้ให้บริการ", + "dialog.provider.group.popular": "ยอดนิยม", + "dialog.provider.group.other": "อื่น ๆ", + "dialog.provider.tag.recommended": "แนะนำ", + "dialog.provider.opencode.note": "โมเดลที่คัดสรร รวมถึง Claude, GPT, Gemini และอื่น ๆ", + "dialog.provider.anthropic.note": "เข้าถึงโมเดล Claude โดยตรง รวมถึง Pro และ Max", + "dialog.provider.copilot.note": "โมเดล Claude สำหรับการช่วยเหลือในการเขียนโค้ด", + "dialog.provider.openai.note": "โมเดล GPT สำหรับงาน AI ทั่วไปที่รวดเร็วและมีความสามารถ", + "dialog.provider.google.note": "โมเดล Gemini สำหรับการตอบสนองที่รวดเร็วและมีโครงสร้าง", + "dialog.provider.openrouter.note": "เข้าถึงโมเดลที่รองรับทั้งหมดจากผู้ให้บริการเดียว", + "dialog.provider.vercel.note": "การเข้าถึงโมเดล AI แบบรวมด้วยการกำหนดเส้นทางอัจฉริยะ", + + "dialog.model.select.title": "เลือกโมเดล", + "dialog.model.search.placeholder": "ค้นหาโมเดล", + "dialog.model.empty": "ไม่พบผลลัพธ์โมเดล", + "dialog.model.manage": "จัดการโมเดล", + "dialog.model.manage.description": "ปรับแต่งโมเดลที่จะปรากฏในตัวเลือกโมเดล", + + "dialog.model.unpaid.freeModels.title": "โมเดลฟรีที่จัดหาให้โดย OpenCode", + "dialog.model.unpaid.addMore.title": "เพิ่มโมเดลเพิ่มเติมจากผู้ให้บริการยอดนิยม", + + "dialog.provider.viewAll": "แสดงผู้ให้บริการเพิ่มเติม", + + "provider.connect.title": "เชื่อมต่อ {{provider}}", + "provider.connect.title.anthropicProMax": "เข้าสู่ระบบด้วย Claude Pro/Max", + "provider.connect.selectMethod": "เลือกวิธีการเข้าสู่ระบบสำหรับ {{provider}}", + "provider.connect.method.apiKey": "คีย์ API", + "provider.connect.status.inProgress": "กำลังอนุญาต...", + "provider.connect.status.waiting": "รอการอนุญาต...", + "provider.connect.status.failed": "การอนุญาตล้มเหลว: {{error}}", + "provider.connect.apiKey.description": + "ป้อนคีย์ API ของ {{provider}} เพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน OpenCode", + "provider.connect.apiKey.label": "คีย์ API ของ {{provider}}", + "provider.connect.apiKey.placeholder": "คีย์ API", + "provider.connect.apiKey.required": "ต้องใช้คีย์ API", + "provider.connect.opencodeZen.line1": + "OpenCode Zen ให้คุณเข้าถึงชุดโมเดลที่เชื่อถือได้และปรับแต่งแล้วสำหรับเอเจนต์การเขียนโค้ด", + "provider.connect.opencodeZen.line2": + "ด้วยคีย์ API เดียวคุณจะได้รับการเข้าถึงโมเดล เช่น Claude, GPT, Gemini, GLM และอื่น ๆ", + "provider.connect.opencodeZen.visit.prefix": "เยี่ยมชม ", + "provider.connect.opencodeZen.visit.link": "opencode.ai/zen", + "provider.connect.opencodeZen.visit.suffix": " เพื่อรวบรวมคีย์ API ของคุณ", + "provider.connect.oauth.code.visit.prefix": "เยี่ยมชม ", + "provider.connect.oauth.code.visit.link": "ลิงก์นี้", + "provider.connect.oauth.code.visit.suffix": + " เพื่อรวบรวมรหัสการอนุญาตของคุณเพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน OpenCode", + "provider.connect.oauth.code.label": "รหัสการอนุญาต {{method}}", + "provider.connect.oauth.code.placeholder": "รหัสการอนุญาต", + "provider.connect.oauth.code.required": "ต้องใช้รหัสการอนุญาต", + "provider.connect.oauth.code.invalid": "รหัสการอนุญาตไม่ถูกต้อง", + "provider.connect.oauth.auto.visit.prefix": "เยี่ยมชม ", + "provider.connect.oauth.auto.visit.link": "ลิงก์นี้", + "provider.connect.oauth.auto.visit.suffix": + " และป้อนรหัสด้านล่างเพื่อเชื่อมต่อบัญชีและใช้โมเดล {{provider}} ใน OpenCode", + "provider.connect.oauth.auto.confirmationCode": "รหัสยืนยัน", + "provider.connect.toast.connected.title": "{{provider}} ที่เชื่อมต่อแล้ว", + "provider.connect.toast.connected.description": "โมเดล {{provider}} พร้อมใช้งานแล้ว", + + "provider.disconnect.toast.disconnected.title": "{{provider}} ที่ยกเลิกการเชื่อมต่อแล้ว", + "provider.disconnect.toast.disconnected.description": "โมเดล {{provider}} ไม่พร้อมใช้งานอีกต่อไป", + + "model.tag.free": "ฟรี", + "model.tag.latest": "ล่าสุด", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "ข้อความ", + "model.input.image": "รูปภาพ", + "model.input.audio": "เสียง", + "model.input.video": "วิดีโอ", + "model.input.pdf": "pdf", + "model.tooltip.allows": "อนุญาต: {{inputs}}", + "model.tooltip.reasoning.allowed": "อนุญาตการใช้เหตุผล", + "model.tooltip.reasoning.none": "ไม่มีการใช้เหตุผล", + "model.tooltip.context": "ขีดจำกัดบริบท {{limit}}", + + "common.search.placeholder": "ค้นหา", + "common.goBack": "ย้อนกลับ", + "common.loading": "กำลังโหลด", + "common.loading.ellipsis": "...", + "common.cancel": "ยกเลิก", + "common.connect": "เชื่อมต่อ", + "common.disconnect": "ยกเลิกการเชื่อมต่อ", + "common.submit": "ส่ง", + "common.save": "บันทึก", + "common.saving": "กำลังบันทึก...", + "common.default": "ค่าเริ่มต้น", + "common.attachment": "ไฟล์แนบ", + + "prompt.placeholder.shell": "ป้อนคำสั่งเชลล์...", + "prompt.placeholder.normal": 'ถามอะไรก็ได้... "{{example}}"', + "prompt.placeholder.summarizeComments": "สรุปความคิดเห็น…", + "prompt.placeholder.summarizeComment": "สรุปความคิดเห็น…", + "prompt.mode.shell": "เชลล์", + "prompt.mode.shell.exit": "กด esc เพื่อออก", + + "prompt.example.1": "แก้ไข TODO ในโค้ดเบส", + "prompt.example.2": "เทคโนโลยีของโปรเจกต์นี้คืออะไร?", + "prompt.example.3": "แก้ไขการทดสอบที่เสีย", + "prompt.example.4": "อธิบายวิธีการทำงานของการตรวจสอบสิทธิ์", + "prompt.example.5": "ค้นหาและแก้ไขช่องโหว่ความปลอดภัย", + "prompt.example.6": "เพิ่มการทดสอบหน่วยสำหรับบริการผู้ใช้", + "prompt.example.7": "ปรับโครงสร้างฟังก์ชันนี้ให้อ่านง่ายขึ้น", + "prompt.example.8": "ข้อผิดพลาดนี้หมายความว่าอะไร?", + "prompt.example.9": "ช่วยฉันดีบักปัญหานี้", + "prompt.example.10": "สร้างเอกสาร API", + "prompt.example.11": "ปรับปรุงการสืบค้นฐานข้อมูล", + "prompt.example.12": "เพิ่มการตรวจสอบข้อมูลนำเข้า", + "prompt.example.13": "สร้างคอมโพเนนต์ใหม่สำหรับ...", + "prompt.example.14": "ฉันจะทำให้โปรเจกต์นี้ทำงานได้อย่างไร?", + "prompt.example.15": "ตรวจสอบโค้ดของฉันเพื่อแนวทางปฏิบัติที่ดีที่สุด", + "prompt.example.16": "เพิ่มการจัดการข้อผิดพลาดในฟังก์ชันนี้", + "prompt.example.17": "อธิบายรูปแบบ regex นี้", + "prompt.example.18": "แปลงสิ่งนี้เป็น TypeScript", + "prompt.example.19": "เพิ่มการบันทึกทั่วทั้งโค้ดเบส", + "prompt.example.20": "มีการพึ่งพาอะไรที่ล้าสมัยอยู่?", + "prompt.example.21": "ช่วยฉันเขียนสคริปต์การย้ายข้อมูล", + "prompt.example.22": "ใช้งานแคชสำหรับจุดสิ้นสุดนี้", + "prompt.example.23": "เพิ่มการแบ่งหน้าในรายการนี้", + "prompt.example.24": "สร้างคำสั่ง CLI สำหรับ...", + "prompt.example.25": "ตัวแปรสภาพแวดล้อมทำงานอย่างไรที่นี่?", + + "prompt.popover.emptyResults": "ไม่พบผลลัพธ์ที่ตรงกัน", + "prompt.popover.emptyCommands": "ไม่พบคำสั่งที่ตรงกัน", + "prompt.dropzone.label": "วางรูปภาพหรือ PDF ที่นี่", + "prompt.slash.badge.custom": "กำหนดเอง", + "prompt.context.active": "ใช้งานอยู่", + "prompt.context.includeActiveFile": "รวมไฟล์ที่ใช้งานอยู่", + "prompt.context.removeActiveFile": "เอาไฟล์ที่ใช้งานอยู่ออกจากบริบท", + "prompt.context.removeFile": "เอาไฟล์ออกจากบริบท", + "prompt.action.attachFile": "แนบไฟล์", + "prompt.attachment.remove": "เอาไฟล์แนบออก", + "prompt.action.send": "ส่ง", + "prompt.action.stop": "หยุด", + + "prompt.toast.pasteUnsupported.title": "การวางไม่รองรับ", + "prompt.toast.pasteUnsupported.description": "สามารถวางรูปภาพหรือ PDF เท่านั้น", + "prompt.toast.modelAgentRequired.title": "เลือกเอเจนต์และโมเดล", + "prompt.toast.modelAgentRequired.description": "เลือกเอเจนต์และโมเดลก่อนส่งพร้อมท์", + "prompt.toast.worktreeCreateFailed.title": "ไม่สามารถสร้าง worktree", + "prompt.toast.sessionCreateFailed.title": "ไม่สามารถสร้างเซสชัน", + "prompt.toast.shellSendFailed.title": "ไม่สามารถส่งคำสั่งเชลล์", + "prompt.toast.commandSendFailed.title": "ไม่สามารถส่งคำสั่ง", + "prompt.toast.promptSendFailed.title": "ไม่สามารถส่งพร้อมท์", + + "dialog.mcp.title": "MCPs", + "dialog.mcp.description": "{{enabled}} จาก {{total}} ที่เปิดใช้งาน", + "dialog.mcp.empty": "ไม่มี MCP ที่กำหนดค่า", + + "dialog.lsp.empty": "LSPs ตรวจจับอัตโนมัติจากประเภทไฟล์", + "dialog.plugins.empty": "ปลั๊กอินที่กำหนดค่าใน opencode.json", + + "mcp.status.connected": "เชื่อมต่อแล้ว", + "mcp.status.failed": "ล้มเหลว", + "mcp.status.needs_auth": "ต้องการการตรวจสอบสิทธิ์", + "mcp.status.disabled": "ปิดใช้งาน", + + "dialog.fork.empty": "ไม่มีข้อความให้แตกแขนง", + + "dialog.directory.search.placeholder": "ค้นหาโฟลเดอร์", + "dialog.directory.empty": "ไม่พบโฟลเดอร์", + + "dialog.server.title": "เซิร์ฟเวอร์", + "dialog.server.description": "สลับเซิร์ฟเวอร์ OpenCode ที่แอปนี้เชื่อมต่อด้วย", + "dialog.server.search.placeholder": "ค้นหาเซิร์ฟเวอร์", + "dialog.server.empty": "ยังไม่มีเซิร์ฟเวอร์", + "dialog.server.add.title": "เพิ่มเซิร์ฟเวอร์", + "dialog.server.add.url": "URL เซิร์ฟเวอร์", + "dialog.server.add.placeholder": "http://localhost:4096", + "dialog.server.add.error": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์", + "dialog.server.add.checking": "กำลังตรวจสอบ...", + "dialog.server.add.button": "เพิ่มเซิร์ฟเวอร์", + "dialog.server.default.title": "เซิร์ฟเวอร์เริ่มต้น", + "dialog.server.default.description": + "เชื่อมต่อกับเซิร์ฟเวอร์นี้เมื่อเปิดแอปแทนการเริ่มเซิร์ฟเวอร์ในเครื่อง ต้องรีสตาร์ท", + "dialog.server.default.none": "ไม่ได้เลือกเซิร์ฟเวอร์", + "dialog.server.default.set": "ตั้งเซิร์ฟเวอร์ปัจจุบันเป็นค่าเริ่มต้น", + "dialog.server.default.clear": "ล้าง", + "dialog.server.action.remove": "เอาเซิร์ฟเวอร์ออก", + + "dialog.server.menu.edit": "แก้ไข", + "dialog.server.menu.default": "ตั้งเป็นค่าเริ่มต้น", + "dialog.server.menu.defaultRemove": "เอาค่าเริ่มต้นออก", + "dialog.server.menu.delete": "ลบ", + "dialog.server.current": "เซิร์ฟเวอร์ปัจจุบัน", + "dialog.server.status.default": "ค่าเริ่มต้น", + + "dialog.project.edit.title": "แก้ไขโปรเจกต์", + "dialog.project.edit.name": "ชื่อ", + "dialog.project.edit.icon": "ไอคอน", + "dialog.project.edit.icon.alt": "ไอคอนโปรเจกต์", + "dialog.project.edit.icon.hint": "คลิกหรือลากรูปภาพ", + "dialog.project.edit.icon.recommended": "แนะนำ: 128x128px", + "dialog.project.edit.color": "สี", + "dialog.project.edit.color.select": "เลือกสี {{color}}", + "dialog.project.edit.worktree.startup": "สคริปต์เริ่มต้นพื้นที่ทำงาน", + "dialog.project.edit.worktree.startup.description": "ทำงานหลังจากสร้างพื้นที่ทำงานใหม่ (worktree)", + "dialog.project.edit.worktree.startup.placeholder": "เช่น bun install", + + "context.breakdown.title": "การแบ่งบริบท", + "context.breakdown.note": 'การแบ่งโดยประมาณของโทเค็นนำเข้า "อื่น ๆ" รวมถึงคำนิยามเครื่องมือและโอเวอร์เฮด', + "context.breakdown.system": "ระบบ", + "context.breakdown.user": "ผู้ใช้", + "context.breakdown.assistant": "ผู้ช่วย", + "context.breakdown.tool": "การเรียกเครื่องมือ", + "context.breakdown.other": "อื่น ๆ", + + "context.systemPrompt.title": "พร้อมท์ระบบ", + "context.rawMessages.title": "ข้อความดิบ", + + "context.stats.session": "เซสชัน", + "context.stats.messages": "ข้อความ", + "context.stats.provider": "ผู้ให้บริการ", + "context.stats.model": "โมเดล", + "context.stats.limit": "ขีดจำกัดบริบท", + "context.stats.totalTokens": "โทเค็นทั้งหมด", + "context.stats.usage": "การใช้งาน", + "context.stats.inputTokens": "โทเค็นนำเข้า", + "context.stats.outputTokens": "โทเค็นส่งออก", + "context.stats.reasoningTokens": "โทเค็นการใช้เหตุผล", + "context.stats.cacheTokens": "โทเค็นแคช (อ่าน/เขียน)", + "context.stats.userMessages": "ข้อความผู้ใช้", + "context.stats.assistantMessages": "ข้อความผู้ช่วย", + "context.stats.totalCost": "ต้นทุนทั้งหมด", + "context.stats.sessionCreated": "สร้างเซสชันเมื่อ", + "context.stats.lastActivity": "กิจกรรมล่าสุด", + + "context.usage.tokens": "โทเค็น", + "context.usage.usage": "การใช้งาน", + "context.usage.cost": "ต้นทุน", + "context.usage.clickToView": "คลิกเพื่อดูบริบท", + "context.usage.view": "ดูการใช้บริบท", + + "language.en": "อังกฤษ", + "language.zh": "จีนตัวย่อ", + "language.zht": "จีนตัวเต็ม", + "language.ko": "เกาหลี", + "language.de": "เยอรมัน", + "language.es": "สเปน", + "language.fr": "ฝรั่งเศส", + "language.da": "เดนมาร์ก", + "language.ja": "ญี่ปุ่น", + "language.pl": "โปแลนด์", + "language.ru": "รัสเซีย", + "language.ar": "อาหรับ", + "language.no": "นอร์เวย์", + "language.br": "โปรตุเกส (บราซิล)", + "language.th": "ไทย", + + "toast.language.title": "ภาษา", + "toast.language.description": "สลับไปที่ {{language}}", + + "toast.theme.title": "สลับธีมแล้ว", + "toast.scheme.title": "โทนสี", + + "toast.permissions.autoaccept.on.title": "กำลังยอมรับการแก้ไขโดยอัตโนมัติ", + "toast.permissions.autoaccept.on.description": "สิทธิ์การแก้ไขและเขียนจะได้รับการอนุมัติโดยอัตโนมัติ", + "toast.permissions.autoaccept.off.title": "หยุดยอมรับการแก้ไขโดยอัตโนมัติ", + "toast.permissions.autoaccept.off.description": "สิทธิ์การแก้ไขและเขียนจะต้องได้รับการอนุมัติ", + + "toast.model.none.title": "ไม่ได้เลือกโมเดล", + "toast.model.none.description": "เชื่อมต่อผู้ให้บริการเพื่อสรุปเซสชันนี้", + + "toast.file.loadFailed.title": "ไม่สามารถโหลดไฟล์", + "toast.file.listFailed.title": "ไม่สามารถแสดงรายการไฟล์", + + "toast.context.noLineSelection.title": "ไม่มีการเลือกบรรทัด", + "toast.context.noLineSelection.description": "เลือกช่วงบรรทัดในแท็บไฟล์ก่อน", + + "toast.session.share.copyFailed.title": "ไม่สามารถคัดลอก URL ไปยังคลิปบอร์ด", + "toast.session.share.success.title": "แชร์เซสชันแล้ว", + "toast.session.share.success.description": "คัดลอก URL แชร์ไปยังคลิปบอร์ดแล้ว!", + "toast.session.share.failed.title": "ไม่สามารถแชร์เซสชัน", + "toast.session.share.failed.description": "เกิดข้อผิดพลาดระหว่างการแชร์เซสชัน", + + "toast.session.unshare.success.title": "ยกเลิกการแชร์เซสชันแล้ว", + "toast.session.unshare.success.description": "ยกเลิกการแชร์เซสชันสำเร็จ!", + "toast.session.unshare.failed.title": "ไม่สามารถยกเลิกการแชร์เซสชัน", + "toast.session.unshare.failed.description": "เกิดข้อผิดพลาดระหว่างการยกเลิกการแชร์เซสชัน", + + "toast.session.listFailed.title": "ไม่สามารถโหลดเซสชันสำหรับ {{project}}", + + "toast.update.title": "มีการอัปเดต", + "toast.update.description": "เวอร์ชันใหม่ของ OpenCode ({{version}}) พร้อมใช้งานสำหรับติดตั้ง", + "toast.update.action.installRestart": "ติดตั้งและรีสตาร์ท", + "toast.update.action.notYet": "ยังไม่", + + "error.page.title": "เกิดข้อผิดพลาด", + "error.page.description": "เกิดข้อผิดพลาดระหว่างการโหลดแอปพลิเคชัน", + "error.page.details.label": "รายละเอียดข้อผิดพลาด", + "error.page.action.restart": "รีสตาร์ท", + "error.page.action.checking": "กำลังตรวจสอบ...", + "error.page.action.checkUpdates": "ตรวจสอบการอัปเดต", + "error.page.action.updateTo": "อัปเดตเป็น {{version}}", + "error.page.report.prefix": "โปรดรายงานข้อผิดพลาดนี้ให้ทีม OpenCode", + "error.page.report.discord": "บน Discord", + "error.page.version": "เวอร์ชัน: {{version}}", + + "error.dev.rootNotFound": "ไม่พบองค์ประกอบรูท คุณลืมเพิ่มใน index.html หรือบางทีแอตทริบิวต์ id อาจสะกดผิด?", + + "error.globalSync.connectFailed": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ มีเซิร์ฟเวอร์ทำงานอยู่ที่ `{{url}}` หรือไม่?", + + "error.chain.unknown": "ข้อผิดพลาดที่ไม่รู้จัก", + "error.chain.causedBy": "สาเหตุ:", + "error.chain.apiError": "ข้อผิดพลาด API", + "error.chain.status": "สถานะ: {{status}}", + "error.chain.retryable": "สามารถลองใหม่: {{retryable}}", + "error.chain.responseBody": "เนื้อหาการตอบสนอง:\n{{body}}", + "error.chain.didYouMean": "คุณหมายถึง: {{suggestions}}", + "error.chain.modelNotFound": "ไม่พบโมเดล: {{provider}}/{{model}}", + "error.chain.checkConfig": "ตรวจสอบการกำหนดค่าของคุณ (opencode.json) ชื่อผู้ให้บริการ/โมเดล", + "error.chain.mcpFailed": 'เซิร์ฟเวอร์ MCP "{{name}}" ล้มเหลว โปรดทราบว่า OpenCode ยังไม่รองรับการตรวจสอบสิทธิ์ MCP', + "error.chain.providerAuthFailed": "การตรวจสอบสิทธิ์ผู้ให้บริการล้มเหลว ({{provider}}): {{message}}", + "error.chain.providerInitFailed": 'ไม่สามารถเริ่มต้นผู้ให้บริการ "{{provider}}" ตรวจสอบข้อมูลรับรองและการกำหนดค่า', + "error.chain.configJsonInvalid": "ไฟล์กำหนดค่าที่ {{path}} ไม่ใช่ JSON(C) ที่ถูกต้อง", + "error.chain.configJsonInvalidWithMessage": "ไฟล์กำหนดค่าที่ {{path}} ไม่ใช่ JSON(C) ที่ถูกต้อง: {{message}}", + "error.chain.configDirectoryTypo": + 'ไดเรกทอรี "{{dir}}" ใน {{path}} ไม่ถูกต้อง เปลี่ยนชื่อไดเรกทอรีเป็น "{{suggestion}}" หรือเอาออก นี่เป็นการสะกดผิดทั่วไป', + "error.chain.configFrontmatterError": "ไม่สามารถแยกวิเคราะห์ frontmatter ใน {{path}}:\n{{message}}", + "error.chain.configInvalid": "ไฟล์กำหนดค่าที่ {{path}} ไม่ถูกต้อง", + "error.chain.configInvalidWithMessage": "ไฟล์กำหนดค่าที่ {{path}} ไม่ถูกต้อง: {{message}}", + + "notification.permission.title": "ต้องการสิทธิ์", + "notification.permission.description": "{{sessionTitle}} ใน {{projectName}} ต้องการสิทธิ์", + "notification.question.title": "คำถาม", + "notification.question.description": "{{sessionTitle}} ใน {{projectName}} มีคำถาม", + "notification.action.goToSession": "ไปที่เซสชัน", + + "notification.session.responseReady.title": "การตอบสนองพร้อม", + "notification.session.error.title": "ข้อผิดพลาดเซสชัน", + "notification.session.error.fallbackDescription": "เกิดข้อผิดพลาด", + + "home.recentProjects": "โปรเจกต์ล่าสุด", + "home.empty.title": "ไม่มีโปรเจกต์ล่าสุด", + "home.empty.description": "เริ่มต้นโดยเปิดโปรเจกต์ในเครื่อง", + + "session.tab.session": "เซสชัน", + "session.tab.review": "ตรวจสอบ", + "session.tab.context": "บริบท", + "session.panel.reviewAndFiles": "ตรวจสอบและไฟล์", + "session.review.filesChanged": "{{count}} ไฟล์ที่เปลี่ยนแปลง", + "session.review.change.one": "การเปลี่ยนแปลง", + "session.review.change.other": "การเปลี่ยนแปลง", + "session.review.loadingChanges": "กำลังโหลดการเปลี่ยนแปลง...", + "session.review.empty": "ยังไม่มีการเปลี่ยนแปลงในเซสชันนี้", + "session.review.noChanges": "ไม่มีการเปลี่ยนแปลง", + + "session.files.selectToOpen": "เลือกไฟล์เพื่อเปิด", + "session.files.all": "ไฟล์ทั้งหมด", + + "session.messages.renderEarlier": "แสดงข้อความก่อนหน้า", + "session.messages.loadingEarlier": "กำลังโหลดข้อความก่อนหน้า...", + "session.messages.loadEarlier": "โหลดข้อความก่อนหน้า", + "session.messages.loading": "กำลังโหลดข้อความ...", + "session.messages.jumpToLatest": "ไปที่ล่าสุด", + + "session.context.addToContext": "เพิ่ม {{selection}} ไปยังบริบท", + + "session.new.worktree.main": "สาขาหลัก", + "session.new.worktree.mainWithBranch": "สาขาหลัก ({{branch}})", + "session.new.worktree.create": "สร้าง worktree ใหม่", + "session.new.lastModified": "แก้ไขล่าสุด", + + "session.header.search.placeholder": "ค้นหา {{project}}", + "session.header.searchFiles": "ค้นหาไฟล์", + + "status.popover.trigger": "สถานะ", + "status.popover.ariaLabel": "การกำหนดค่าเซิร์ฟเวอร์", + "status.popover.tab.servers": "เซิร์ฟเวอร์", + "status.popover.tab.mcp": "MCP", + "status.popover.tab.lsp": "LSP", + "status.popover.tab.plugins": "ปลั๊กอิน", + "status.popover.action.manageServers": "จัดการเซิร์ฟเวอร์", + + "session.share.popover.title": "เผยแพร่บนเว็บ", + "session.share.popover.description.shared": "เซสชันนี้เป็นสาธารณะบนเว็บ สามารถเข้าถึงได้โดยผู้ที่มีลิงก์", + "session.share.popover.description.unshared": "แชร์เซสชันสาธารณะบนเว็บ จะเข้าถึงได้โดยผู้ที่มีลิงก์", + "session.share.action.share": "แชร์", + "session.share.action.publish": "เผยแพร่", + "session.share.action.publishing": "กำลังเผยแพร่...", + "session.share.action.unpublish": "ยกเลิกการเผยแพร่", + "session.share.action.unpublishing": "กำลังยกเลิกการเผยแพร่...", + "session.share.action.view": "ดู", + "session.share.copy.copied": "คัดลอกแล้ว", + "session.share.copy.copyLink": "คัดลอกลิงก์", + + "lsp.tooltip.none": "ไม่มีเซิร์ฟเวอร์ LSP", + "lsp.label.connected": "{{count}} LSP", + + "prompt.loading": "กำลังโหลดพร้อมท์...", + "terminal.loading": "กำลังโหลดเทอร์มินัล...", + "terminal.title": "เทอร์มินัล", + "terminal.title.numbered": "เทอร์มินัล {{number}}", + "terminal.close": "ปิดเทอร์มินัล", + "terminal.connectionLost.title": "การเชื่อมต่อขาดหาย", + "terminal.connectionLost.description": "การเชื่อมต่อเทอร์มินัลถูกขัดจังหวะ อาจเกิดขึ้นเมื่อเซิร์ฟเวอร์รีสตาร์ท", + + "common.closeTab": "ปิดแท็บ", + "common.dismiss": "ปิด", + "common.requestFailed": "คำขอล้มเหลว", + "common.moreOptions": "ตัวเลือกเพิ่มเติม", + "common.learnMore": "เรียนรู้เพิ่มเติม", + "common.rename": "เปลี่ยนชื่อ", + "common.reset": "รีเซ็ต", + "common.archive": "จัดเก็บ", + "common.delete": "ลบ", + "common.close": "ปิด", + "common.edit": "แก้ไข", + "common.loadMore": "โหลดเพิ่มเติม", + "common.key.esc": "ESC", + + "sidebar.menu.toggle": "สลับเมนู", + "sidebar.nav.projectsAndSessions": "โปรเจกต์และเซสชัน", + "sidebar.settings": "การตั้งค่า", + "sidebar.help": "ช่วยเหลือ", + "sidebar.workspaces.enable": "เปิดใช้งานพื้นที่ทำงาน", + "sidebar.workspaces.disable": "ปิดใช้งานพื้นที่ทำงาน", + "sidebar.gettingStarted.title": "เริ่มต้นใช้งาน", + "sidebar.gettingStarted.line1": "OpenCode รวมถึงโมเดลฟรีเพื่อให้คุณเริ่มต้นได้ทันที", + "sidebar.gettingStarted.line2": "เชื่อมต่อผู้ให้บริการใด ๆ เพื่อใช้โมเดล รวมถึง Claude, GPT, Gemini ฯลฯ", + "sidebar.project.recentSessions": "เซสชันล่าสุด", + "sidebar.project.viewAllSessions": "ดูเซสชันทั้งหมด", + + "app.name.desktop": "OpenCode Desktop", + + "settings.section.desktop": "เดสก์ท็อป", + "settings.section.server": "เซิร์ฟเวอร์", + "settings.tab.general": "ทั่วไป", + "settings.tab.shortcuts": "ทางลัด", + + "settings.general.section.appearance": "รูปลักษณ์", + "settings.general.section.notifications": "การแจ้งเตือนระบบ", + "settings.general.section.updates": "การอัปเดต", + "settings.general.section.sounds": "เสียงเอฟเฟกต์", + + "settings.general.row.language.title": "ภาษา", + "settings.general.row.language.description": "เปลี่ยนภาษาที่แสดงสำหรับ OpenCode", + "settings.general.row.appearance.title": "รูปลักษณ์", + "settings.general.row.appearance.description": "ปรับแต่งวิธีการที่ OpenCode มีลักษณะบนอุปกรณ์ของคุณ", + "settings.general.row.theme.title": "ธีม", + "settings.general.row.theme.description": "ปรับแต่งวิธีการที่ OpenCode มีธีม", + "settings.general.row.font.title": "ฟอนต์", + "settings.general.row.font.description": "ปรับแต่งฟอนต์โมโนที่ใช้ในบล็อกโค้ด", + + "settings.general.row.releaseNotes.title": "บันทึกการอัปเดต", + "settings.general.row.releaseNotes.description": "แสดงป๊อปอัพ What's New หลังจากอัปเดต", + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "เสียงเตือน 01", + "sound.option.alert02": "เสียงเตือน 02", + "sound.option.alert03": "เสียงเตือน 03", + "sound.option.alert04": "เสียงเตือน 04", + "sound.option.alert05": "เสียงเตือน 05", + "sound.option.alert06": "เสียงเตือน 06", + "sound.option.alert07": "เสียงเตือน 07", + "sound.option.alert08": "เสียงเตือน 08", + "sound.option.alert09": "เสียงเตือน 09", + "sound.option.alert10": "เสียงเตือน 10", + "sound.option.bipbop01": "Bip-bop 01", + "sound.option.bipbop02": "Bip-bop 02", + "sound.option.bipbop03": "Bip-bop 03", + "sound.option.bipbop04": "Bip-bop 04", + "sound.option.bipbop05": "Bip-bop 05", + "sound.option.bipbop06": "Bip-bop 06", + "sound.option.bipbop07": "Bip-bop 07", + "sound.option.bipbop08": "Bip-bop 08", + "sound.option.bipbop09": "Bip-bop 09", + "sound.option.bipbop10": "Bip-bop 10", + "sound.option.staplebops01": "Staplebops 01", + "sound.option.staplebops02": "Staplebops 02", + "sound.option.staplebops03": "Staplebops 03", + "sound.option.staplebops04": "Staplebops 04", + "sound.option.staplebops05": "Staplebops 05", + "sound.option.staplebops06": "Staplebops 06", + "sound.option.staplebops07": "Staplebops 07", + "sound.option.nope01": "Nope 01", + "sound.option.nope02": "Nope 02", + "sound.option.nope03": "Nope 03", + "sound.option.nope04": "Nope 04", + "sound.option.nope05": "Nope 05", + "sound.option.nope06": "Nope 06", + "sound.option.nope07": "Nope 07", + "sound.option.nope08": "Nope 08", + "sound.option.nope09": "Nope 09", + "sound.option.nope10": "Nope 10", + "sound.option.nope11": "Nope 11", + "sound.option.nope12": "Nope 12", + "sound.option.yup01": "Yup 01", + "sound.option.yup02": "Yup 02", + "sound.option.yup03": "Yup 03", + "sound.option.yup04": "Yup 04", + "sound.option.yup05": "Yup 05", + "sound.option.yup06": "Yup 06", + + "settings.general.notifications.agent.title": "เอเจนต์", + "settings.general.notifications.agent.description": "แสดงการแจ้งเตือนระบบเมื่อเอเจนต์เสร็จสิ้นหรือต้องการความสนใจ", + "settings.general.notifications.permissions.title": "สิทธิ์", + "settings.general.notifications.permissions.description": "แสดงการแจ้งเตือนระบบเมื่อต้องการสิทธิ์", + "settings.general.notifications.errors.title": "ข้อผิดพลาด", + "settings.general.notifications.errors.description": "แสดงการแจ้งเตือนระบบเมื่อเกิดข้อผิดพลาด", + + "settings.general.sounds.agent.title": "เอเจนต์", + "settings.general.sounds.agent.description": "เล่นเสียงเมื่อเอเจนต์เสร็จสิ้นหรือต้องการความสนใจ", + "settings.general.sounds.permissions.title": "สิทธิ์", + "settings.general.sounds.permissions.description": "เล่นเสียงเมื่อต้องการสิทธิ์", + "settings.general.sounds.errors.title": "ข้อผิดพลาด", + "settings.general.sounds.errors.description": "เล่นเสียงเมื่อเกิดข้อผิดพลาด", + + "settings.shortcuts.title": "ทางลัดแป้นพิมพ์", + "settings.shortcuts.reset.button": "รีเซ็ตเป็นค่าเริ่มต้น", + "settings.shortcuts.reset.toast.title": "รีเซ็ตทางลัดแล้ว", + "settings.shortcuts.reset.toast.description": "รีเซ็ตทางลัดแป้นพิมพ์เป็นค่าเริ่มต้นแล้ว", + "settings.shortcuts.conflict.title": "ทางลัดใช้งานอยู่แล้ว", + "settings.shortcuts.conflict.description": "{{keybind}} ถูกกำหนดให้กับ {{titles}} แล้ว", + "settings.shortcuts.unassigned": "ไม่ได้กำหนด", + "settings.shortcuts.pressKeys": "กดปุ่ม", + "settings.shortcuts.search.placeholder": "ค้นหาทางลัด", + "settings.shortcuts.search.empty": "ไม่พบทางลัด", + + "settings.shortcuts.group.general": "ทั่วไป", + "settings.shortcuts.group.session": "เซสชัน", + "settings.shortcuts.group.navigation": "การนำทาง", + "settings.shortcuts.group.modelAndAgent": "โมเดลและเอเจนต์", + "settings.shortcuts.group.terminal": "เทอร์มินัล", + "settings.shortcuts.group.prompt": "พร้อมท์", + + "settings.providers.title": "ผู้ให้บริการ", + "settings.providers.description": "การตั้งค่าผู้ให้บริการจะสามารถกำหนดค่าได้ที่นี่", + "settings.providers.section.connected": "ผู้ให้บริการที่เชื่อมต่อ", + "settings.providers.connected.empty": "ไม่มีผู้ให้บริการที่เชื่อมต่อ", + "settings.providers.section.popular": "ผู้ให้บริการยอดนิยม", + "settings.providers.tag.environment": "สภาพแวดล้อม", + "settings.providers.tag.config": "กำหนดค่า", + "settings.providers.tag.custom": "กำหนดเอง", + "settings.providers.tag.other": "อื่น ๆ", + "settings.models.title": "โมเดล", + "settings.models.description": "การตั้งค่าโมเดลจะสามารถกำหนดค่าได้ที่นี่", + "settings.agents.title": "เอเจนต์", + "settings.agents.description": "การตั้งค่าเอเจนต์จะสามารถกำหนดค่าได้ที่นี่", + "settings.commands.title": "คำสั่ง", + "settings.commands.description": "การตั้งค่าคำสั่งจะสามารถกำหนดค่าได้ที่นี่", + "settings.mcp.title": "MCP", + "settings.mcp.description": "การตั้งค่า MCP จะสามารถกำหนดค่าได้ที่นี่", + + "settings.permissions.title": "สิทธิ์", + "settings.permissions.description": "ควบคุมเครื่องมือที่เซิร์ฟเวอร์สามารถใช้โดยค่าเริ่มต้น", + "settings.permissions.section.tools": "เครื่องมือ", + "settings.permissions.toast.updateFailed.title": "ไม่สามารถอัปเดตสิทธิ์", + + "settings.permissions.action.allow": "อนุญาต", + "settings.permissions.action.ask": "ถาม", + "settings.permissions.action.deny": "ปฏิเสธ", + + "settings.permissions.tool.read.title": "อ่าน", + "settings.permissions.tool.read.description": "อ่านไฟล์ (ตรงกับเส้นทางไฟล์)", + "settings.permissions.tool.edit.title": "แก้ไข", + "settings.permissions.tool.edit.description": "แก้ไขไฟล์ รวมถึงการแก้ไข เขียน แพตช์ และแก้ไขหลายรายการ", + "settings.permissions.tool.glob.title": "Glob", + "settings.permissions.tool.glob.description": "จับคู่ไฟล์โดยใช้รูปแบบ glob", + "settings.permissions.tool.grep.title": "Grep", + "settings.permissions.tool.grep.description": "ค้นหาเนื้อหาไฟล์โดยใช้นิพจน์ทั่วไป", + "settings.permissions.tool.list.title": "รายการ", + "settings.permissions.tool.list.description": "แสดงรายการไฟล์ภายในไดเรกทอรี", + "settings.permissions.tool.bash.title": "Bash", + "settings.permissions.tool.bash.description": "เรียกใช้คำสั่งเชลล์", + "settings.permissions.tool.task.title": "งาน", + "settings.permissions.tool.task.description": "เปิดเอเจนต์ย่อย", + "settings.permissions.tool.skill.title": "ทักษะ", + "settings.permissions.tool.skill.description": "โหลดทักษะตามชื่อ", + "settings.permissions.tool.lsp.title": "LSP", + "settings.permissions.tool.lsp.description": "เรียกใช้การสืบค้นเซิร์ฟเวอร์ภาษา", + "settings.permissions.tool.todoread.title": "อ่านรายการงาน", + "settings.permissions.tool.todoread.description": "อ่านรายการงาน", + "settings.permissions.tool.todowrite.title": "เขียนรายการงาน", + "settings.permissions.tool.todowrite.description": "อัปเดตรายการงาน", + "settings.permissions.tool.webfetch.title": "ดึงข้อมูลจากเว็บ", + "settings.permissions.tool.webfetch.description": "ดึงเนื้อหาจาก URL", + "settings.permissions.tool.websearch.title": "ค้นหาเว็บ", + "settings.permissions.tool.websearch.description": "ค้นหาบนเว็บ", + "settings.permissions.tool.codesearch.title": "ค้นหาโค้ด", + "settings.permissions.tool.codesearch.description": "ค้นหาโค้ดบนเว็บ", + "settings.permissions.tool.external_directory.title": "ไดเรกทอรีภายนอก", + "settings.permissions.tool.external_directory.description": "เข้าถึงไฟล์นอกไดเรกทอรีโปรเจกต์", + "settings.permissions.tool.doom_loop.title": "Doom Loop", + "settings.permissions.tool.doom_loop.description": "ตรวจจับการเรียกเครื่องมือซ้ำด้วยข้อมูลนำเข้าเหมือนกัน", + + "session.delete.failed.title": "ไม่สามารถลบเซสชัน", + "session.delete.title": "ลบเซสชัน", + "session.delete.confirm": 'ลบเซสชัน "{{name}}" หรือไม่?', + "session.delete.button": "ลบเซสชัน", + + "workspace.new": "พื้นที่ทำงานใหม่", + "workspace.type.local": "ในเครื่อง", + "workspace.type.sandbox": "แซนด์บ็อกซ์", + "workspace.create.failed.title": "ไม่สามารถสร้างพื้นที่ทำงาน", + "workspace.delete.failed.title": "ไม่สามารถลบพื้นที่ทำงาน", + "workspace.resetting.title": "กำลังรีเซ็ตพื้นที่ทำงาน", + "workspace.resetting.description": "อาจใช้เวลาประมาณหนึ่งนาที", + "workspace.reset.failed.title": "ไม่สามารถรีเซ็ตพื้นที่ทำงาน", + "workspace.reset.success.title": "รีเซ็ตพื้นที่ทำงานแล้ว", + "workspace.reset.success.description": "พื้นที่ทำงานตรงกับสาขาเริ่มต้นแล้ว", + "workspace.error.stillPreparing": "พื้นที่ทำงานกำลังเตรียมอยู่", + "workspace.status.checking": "กำลังตรวจสอบการเปลี่ยนแปลงที่ไม่ได้ผสาน...", + "workspace.status.error": "ไม่สามารถตรวจสอบสถานะ git", + "workspace.status.clean": "ไม่ตรวจพบการเปลี่ยนแปลงที่ไม่ได้ผสาน", + "workspace.status.dirty": "ตรวจพบการเปลี่ยนแปลงที่ไม่ได้ผสานในพื้นที่ทำงานนี้", + "workspace.delete.title": "ลบพื้นที่ทำงาน", + "workspace.delete.confirm": 'ลบพื้นที่ทำงาน "{{name}}" หรือไม่?', + "workspace.delete.button": "ลบพื้นที่ทำงาน", + "workspace.reset.title": "รีเซ็ตพื้นที่ทำงาน", + "workspace.reset.confirm": 'รีเซ็ตพื้นที่ทำงาน "{{name}}" หรือไม่?', + "workspace.reset.button": "รีเซ็ตพื้นที่ทำงาน", + "workspace.reset.archived.none": "ไม่มีเซสชันที่ใช้งานอยู่จะถูกจัดเก็บ", + "workspace.reset.archived.one": "1 เซสชันจะถูกจัดเก็บ", + "workspace.reset.archived.many": "{{count}} เซสชันจะถูกจัดเก็บ", + "workspace.reset.note": "สิ่งนี้จะรีเซ็ตพื้นที่ทำงานให้ตรงกับสาขาเริ่มต้น", +} diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 3208edcf45..17eef0f5ec 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -12,6 +12,7 @@ export const dict = { "command.category.theme": "主题", "command.category.language": "语言", "command.category.file": "文件", + "command.category.context": "上下文", "command.category.terminal": "终端", "command.category.model": "模型", "command.category.mcp": "MCP", @@ -19,6 +20,7 @@ export const dict = { "command.category.permissions": "权限", "command.category.workspace": "工作区", + "command.category.settings": "设置", "theme.scheme.system": "系统", "theme.scheme.light": "浅色", "theme.scheme.dark": "深色", @@ -27,6 +29,7 @@ export const dict = { "command.project.open": "打开项目", "command.provider.connect": "连接提供商", "command.server.switch": "切换服务器", + "command.settings.open": "打开设置", "command.session.previous": "上一个会话", "command.session.next": "下一个会话", "command.session.archive": "归档会话", @@ -34,17 +37,20 @@ export const dict = { "command.palette": "命令面板", "command.theme.cycle": "切换主题", - "command.theme.set": "使用主题: {{theme}}", + "command.theme.set": "使用主题:{{theme}}", "command.theme.scheme.cycle": "切换配色方案", - "command.theme.scheme.set": "使用配色方案: {{scheme}}", + "command.theme.scheme.set": "使用配色方案:{{scheme}}", "command.language.cycle": "切换语言", - "command.language.set": "使用语言: {{language}}", + "command.language.set": "使用语言:{{language}}", "command.session.new": "新建会话", "command.file.open": "打开文件", "command.file.open.description": "搜索文件和命令", + "command.context.addSelection": "将所选内容添加到上下文", + "command.context.addSelection.description": "添加当前文件中选中的行", "command.terminal.toggle": "切换终端", + "command.fileTree.toggle": "切换文件树", "command.review.toggle": "切换审查", "command.terminal.new": "新建终端", "command.terminal.new.description": "创建新的终端标签页", @@ -94,6 +100,10 @@ export const dict = { "dialog.provider.anthropic.note": "使用 Claude Pro/Max 或 API 密钥连接", "dialog.provider.openai.note": "使用 ChatGPT Pro/Plus 或 API 密钥连接", "dialog.provider.copilot.note": "使用 Copilot 或 API 密钥连接", + "dialog.provider.opencode.note": "使用 OpenCode Zen 或 API 密钥连接", + "dialog.provider.google.note": "使用 Google 账号或 API 密钥连接", + "dialog.provider.openrouter.note": "使用 OpenRouter 账号或 API 密钥连接", + "dialog.provider.vercel.note": "使用 Vercel 账号或 API 密钥连接", "dialog.model.select.title": "选择模型", "dialog.model.search.placeholder": "搜索模型", @@ -104,7 +114,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Kilo CLI 提供的免费模型", "dialog.model.unpaid.addMore.title": "从热门提供商添加更多模型", - "dialog.provider.viewAll": "查看全部提供商", + "dialog.provider.viewAll": "查看更多提供商", "provider.connect.title": "连接 {{provider}}", "provider.connect.title.anthropicProMax": "使用 Claude Pro/Max 登录", @@ -112,7 +122,7 @@ export const dict = { "provider.connect.method.apiKey": "API 密钥", "provider.connect.status.inProgress": "正在授权...", "provider.connect.status.waiting": "等待授权...", - "provider.connect.status.failed": "授权失败: {{error}}", + "provider.connect.status.failed": "授权失败:{{error}}", "provider.connect.apiKey.description": "输入你的 {{provider}} API 密钥以连接帐户,并在 Kilo CLI 中使用 {{provider}} 模型。", "provider.connect.apiKey.label": "{{provider}} API 密钥", @@ -137,13 +147,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} 已连接", "provider.connect.toast.connected.description": "现在可以使用 {{provider}} 模型了。", + "provider.disconnect.toast.disconnected.title": "{{provider}} 已断开连接", + "provider.disconnect.toast.disconnected.description": "{{provider}} 模型已不再可用。", "model.tag.free": "免费", "model.tag.latest": "最新", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "文本", + "model.input.image": "图像", + "model.input.audio": "音频", + "model.input.video": "视频", + "model.input.pdf": "pdf", + "model.tooltip.allows": "支持:{{inputs}}", + "model.tooltip.reasoning.allowed": "支持推理", + "model.tooltip.reasoning.none": "不支持推理", + "model.tooltip.context": "上下文上限 {{limit}}", "common.search.placeholder": "搜索", "common.goBack": "返回", "common.loading": "加载中", + "common.loading.ellipsis": "...", "common.cancel": "取消", + "common.connect": "连接", + "common.disconnect": "断开连接", "common.submit": "提交", "common.save": "保存", "common.saving": "保存中...", @@ -152,34 +181,36 @@ export const dict = { "prompt.placeholder.shell": "输入 shell 命令...", "prompt.placeholder.normal": '随便问点什么... "{{example}}"', + "prompt.placeholder.summarizeComments": "总结评论…", + "prompt.placeholder.summarizeComment": "总结该评论…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "按 esc 退出", "prompt.example.1": "修复代码库中的一个 TODO", - "prompt.example.2": "这个项目的技术栈是什么?", + "prompt.example.2": "这个项目的技术栈是什么?", "prompt.example.3": "修复失败的测试", "prompt.example.4": "解释认证是如何工作的", "prompt.example.5": "查找并修复安全漏洞", "prompt.example.6": "为用户服务添加单元测试", "prompt.example.7": "重构这个函数,让它更易读", - "prompt.example.8": "这个错误是什么意思?", + "prompt.example.8": "这个错误是什么意思?", "prompt.example.9": "帮我调试这个问题", "prompt.example.10": "生成 API 文档", "prompt.example.11": "优化数据库查询", "prompt.example.12": "添加输入校验", "prompt.example.13": "创建一个新的组件用于...", - "prompt.example.14": "我该如何部署这个项目?", + "prompt.example.14": "我该如何部署这个项目?", "prompt.example.15": "审查我的代码并给出最佳实践建议", "prompt.example.16": "为这个函数添加错误处理", "prompt.example.17": "解释这个正则表达式", "prompt.example.18": "把它转换成 TypeScript", "prompt.example.19": "在整个代码库中添加日志", - "prompt.example.20": "哪些依赖已经过期?", + "prompt.example.20": "哪些依赖已经过期?", "prompt.example.21": "帮我写一个迁移脚本", "prompt.example.22": "为这个接口实现缓存", "prompt.example.23": "给这个列表添加分页", "prompt.example.24": "创建一个 CLI 命令用于...", - "prompt.example.25": "这里的环境变量是怎么工作的?", + "prompt.example.25": "这里的环境变量是怎么工作的?", "prompt.popover.emptyResults": "没有匹配的结果", "prompt.popover.emptyCommands": "没有匹配的命令", @@ -254,6 +285,9 @@ export const dict = { "dialog.project.edit.color": "颜色", "dialog.project.edit.color.select": "选择{{color}}颜色", + "dialog.project.edit.worktree.startup": "工作区启动脚本", + "dialog.project.edit.worktree.startup.description": "在创建新的工作区 (worktree) 后运行。", + "dialog.project.edit.worktree.startup.placeholder": "例如 bun install", "context.breakdown.title": "上下文拆分", "context.breakdown.note": "输入 token 的大致拆分。“其他”包含工具定义和开销。", "context.breakdown.system": "系统", @@ -302,6 +336,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "语言", "toast.language.description": "已切换到{{language}}", @@ -319,6 +354,9 @@ export const dict = { "toast.file.loadFailed.title": "加载文件失败", + "toast.file.listFailed.title": "列出文件失败", + "toast.context.noLineSelection.title": "未选择行", + "toast.context.noLineSelection.description": "请先在文件标签中选择行范围。", "toast.session.share.copyFailed.title": "无法复制链接到剪贴板", "toast.session.share.success.title": "会话已分享", "toast.session.share.success.description": "分享链接已复制到剪贴板", @@ -346,31 +384,31 @@ export const dict = { "error.page.action.updateTo": "更新到 {{version}}", "error.page.report.prefix": "请将此错误报告给 Kilo CLI 团队", "error.page.report.discord": "在 Discord 上", - "error.page.version": "版本: {{version}}", + "error.page.version": "版本:{{version}}", - "error.dev.rootNotFound": "未找到根元素。你是不是忘了把它添加到 index.html? 或者 id 属性拼写错了?", + "error.dev.rootNotFound": "未找到根元素。你是不是忘了把它添加到 index.html?或者 id 属性拼写错了?", - "error.globalSync.connectFailed": "无法连接到服务器。是否有服务器正在 `{{url}}` 运行?", + "error.globalSync.connectFailed": "无法连接到服务器。是否有服务器正在 `{{url}}` 运行?", "error.chain.unknown": "未知错误", - "error.chain.causedBy": "原因:", + "error.chain.causedBy": "原因:", "error.chain.apiError": "API 错误", - "error.chain.status": "状态: {{status}}", - "error.chain.retryable": "可重试: {{retryable}}", - "error.chain.responseBody": "响应内容:\n{{body}}", - "error.chain.didYouMean": "你是不是想输入: {{suggestions}}", - "error.chain.modelNotFound": "未找到模型: {{provider}}/{{model}}", + "error.chain.status": "状态:{{status}}", + "error.chain.retryable": "可重试:{{retryable}}", + "error.chain.responseBody": "响应内容:\n{{body}}", + "error.chain.didYouMean": "你是不是想输入:{{suggestions}}", + "error.chain.modelNotFound": "未找到模型:{{provider}}/{{model}}", "error.chain.checkConfig": "请检查你的配置 (opencode.json) 中的 provider/model 名称", "error.chain.mcpFailed": 'MCP 服务器 "{{name}}" 启动失败。注意: Kilo CLI 暂不支持 MCP 认证。', "error.chain.providerAuthFailed": "提供商认证失败 ({{provider}}): {{message}}", "error.chain.providerInitFailed": '无法初始化提供商 "{{provider}}"。请检查凭据和配置。', "error.chain.configJsonInvalid": "配置文件 {{path}} 不是有效的 JSON(C)", - "error.chain.configJsonInvalidWithMessage": "配置文件 {{path}} 不是有效的 JSON(C): {{message}}", + "error.chain.configJsonInvalidWithMessage": "配置文件 {{path}} 不是有效的 JSON(C):{{message}}", "error.chain.configDirectoryTypo": '{{path}} 中的目录 "{{dir}}" 无效。请将目录重命名为 "{{suggestion}}" 或移除它。这是一个常见拼写错误。', - "error.chain.configFrontmatterError": "无法解析 {{path}} 中的 frontmatter:\n{{message}}", + "error.chain.configFrontmatterError": "无法解析 {{path}} 中的 frontmatter:\n{{message}}", "error.chain.configInvalid": "配置文件 {{path}} 无效", - "error.chain.configInvalidWithMessage": "配置文件 {{path}} 无效: {{message}}", + "error.chain.configInvalidWithMessage": "配置文件 {{path}} 无效:{{message}}", "notification.permission.title": "需要权限", "notification.permission.description": "{{sessionTitle}}({{projectName}})需要权限", @@ -391,17 +429,23 @@ export const dict = { "session.tab.context": "上下文", "session.panel.reviewAndFiles": "审查和文件", "session.review.filesChanged": "{{count}} 个文件变更", + "session.review.change.one": "更改", + "session.review.change.other": "更改", "session.review.loadingChanges": "正在加载更改...", "session.review.empty": "此会话暂无更改", + "session.review.noChanges": "无更改", + "session.files.selectToOpen": "选择要打开的文件", + "session.files.all": "所有文件", "session.messages.renderEarlier": "显示更早的消息", "session.messages.loadingEarlier": "正在加载更早的消息...", "session.messages.loadEarlier": "加载更早的消息", "session.messages.loading": "正在加载消息...", + "session.messages.jumpToLatest": "跳转到最新", "session.context.addToContext": "将 {{selection}} 添加到上下文", "session.new.worktree.main": "主分支", - "session.new.worktree.mainWithBranch": "主分支 ({{branch}})", + "session.new.worktree.mainWithBranch": "主分支({{branch}})", "session.new.worktree.create": "创建新的 worktree", "session.new.lastModified": "最后修改", @@ -437,6 +481,8 @@ export const dict = { "terminal.title.numbered": "终端 {{number}}", "terminal.close": "关闭终端", + "terminal.connectionLost.title": "连接已丢失", + "terminal.connectionLost.description": "终端连接已中断。这可能发生在服务器重启时。", "common.closeTab": "关闭标签页", "common.dismiss": "忽略", "common.requestFailed": "请求失败", @@ -450,6 +496,8 @@ export const dict = { "common.edit": "编辑", "common.loadMore": "加载更多", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "切换菜单", "sidebar.nav.projectsAndSessions": "项目和会话", "sidebar.settings": "设置", "sidebar.help": "帮助", @@ -461,12 +509,15 @@ export const dict = { "sidebar.project.recentSessions": "最近会话", "sidebar.project.viewAllSessions": "查看全部会话", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "桌面", + "settings.section.server": "服务器", "settings.tab.general": "通用", "settings.tab.shortcuts": "快捷键", "settings.general.section.appearance": "外观", "settings.general.section.notifications": "系统通知", + "settings.general.section.updates": "更新", "settings.general.section.sounds": "音效", "settings.general.row.language.title": "语言", @@ -477,7 +528,75 @@ export const dict = { "settings.general.row.theme.description": "自定义 Kilo CLI 的主题。", "settings.general.row.font.title": "字体", "settings.general.row.font.description": "自定义代码块使用的等宽字体", + "settings.general.row.releaseNotes.title": "发行说明", + "settings.general.row.releaseNotes.description": "更新后显示“新功能”弹窗", + "settings.updates.row.startup.title": "启动时检查更新", + "settings.updates.row.startup.description": "在 OpenCode 启动时自动检查更新", + "settings.updates.row.check.title": "检查更新", + "settings.updates.row.check.description": "手动检查更新并在有更新时安装", + "settings.updates.action.checkNow": "立即检查", + "settings.updates.action.checking": "正在检查...", + "settings.updates.toast.latest.title": "已是最新版本", + "settings.updates.toast.latest.description": "你正在使用最新版本的 OpenCode。", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "警报 01", + "sound.option.alert02": "警报 02", + "sound.option.alert03": "警报 03", + "sound.option.alert04": "警报 04", + "sound.option.alert05": "警报 05", + "sound.option.alert06": "警报 06", + "sound.option.alert07": "警报 07", + "sound.option.alert08": "警报 08", + "sound.option.alert09": "警报 09", + "sound.option.alert10": "警报 10", + "sound.option.bipbop01": "哔啵 01", + "sound.option.bipbop02": "哔啵 02", + "sound.option.bipbop03": "哔啵 03", + "sound.option.bipbop04": "哔啵 04", + "sound.option.bipbop05": "哔啵 05", + "sound.option.bipbop06": "哔啵 06", + "sound.option.bipbop07": "哔啵 07", + "sound.option.bipbop08": "哔啵 08", + "sound.option.bipbop09": "哔啵 09", + "sound.option.bipbop10": "哔啵 10", + "sound.option.staplebops01": "斯泰普博普斯 01", + "sound.option.staplebops02": "斯泰普博普斯 02", + "sound.option.staplebops03": "斯泰普博普斯 03", + "sound.option.staplebops04": "斯泰普博普斯 04", + "sound.option.staplebops05": "斯泰普博普斯 05", + "sound.option.staplebops06": "斯泰普博普斯 06", + "sound.option.staplebops07": "斯泰普博普斯 07", + "sound.option.nope01": "否 01", + "sound.option.nope02": "否 02", + "sound.option.nope03": "否 03", + "sound.option.nope04": "否 04", + "sound.option.nope05": "否 05", + "sound.option.nope06": "否 06", + "sound.option.nope07": "否 07", + "sound.option.nope08": "否 08", + "sound.option.nope09": "否 09", + "sound.option.nope10": "否 10", + "sound.option.nope11": "否 11", + "sound.option.nope12": "否 12", + "sound.option.yup01": "是 01", + "sound.option.yup02": "是 02", + "sound.option.yup03": "是 03", + "sound.option.yup04": "是 04", + "sound.option.yup05": "是 05", + "sound.option.yup06": "是 06", "settings.general.notifications.agent.title": "智能体", "settings.general.notifications.agent.description": "当智能体完成或需要注意时显示系统通知", "settings.general.notifications.permissions.title": "权限", @@ -512,6 +631,13 @@ export const dict = { "settings.providers.title": "提供商", "settings.providers.description": "提供商设置将在此处可配置。", + "settings.providers.section.connected": "已连接的提供商", + "settings.providers.connected.empty": "没有已连接的提供商", + "settings.providers.section.popular": "热门提供商", + "settings.providers.tag.environment": "环境", + "settings.providers.tag.config": "配置", + "settings.providers.tag.custom": "自定义", + "settings.providers.tag.other": "其他", "settings.models.title": "模型", "settings.models.description": "模型设置将在此处可配置。", "settings.agents.title": "智能体", @@ -565,7 +691,7 @@ export const dict = { "session.delete.failed.title": "删除会话失败", "session.delete.title": "删除会话", - "session.delete.confirm": '删除会话 "{{name}}"?', + "session.delete.confirm": '删除会话 "{{name}}"?', "session.delete.button": "删除会话", "workspace.new": "新建工作区", @@ -578,15 +704,16 @@ export const dict = { "workspace.reset.failed.title": "重置工作区失败", "workspace.reset.success.title": "工作区已重置", "workspace.reset.success.description": "工作区已与默认分支保持一致。", + "workspace.error.stillPreparing": "工作区仍在准备中", "workspace.status.checking": "正在检查未合并的更改...", "workspace.status.error": "无法验证 git 状态。", "workspace.status.clean": "未检测到未合并的更改。", "workspace.status.dirty": "检测到未合并的更改。", "workspace.delete.title": "删除工作区", - "workspace.delete.confirm": '删除工作区 "{{name}}"?', + "workspace.delete.confirm": '删除工作区 "{{name}}"?', "workspace.delete.button": "删除工作区", "workspace.reset.title": "重置工作区", - "workspace.reset.confirm": '重置工作区 "{{name}}"?', + "workspace.reset.confirm": '重置工作区 "{{name}}"?', "workspace.reset.button": "重置工作区", "workspace.reset.archived.none": "不会归档任何活跃会话。", "workspace.reset.archived.one": "将归档 1 个会话。", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index bd6bac4979..914556665f 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -12,6 +12,7 @@ export const dict = { "command.category.theme": "主題", "command.category.language": "語言", "command.category.file": "檔案", + "command.category.context": "上下文", "command.category.terminal": "終端機", "command.category.model": "模型", "command.category.mcp": "MCP", @@ -19,6 +20,7 @@ export const dict = { "command.category.permissions": "權限", "command.category.workspace": "工作區", + "command.category.settings": "設定", "theme.scheme.system": "系統", "theme.scheme.light": "淺色", "theme.scheme.dark": "深色", @@ -27,6 +29,7 @@ export const dict = { "command.project.open": "開啟專案", "command.provider.connect": "連接提供者", "command.server.switch": "切換伺服器", + "command.settings.open": "開啟設定", "command.session.previous": "上一個工作階段", "command.session.next": "下一個工作階段", "command.session.archive": "封存工作階段", @@ -44,7 +47,10 @@ export const dict = { "command.session.new": "新增工作階段", "command.file.open": "開啟檔案", "command.file.open.description": "搜尋檔案和命令", + "command.context.addSelection": "將選取內容加入上下文", + "command.context.addSelection.description": "加入目前檔案中選取的行", "command.terminal.toggle": "切換終端機", + "command.fileTree.toggle": "切換檔案樹", "command.review.toggle": "切換審查", "command.terminal.new": "新增終端機", "command.terminal.new.description": "建立新的終端機標籤頁", @@ -104,7 +110,7 @@ export const dict = { "dialog.model.unpaid.freeModels.title": "Kilo CLI 提供的免費模型", "dialog.model.unpaid.addMore.title": "從熱門提供者新增更多模型", - "dialog.provider.viewAll": "查看全部提供者", + "dialog.provider.viewAll": "查看更多提供者", "provider.connect.title": "連線 {{provider}}", "provider.connect.title.anthropicProMax": "使用 Claude Pro/Max 登入", @@ -138,13 +144,32 @@ export const dict = { "provider.connect.toast.connected.title": "{{provider}} 已連線", "provider.connect.toast.connected.description": "現在可以使用 {{provider}} 模型了。", + "provider.disconnect.toast.disconnected.title": "{{provider}} 已中斷連線", + "provider.disconnect.toast.disconnected.description": "{{provider}} 模型已不再可用。", "model.tag.free": "免費", "model.tag.latest": "最新", + "model.provider.anthropic": "Anthropic", + "model.provider.openai": "OpenAI", + "model.provider.google": "Google", + "model.provider.xai": "xAI", + "model.provider.meta": "Meta", + "model.input.text": "文字", + "model.input.image": "圖片", + "model.input.audio": "音訊", + "model.input.video": "影片", + "model.input.pdf": "pdf", + "model.tooltip.allows": "支援: {{inputs}}", + "model.tooltip.reasoning.allowed": "支援推理", + "model.tooltip.reasoning.none": "不支援推理", + "model.tooltip.context": "上下文上限 {{limit}}", "common.search.placeholder": "搜尋", "common.goBack": "返回", "common.loading": "載入中", + "common.loading.ellipsis": "...", "common.cancel": "取消", + "common.connect": "連線", + "common.disconnect": "中斷連線", "common.submit": "提交", "common.save": "儲存", "common.saving": "儲存中...", @@ -153,6 +178,8 @@ export const dict = { "prompt.placeholder.shell": "輸入 shell 命令...", "prompt.placeholder.normal": '隨便問點什麼... "{{example}}"', + "prompt.placeholder.summarizeComments": "摘要評論…", + "prompt.placeholder.summarizeComment": "摘要這則評論…", "prompt.mode.shell": "Shell", "prompt.mode.shell.exit": "按 esc 退出", @@ -255,6 +282,9 @@ export const dict = { "dialog.project.edit.color": "顏色", "dialog.project.edit.color.select": "選擇{{color}}顏色", + "dialog.project.edit.worktree.startup": "工作區啟動腳本", + "dialog.project.edit.worktree.startup.description": "在建立新的工作區 (worktree) 後執行。", + "dialog.project.edit.worktree.startup.placeholder": "例如 bun install", "context.breakdown.title": "上下文拆分", "context.breakdown.note": "輸入 token 的大致拆分。「其他」包含工具定義和額外開銷。", "context.breakdown.system": "系統", @@ -303,6 +333,7 @@ export const dict = { "language.ar": "العربية", "language.no": "Norsk", "language.br": "Português (Brasil)", + "language.th": "ไทย", "toast.language.title": "語言", "toast.language.description": "已切換到 {{language}}", @@ -320,6 +351,9 @@ export const dict = { "toast.file.loadFailed.title": "載入檔案失敗", + "toast.file.listFailed.title": "列出檔案失敗", + "toast.context.noLineSelection.title": "未選取行", + "toast.context.noLineSelection.description": "請先在檔案分頁中選取行範圍。", "toast.session.share.copyFailed.title": "無法複製連結到剪貼簿", "toast.session.share.success.title": "工作階段已分享", "toast.session.share.success.description": "分享連結已複製到剪貼簿", @@ -392,13 +426,19 @@ export const dict = { "session.tab.context": "上下文", "session.panel.reviewAndFiles": "審查與檔案", "session.review.filesChanged": "{{count}} 個檔案變更", + "session.review.change.one": "變更", + "session.review.change.other": "變更", "session.review.loadingChanges": "正在載入變更...", "session.review.empty": "此工作階段暫無變更", + "session.review.noChanges": "沒有變更", + "session.files.selectToOpen": "選取要開啟的檔案", + "session.files.all": "所有檔案", "session.messages.renderEarlier": "顯示更早的訊息", "session.messages.loadingEarlier": "正在載入更早的訊息...", "session.messages.loadEarlier": "載入更早的訊息", "session.messages.loading": "正在載入訊息...", + "session.messages.jumpToLatest": "跳到最新", "session.context.addToContext": "將 {{selection}} 新增到上下文", "session.new.worktree.main": "主分支", @@ -438,6 +478,8 @@ export const dict = { "terminal.title.numbered": "終端機 {{number}}", "terminal.close": "關閉終端機", + "terminal.connectionLost.title": "連線中斷", + "terminal.connectionLost.description": "終端機連線已中斷。這可能會在伺服器重新啟動時發生。", "common.closeTab": "關閉標籤頁", "common.dismiss": "忽略", "common.requestFailed": "要求失敗", @@ -451,6 +493,8 @@ export const dict = { "common.edit": "編輯", "common.loadMore": "載入更多", + "common.key.esc": "ESC", + "sidebar.menu.toggle": "切換選單", "sidebar.nav.projectsAndSessions": "專案與工作階段", "sidebar.settings": "設定", "sidebar.help": "說明", @@ -462,12 +506,15 @@ export const dict = { "sidebar.project.recentSessions": "最近工作階段", "sidebar.project.viewAllSessions": "查看全部工作階段", + "app.name.desktop": "OpenCode Desktop", "settings.section.desktop": "桌面", + "settings.section.server": "伺服器", "settings.tab.general": "一般", "settings.tab.shortcuts": "快速鍵", "settings.general.section.appearance": "外觀", "settings.general.section.notifications": "系統通知", + "settings.general.section.updates": "更新", "settings.general.section.sounds": "音效", "settings.general.row.language.title": "語言", @@ -479,6 +526,75 @@ export const dict = { "settings.general.row.font.title": "字型", "settings.general.row.font.description": "自訂程式碼區塊使用的等寬字型", + "settings.general.row.releaseNotes.title": "發行說明", + "settings.general.row.releaseNotes.description": "更新後顯示「新功能」彈出視窗", + + "settings.updates.row.startup.title": "啟動時檢查更新", + "settings.updates.row.startup.description": "在 OpenCode 啟動時自動檢查更新", + "settings.updates.row.check.title": "檢查更新", + "settings.updates.row.check.description": "手動檢查更新並在有更新時安裝", + "settings.updates.action.checkNow": "立即檢查", + "settings.updates.action.checking": "檢查中...", + "settings.updates.toast.latest.title": "已是最新版本", + "settings.updates.toast.latest.description": "你正在使用最新版本的 OpenCode。", + + "font.option.ibmPlexMono": "IBM Plex Mono", + "font.option.cascadiaCode": "Cascadia Code", + "font.option.firaCode": "Fira Code", + "font.option.hack": "Hack", + "font.option.inconsolata": "Inconsolata", + "font.option.intelOneMono": "Intel One Mono", + "font.option.iosevka": "Iosevka", + "font.option.jetbrainsMono": "JetBrains Mono", + "font.option.mesloLgs": "Meslo LGS", + "font.option.robotoMono": "Roboto Mono", + "font.option.sourceCodePro": "Source Code Pro", + "font.option.ubuntuMono": "Ubuntu Mono", + "sound.option.alert01": "警報 01", + "sound.option.alert02": "警報 02", + "sound.option.alert03": "警報 03", + "sound.option.alert04": "警報 04", + "sound.option.alert05": "警報 05", + "sound.option.alert06": "警報 06", + "sound.option.alert07": "警報 07", + "sound.option.alert08": "警報 08", + "sound.option.alert09": "警報 09", + "sound.option.alert10": "警報 10", + "sound.option.bipbop01": "嗶啵 01", + "sound.option.bipbop02": "嗶啵 02", + "sound.option.bipbop03": "嗶啵 03", + "sound.option.bipbop04": "嗶啵 04", + "sound.option.bipbop05": "嗶啵 05", + "sound.option.bipbop06": "嗶啵 06", + "sound.option.bipbop07": "嗶啵 07", + "sound.option.bipbop08": "嗶啵 08", + "sound.option.bipbop09": "嗶啵 09", + "sound.option.bipbop10": "嗶啵 10", + "sound.option.staplebops01": "斯泰普博普斯 01", + "sound.option.staplebops02": "斯泰普博普斯 02", + "sound.option.staplebops03": "斯泰普博普斯 03", + "sound.option.staplebops04": "斯泰普博普斯 04", + "sound.option.staplebops05": "斯泰普博普斯 05", + "sound.option.staplebops06": "斯泰普博普斯 06", + "sound.option.staplebops07": "斯泰普博普斯 07", + "sound.option.nope01": "否 01", + "sound.option.nope02": "否 02", + "sound.option.nope03": "否 03", + "sound.option.nope04": "否 04", + "sound.option.nope05": "否 05", + "sound.option.nope06": "否 06", + "sound.option.nope07": "否 07", + "sound.option.nope08": "否 08", + "sound.option.nope09": "否 09", + "sound.option.nope10": "否 10", + "sound.option.nope11": "否 11", + "sound.option.nope12": "否 12", + "sound.option.yup01": "是 01", + "sound.option.yup02": "是 02", + "sound.option.yup03": "是 03", + "sound.option.yup04": "是 04", + "sound.option.yup05": "是 05", + "sound.option.yup06": "是 06", "settings.general.notifications.agent.title": "代理程式", "settings.general.notifications.agent.description": "當代理程式完成或需要注意時顯示系統通知", "settings.general.notifications.permissions.title": "權限", @@ -513,6 +629,13 @@ export const dict = { "settings.providers.title": "提供者", "settings.providers.description": "提供者設定將在此處可設定。", + "settings.providers.section.connected": "已連線的提供商", + "settings.providers.connected.empty": "沒有已連線的提供商", + "settings.providers.section.popular": "熱門提供商", + "settings.providers.tag.environment": "環境", + "settings.providers.tag.config": "配置", + "settings.providers.tag.custom": "自訂", + "settings.providers.tag.other": "其他", "settings.models.title": "模型", "settings.models.description": "模型設定將在此處可設定。", "settings.agents.title": "代理程式", @@ -579,6 +702,7 @@ export const dict = { "workspace.reset.failed.title": "重設工作區失敗", "workspace.reset.success.title": "工作區已重設", "workspace.reset.success.description": "工作區已與預設分支保持一致。", + "workspace.error.stillPreparing": "工作區仍在準備中", "workspace.status.checking": "正在檢查未合併的變更...", "workspace.status.error": "無法驗證 git 狀態。", "workspace.status.clean": "未偵測到未合併的變更。", diff --git a/packages/app/src/index.css b/packages/app/src/index.css index 3d7b9db7af..4af87bca63 100644 --- a/packages/app/src/index.css +++ b/packages/app/src/index.css @@ -1,57 +1 @@ @import "@opencode-ai/ui/styles/tailwind"; - -:root { - a { - cursor: default; - } -} - -[data-component="markdown"] ul { - list-style: disc outside; - padding-left: 1.5rem; -} - -[data-component="markdown"] ol { - list-style: decimal outside; - padding-left: 1.5rem; -} - -[data-component="markdown"] li > p:first-child { - display: inline; - margin: 0; -} - -[data-component="markdown"] li > p + p { - display: block; - margin-top: 0.5rem; -} - -*[data-tauri-drag-region] { - app-region: drag; -} - -.session-scroller::-webkit-scrollbar { - width: 10px !important; - height: 10px !important; -} - -.session-scroller::-webkit-scrollbar-track { - background: transparent !important; - border-radius: 5px !important; -} - -.session-scroller::-webkit-scrollbar-thumb { - background: var(--border-weak-base) !important; - border-radius: 5px !important; - border: 3px solid transparent !important; - background-clip: padding-box !important; -} - -.session-scroller::-webkit-scrollbar-thumb:hover { - background: var(--border-weak-base) !important; -} - -.session-scroller { - scrollbar-width: thin !important; - scrollbar-color: var(--border-weak-base) transparent !important; -} diff --git a/packages/app/src/pages/directory-layout.tsx b/packages/app/src/pages/directory-layout.tsx index 10e86d16d9..b10aee05e8 100644 --- a/packages/app/src/pages/directory-layout.tsx +++ b/packages/app/src/pages/directory-layout.tsx @@ -1,22 +1,36 @@ -import { createMemo, Show, type ParentProps } from "solid-js" +import { createEffect, createMemo, Show, type ParentProps } from "solid-js" import { useNavigate, useParams } from "@solidjs/router" import { SDKProvider, useSDK } from "@/context/sdk" import { SyncProvider, useSync } from "@/context/sync" import { LocalProvider } from "@/context/local" -import { base64Decode } from "@opencode-ai/util/encode" import { DataProvider } from "@opencode-ai/ui/context" import { iife } from "@opencode-ai/util/iife" import type { QuestionAnswer } from "@kilocode/sdk/v2" // kilocode_change +import { decode64 } from "@/utils/base64" +import { showToast } from "@opencode-ai/ui/toast" +import { useLanguage } from "@/context/language" export default function Layout(props: ParentProps) { const params = useParams() const navigate = useNavigate() + const language = useLanguage() const directory = createMemo(() => { - return base64Decode(params.dir!) + return decode64(params.dir) ?? "" + }) + + createEffect(() => { + if (!params.dir) return + if (directory()) return + showToast({ + variant: "error", + title: language.t("common.requestFailed"), + description: "Invalid directory in URL.", + }) + navigate("/") }) return ( - + {iife(() => { diff --git a/packages/app/src/pages/home.tsx b/packages/app/src/pages/home.tsx index 0c04c07671..10f7dac530 100644 --- a/packages/app/src/pages/home.tsx +++ b/packages/app/src/pages/home.tsx @@ -23,6 +23,11 @@ export default function Home() { const server = useServer() const language = useLanguage() const homedir = createMemo(() => sync.data.path.home) + const recent = createMemo(() => { + return sync.data.project + .toSorted((a, b) => (b.time.updated ?? b.time.created) - (a.time.updated ?? a.time.created)) + .slice(0, 5) + }) function openProject(directory: string) { layout.projects.open(directory) @@ -84,11 +89,7 @@ export default function Home() {
    - (b.time.updated ?? b.time.created) - (a.time.updated ?? a.time.created)) - .slice(0, 5)} - > + {(project) => (
0 && props.notify}> @@ -1553,6 +1638,7 @@ export default function Layout(props: ParentProps) { mobile?: boolean dense?: boolean popover?: boolean + children?: Map }): JSX.Element => { const notification = useNotification() const notifications = createMemo(() => notification.session.unseen(props.session.id)) @@ -1561,6 +1647,16 @@ export default function Layout(props: ParentProps) { const hasPermissions = createMemo(() => { const permissions = sessionStore.permission?.[props.session.id] ?? [] if (permissions.length > 0) return true + + const childIDs = props.children?.get(props.session.id) + if (childIDs) { + for (const id of childIDs) { + const childPermissions = sessionStore.permission?.[id] ?? [] + if (childPermissions.length > 0) return true + } + return false + } + const childSessions = sessionStore.session.filter((s) => s.parentID === props.session.id) for (const child of childSessions) { const childPermissions = sessionStore.permission?.[child.id] ?? [] @@ -1584,18 +1680,36 @@ export default function Layout(props: ParentProps) { if (!user?.agent) return undefined const agent = sessionStore.agent.find((a) => a.name === user.agent) - return agent?.color + return agentColor(user.agent, agent?.color) }) const hoverMessages = createMemo(() => sessionStore.message[props.session.id]?.filter((message) => message.role === "user"), ) const hoverReady = createMemo(() => sessionStore.message[props.session.id] !== undefined) - const hoverAllowed = createMemo(() => !props.mobile && layout.sidebar.opened()) + const hoverAllowed = createMemo(() => !props.mobile && sidebarExpanded()) const hoverEnabled = createMemo(() => (props.popover ?? true) && hoverAllowed()) const isActive = createMemo(() => props.session.id === params.id) - const [menuOpen, setMenuOpen] = createSignal(false) - const [pendingRename, setPendingRename] = createSignal(false) + const [menu, setMenu] = createStore({ + open: false, + pendingRename: false, + }) + + const hoverPrefetch = { current: undefined as ReturnType | undefined } + const cancelHoverPrefetch = () => { + if (hoverPrefetch.current === undefined) return + clearTimeout(hoverPrefetch.current) + hoverPrefetch.current = undefined + } + const scheduleHoverPrefetch = () => { + if (hoverPrefetch.current !== undefined) return + hoverPrefetch.current = setTimeout(() => { + hoverPrefetch.current = undefined + prefetchSession(props.session) + }, 200) + } + + onCleanup(cancelHoverPrefetch) const messageLabel = (message: Message) => { const parts = sessionStore.part[message.id] ?? [] @@ -1606,10 +1720,17 @@ export default function Layout(props: ParentProps) { const item = ( prefetchSession(props.session, "high")} + class={`flex items-center justify-between gap-3 min-w-0 text-left w-full focus:outline-none transition-[padding] ${menu.open ? "pr-7" : ""} group-hover/session:pr-7 group-focus-within/session:pr-7 group-active/session:pr-7 ${props.dense ? "py-0.5" : "py-1"}`} + onPointerEnter={scheduleHoverPrefetch} + onPointerLeave={cancelHoverPrefetch} + onMouseEnter={scheduleHoverPrefetch} + onMouseLeave={cancelHoverPrefetch} onFocus={() => prefetchSession(props.session, "high")} - onClick={() => setHoverSession(undefined)} + onClick={() => { + setState("hoverSession", undefined) + if (layout.sidebar.opened()) return + queueMicrotask(() => setState("hoverProject", undefined)) + }} >
setHoverSession(open ? props.session.id : undefined)} + mount={!props.mobile ? state.nav : undefined} + open={state.hoverSession === props.session.id} + onOpenChange={(open) => setState("hoverSession", open ? props.session.id : undefined)} > - + setMenu("open", open)}> - + { - if (!pendingRename()) return + if (!menu.pendingRename) return event.preventDefault() - setPendingRename(false) + setMenu("pendingRename", false) openEditor(`session:${props.session.id}`, props.session.title) }} > { - setPendingRename(true) - setMenuOpen(false) + setMenu("pendingRename", true) + setMenu("open", false) }} > {language.t("common.rename")} @@ -1751,13 +1874,17 @@ export default function Layout(props: ParentProps) { const NewSessionItem = (props: { slug: string; mobile?: boolean; dense?: boolean }): JSX.Element => { const label = language.t("command.session.new") - const tooltip = () => props.mobile || !layout.sidebar.opened() + const tooltip = () => props.mobile || !sidebarExpanded() const item = ( setHoverSession(undefined)} + onClick={() => { + setState("hoverSession", undefined) + if (layout.sidebar.opened()) return + queueMicrotask(() => setState("hoverProject", undefined)) + }} >
@@ -1771,7 +1898,7 @@ export default function Layout(props: ParentProps) { ) return ( -
+
{ const label = createMemo(() => { - const project = currentProject() + const project = sidebarProject() if (!project) return const directory = store.activeWorkspace if (!directory) return - const [workspaceStore] = globalSync.child(directory) + const [workspaceStore] = globalSync.child(directory, { bootstrap: false }) const kind = directory === project.worktree ? language.t("workspace.type.local") : language.t("workspace.type.sandbox") const name = workspaceLabel(directory, workspaceStore.vcs?.branch, project.id) @@ -1836,18 +1963,33 @@ export default function Layout(props: ParentProps) { const SortableWorkspace = (props: { directory: string; project: LocalProject; mobile?: boolean }): JSX.Element => { const sortable = createSortable(props.directory) const [workspaceStore, setWorkspaceStore] = globalSync.child(props.directory, { bootstrap: false }) - const [menuOpen, setMenuOpen] = createSignal(false) - const [pendingRename, setPendingRename] = createSignal(false) + const [menu, setMenu] = createStore({ + open: false, + pendingRename: false, + }) const slug = createMemo(() => base64Encode(props.directory)) const sessions = createMemo(() => workspaceStore.session .filter((session) => session.directory === workspaceStore.path.directory) .filter((session) => !session.parentID && !session.time?.archived) - .toSorted(sortSessions), + .toSorted(sortSessions(Date.now())), ) + const children = createMemo(() => { + const map = new Map() + for (const session of workspaceStore.session) { + if (!session.parentID) continue + const existing = map.get(session.parentID) + if (existing) { + existing.push(session.id) + continue + } + map.set(session.parentID, [session.id]) + } + return map + }) const local = createMemo(() => props.directory === props.project.worktree) const active = createMemo(() => { - const current = params.dir ? base64Decode(params.dir) : "" + const current = decode64(params.dir) ?? "" return current === props.directory }) const workspaceValue = createMemo(() => { @@ -1857,11 +1999,11 @@ export default function Layout(props: ParentProps) { }) const open = createMemo(() => store.workspaceExpanded[props.directory] ?? local()) const boot = createMemo(() => open() || active()) - const loading = createMemo(() => open() && workspaceStore.status !== "complete" && sessions().length === 0) - const hasMore = createMemo(() => local() && workspaceStore.sessionTotal > workspaceStore.session.length) + const booted = createMemo((prev) => prev || workspaceStore.status === "complete", false) + const loading = createMemo(() => open() && !booted() && sessions().length === 0) + const hasMore = createMemo(() => workspaceStore.sessionTotal > sessions().length) const busy = createMemo(() => isBusy(props.directory)) const loadMore = async () => { - if (!local()) return setWorkspaceStore("limit", (limit) => limit + 5) await globalSync.project.loadSessions(props.directory) } @@ -1947,13 +2089,17 @@ export default function Layout(props: ParentProps) {
- + setMenu("open", open)} + > - + { - if (!pendingRename()) return + if (!menu.pendingRename) return event.preventDefault() - setPendingRename(false) + setMenu("pendingRename", false) openEditor(`workspace:${props.directory}`, workspaceValue()) }} > { - setPendingRename(true) - setMenuOpen(false) + setMenu("pendingRename", true) + setMenu("open", false) }} > {language.t("common.rename")} dialog.show(() => )} + onSelect={() => + dialog.show(() => ( + + )) + } > {language.t("common.reset")} dialog.show(() => )} + onSelect={() => + dialog.show(() => ( + + )) + } > {language.t("common.delete")} @@ -2003,14 +2157,14 @@ export default function Layout(props: ParentProps) {
} > @@ -2439,7 +2971,7 @@ export default function Page() { terminal={pty} onClose={() => { view().terminal.close() - setAutoCreated(false) + setUi("autoCreated", false) }} /> )} diff --git a/packages/app/src/utils/agent.ts b/packages/app/src/utils/agent.ts new file mode 100644 index 0000000000..7c2c81e746 --- /dev/null +++ b/packages/app/src/utils/agent.ts @@ -0,0 +1,11 @@ +const defaults: Record = { + ask: "var(--icon-agent-ask-base)", + build: "var(--icon-agent-build-base)", + docs: "var(--icon-agent-docs-base)", + plan: "var(--icon-agent-plan-base)", +} + +export function agentColor(name: string, custom?: string) { + if (custom) return custom + return defaults[name] ?? defaults[name.toLowerCase()] +} diff --git a/packages/app/src/utils/base64.ts b/packages/app/src/utils/base64.ts new file mode 100644 index 0000000000..c1f9d88c6e --- /dev/null +++ b/packages/app/src/utils/base64.ts @@ -0,0 +1,10 @@ +import { base64Decode } from "@opencode-ai/util/encode" + +export function decode64(value: string | undefined) { + if (value === undefined) return + try { + return base64Decode(value) + } catch { + return + } +} diff --git a/packages/app/src/utils/persist.ts b/packages/app/src/utils/persist.ts index 70884977c7..0ca3abad06 100644 --- a/packages/app/src/utils/persist.ts +++ b/packages/app/src/utils/persist.ts @@ -18,7 +18,52 @@ const LEGACY_STORAGE = "default.dat" const GLOBAL_STORAGE = "opencode.global.dat" const LOCAL_PREFIX = "opencode." const fallback = { disabled: false } -const cache = new Map() + +const CACHE_MAX_ENTRIES = 500 +const CACHE_MAX_BYTES = 8 * 1024 * 1024 + +type CacheEntry = { value: string; bytes: number } +const cache = new Map() +const cacheTotal = { bytes: 0 } + +function cacheDelete(key: string) { + const entry = cache.get(key) + if (!entry) return + cacheTotal.bytes -= entry.bytes + cache.delete(key) +} + +function cachePrune() { + for (;;) { + if (cache.size <= CACHE_MAX_ENTRIES && cacheTotal.bytes <= CACHE_MAX_BYTES) return + const oldest = cache.keys().next().value as string | undefined + if (!oldest) return + cacheDelete(oldest) + } +} + +function cacheSet(key: string, value: string) { + const bytes = value.length * 2 + if (bytes > CACHE_MAX_BYTES) { + cacheDelete(key) + return + } + + const entry = cache.get(key) + if (entry) cacheTotal.bytes -= entry.bytes + cache.delete(key) + cache.set(key, { value, bytes }) + cacheTotal.bytes += bytes + cachePrune() +} + +function cacheGet(key: string) { + const entry = cache.get(key) + if (!entry) return + cache.delete(key) + cache.set(key, entry) + return entry.value +} function quota(error: unknown) { if (error instanceof DOMException) { @@ -63,9 +108,11 @@ function evict(storage: Storage, keep: string, value: string) { for (const item of items) { storage.removeItem(item.key) + cacheDelete(item.key) try { storage.setItem(keep, value) + cacheSet(keep, value) return true } catch (error) { if (!quota(error)) throw error @@ -78,6 +125,7 @@ function evict(storage: Storage, keep: string, value: string) { function write(storage: Storage, key: string, value: string) { try { storage.setItem(key, value) + cacheSet(key, value) return true } catch (error) { if (!quota(error)) throw error @@ -85,13 +133,17 @@ function write(storage: Storage, key: string, value: string) { try { storage.removeItem(key) + cacheDelete(key) storage.setItem(key, value) + cacheSet(key, value) return true } catch (error) { if (!quota(error)) throw error } - return evict(storage, key, value) + const ok = evict(storage, key, value) + if (!ok) cacheSet(key, value) + return ok } function snapshot(value: unknown) { @@ -148,17 +200,24 @@ function localStorageWithPrefix(prefix: string): SyncStorage { return { getItem: (key) => { const name = item(key) - const cached = cache.get(name) + const cached = cacheGet(name) if (fallback.disabled && cached !== undefined) return cached - const stored = localStorage.getItem(name) + const stored = (() => { + try { + return localStorage.getItem(name) + } catch { + fallback.disabled = true + return null + } + })() if (stored === null) return cached ?? null - cache.set(name, stored) + cacheSet(name, stored) return stored }, setItem: (key, value) => { const name = item(key) - cache.set(name, value) + cacheSet(name, value) if (fallback.disabled) return try { if (write(localStorage, name, value)) return @@ -170,9 +229,13 @@ function localStorageWithPrefix(prefix: string): SyncStorage { }, removeItem: (key) => { const name = item(key) - cache.delete(name) + cacheDelete(name) if (fallback.disabled) return - localStorage.removeItem(name) + try { + localStorage.removeItem(name) + } catch { + fallback.disabled = true + } }, } } @@ -180,16 +243,23 @@ function localStorageWithPrefix(prefix: string): SyncStorage { function localStorageDirect(): SyncStorage { return { getItem: (key) => { - const cached = cache.get(key) + const cached = cacheGet(key) if (fallback.disabled && cached !== undefined) return cached - const stored = localStorage.getItem(key) + const stored = (() => { + try { + return localStorage.getItem(key) + } catch { + fallback.disabled = true + return null + } + })() if (stored === null) return cached ?? null - cache.set(key, stored) + cacheSet(key, stored) return stored }, setItem: (key, value) => { - cache.set(key, value) + cacheSet(key, value) if (fallback.disabled) return try { if (write(localStorage, key, value)) return @@ -200,9 +270,13 @@ function localStorageDirect(): SyncStorage { fallback.disabled = true }, removeItem: (key) => { - cache.delete(key) + cacheDelete(key) if (fallback.disabled) return - localStorage.removeItem(key) + try { + localStorage.removeItem(key) + } catch { + fallback.disabled = true + } }, } } diff --git a/packages/app/src/utils/speech.ts b/packages/app/src/utils/speech.ts index 921e0a159b..201c1261bd 100644 --- a/packages/app/src/utils/speech.ts +++ b/packages/app/src/utils/speech.ts @@ -1,4 +1,5 @@ -import { createSignal, onCleanup } from "solid-js" +import { onCleanup } from "solid-js" +import { createStore } from "solid-js/store" // Minimal types to avoid relying on non-standard DOM typings type RecognitionResult = { @@ -59,9 +60,15 @@ export function createSpeechRecognition(opts?: { typeof window !== "undefined" && Boolean((window as any).webkitSpeechRecognition || (window as any).SpeechRecognition) - const [isRecording, setIsRecording] = createSignal(false) - const [committed, setCommitted] = createSignal("") - const [interim, setInterim] = createSignal("") + const [store, setStore] = createStore({ + isRecording: false, + committed: "", + interim: "", + }) + + const isRecording = () => store.isRecording + const committed = () => store.committed + const interim = () => store.interim let recognition: Recognition | undefined let shouldContinue = false @@ -71,6 +78,7 @@ export function createSpeechRecognition(opts?: { let lastInterimSuffix = "" let shrinkCandidate: string | undefined let commitTimer: number | undefined + let restartTimer: number | undefined const cancelPendingCommit = () => { if (commitTimer === undefined) return @@ -78,11 +86,31 @@ export function createSpeechRecognition(opts?: { commitTimer = undefined } + const clearRestart = () => { + if (restartTimer === undefined) return + window.clearTimeout(restartTimer) + restartTimer = undefined + } + + const scheduleRestart = () => { + clearRestart() + if (!shouldContinue) return + if (!recognition) return + restartTimer = window.setTimeout(() => { + restartTimer = undefined + if (!shouldContinue) return + if (!recognition) return + try { + recognition.start() + } catch {} + }, 150) + } + const commitSegment = (segment: string) => { const nextCommitted = appendSegment(committedText, segment) if (nextCommitted === committedText) return committedText = nextCommitted - setCommitted(committedText) + setStore("committed", committedText) if (opts?.onFinal) opts.onFinal(segment.trim()) } @@ -98,7 +126,7 @@ export function createSpeechRecognition(opts?: { pendingHypothesis = "" lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") } @@ -107,7 +135,7 @@ export function createSpeechRecognition(opts?: { pendingHypothesis = hypothesis lastInterimSuffix = suffix shrinkCandidate = undefined - setInterim(suffix) + setStore("interim", suffix) if (opts?.onInterim) { opts.onInterim(suffix ? appendSegment(committedText, suffix) : "") } @@ -122,7 +150,7 @@ export function createSpeechRecognition(opts?: { pendingHypothesis = "" lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") }, COMMIT_DELAY) } @@ -162,7 +190,7 @@ export function createSpeechRecognition(opts?: { pendingHypothesis = "" lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") return } @@ -207,58 +235,54 @@ export function createSpeechRecognition(opts?: { } recognition.onerror = (e: { error: string }) => { + clearRestart() cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined if (e.error === "no-speech" && shouldContinue) { - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") - setTimeout(() => { - try { - recognition?.start() - } catch {} - }, 150) + scheduleRestart() return } shouldContinue = false - setIsRecording(false) + setStore("isRecording", false) } recognition.onstart = () => { + clearRestart() sessionCommitted = "" pendingHypothesis = "" cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") - setIsRecording(true) + setStore("isRecording", true) } recognition.onend = () => { + clearRestart() cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined - setIsRecording(false) + setStore("isRecording", false) if (shouldContinue) { - setTimeout(() => { - try { - recognition?.start() - } catch {} - }, 150) + scheduleRestart() } } } const start = () => { if (!recognition) return + clearRestart() shouldContinue = true sessionCommitted = "" pendingHypothesis = "" cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") try { recognition.start() } catch {} @@ -267,11 +291,12 @@ export function createSpeechRecognition(opts?: { const stop = () => { if (!recognition) return shouldContinue = false + clearRestart() promotePending() cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") try { recognition.stop() @@ -280,11 +305,12 @@ export function createSpeechRecognition(opts?: { onCleanup(() => { shouldContinue = false + clearRestart() promotePending() cancelPendingCommit() lastInterimSuffix = "" shrinkCandidate = undefined - setInterim("") + setStore("interim", "") if (opts?.onInterim) opts.onInterim("") try { recognition?.stop() diff --git a/packages/app/src/utils/worktree.ts b/packages/app/src/utils/worktree.ts index 7c0055920b..581afd5535 100644 --- a/packages/app/src/utils/worktree.ts +++ b/packages/app/src/utils/worktree.ts @@ -13,7 +13,21 @@ type State = } const state = new Map() -const waiters = new Map void>>() +const waiters = new Map< + string, + { + promise: Promise + resolve: (state: State) => void + } +>() + +function deferred() { + const box = { resolve: (_: State) => {} } + const promise = new Promise((resolve) => { + box.resolve = resolve + }) + return { promise, resolve: box.resolve } +} export const Worktree = { get(directory: string) { @@ -27,32 +41,33 @@ export const Worktree = { }, ready(directory: string) { const key = normalize(directory) - state.set(key, { status: "ready" }) - const list = waiters.get(key) - if (!list) return + const next = { status: "ready" } as const + state.set(key, next) + const waiter = waiters.get(key) + if (!waiter) return waiters.delete(key) - for (const fn of list) fn({ status: "ready" }) + waiter.resolve(next) }, failed(directory: string, message: string) { const key = normalize(directory) - state.set(key, { status: "failed", message }) - const list = waiters.get(key) - if (!list) return + const next = { status: "failed", message } as const + state.set(key, next) + const waiter = waiters.get(key) + if (!waiter) return waiters.delete(key) - for (const fn of list) fn({ status: "failed", message }) + waiter.resolve(next) }, wait(directory: string) { const key = normalize(directory) const current = state.get(key) if (current && current.status !== "pending") return Promise.resolve(current) - return new Promise((resolve) => { - const list = waiters.get(key) - if (!list) { - waiters.set(key, [resolve]) - return - } - list.push(resolve) - }) + const existing = waiters.get(key) + if (existing) return existing.promise + + const waiter = deferred() + + waiters.set(key, waiter) + return waiter.promise }, } diff --git a/packages/console/app/package.json b/packages/console/app/package.json index 169f9a7e89..f1b0aca8f5 100644 --- a/packages/console/app/package.json +++ b/packages/console/app/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-app", - "version": "1.1.36", + "version": "1.1.42", "type": "module", "license": "MIT", "scripts": { diff --git a/packages/console/app/src/lib/changelog.ts b/packages/console/app/src/lib/changelog.ts new file mode 100644 index 0000000000..93a0d423c6 --- /dev/null +++ b/packages/console/app/src/lib/changelog.ts @@ -0,0 +1,146 @@ +import { query } from "@solidjs/router" + +type Release = { + tag_name: string + name: string + body: string + published_at: string + html_url: string +} + +export type HighlightMedia = + | { type: "video"; src: string } + | { type: "image"; src: string; width: string; height: string } + +export type HighlightItem = { + title: string + description: string + shortDescription?: string + media: HighlightMedia +} + +export type HighlightGroup = { + source: string + items: HighlightItem[] +} + +export type ChangelogRelease = { + tag: string + name: string + date: string + url: string + highlights: HighlightGroup[] + sections: { title: string; items: string[] }[] +} + +export type ChangelogData = { + ok: boolean + releases: ChangelogRelease[] +} + +export async function loadChangelog(): Promise { + const response = await fetch("https://api.github.com/repos/anomalyco/opencode/releases?per_page=20", { + headers: { + Accept: "application/vnd.github.v3+json", + "User-Agent": "OpenCode-Console", + }, + cf: { + // best-effort edge caching (ignored outside Cloudflare) + cacheTtl: 60 * 5, + cacheEverything: true, + }, + } as RequestInit).catch(() => undefined) + + if (!response?.ok) return { ok: false, releases: [] } + + const data = await response.json().catch(() => undefined) + if (!Array.isArray(data)) return { ok: false, releases: [] } + + const releases = (data as Release[]).map((release) => { + const parsed = parseMarkdown(release.body || "") + return { + tag: release.tag_name, + name: release.name, + date: release.published_at, + url: release.html_url, + highlights: parsed.highlights, + sections: parsed.sections, + } + }) + + return { ok: true, releases } +} + +export const changelog = query(async () => { + "use server" + const result = await loadChangelog() + return result.releases +}, "changelog") + +function parseHighlights(body: string): HighlightGroup[] { + const groups = new Map() + const regex = /([\s\S]*?)<\/highlight>/g + let match + + while ((match = regex.exec(body)) !== null) { + const source = match[1] + const content = match[2] + + const titleMatch = content.match(/

([^<]+)<\/h2>/) + const pMatch = content.match(/([^<]+)<\/p>/) + const imgMatch = content.match(/ { + if (videoMatch) return { type: "video", src: videoMatch[1] } satisfies HighlightMedia + if (imgMatch) { + return { + type: "image", + src: imgMatch[3], + width: imgMatch[1], + height: imgMatch[2], + } satisfies HighlightMedia + } + })() + + if (!titleMatch || !media) continue + + const item: HighlightItem = { + title: titleMatch[1], + description: pMatch?.[2] || "", + shortDescription: pMatch?.[1], + media, + } + + if (!groups.has(source)) groups.set(source, []) + groups.get(source)!.push(item) + } + + return Array.from(groups.entries()).map(([source, items]) => ({ source, items })) +} + +function parseMarkdown(body: string) { + const lines = body.split("\n") + const sections: { title: string; items: string[] }[] = [] + let current: { title: string; items: string[] } | null = null + let skip = false + + for (const line of lines) { + if (line.startsWith("## ")) { + if (current) sections.push(current) + current = { title: line.slice(3).trim(), items: [] } + skip = false + continue + } + + if (line.startsWith("**Thank you")) { + skip = true + continue + } + + if (line.startsWith("- ") && !skip) current?.items.push(line.slice(2).trim()) + } + + if (current) sections.push(current) + return { sections, highlights: parseHighlights(body) } +} diff --git a/packages/console/app/src/routes/changelog.json.ts b/packages/console/app/src/routes/changelog.json.ts new file mode 100644 index 0000000000..f06c1be9b4 --- /dev/null +++ b/packages/console/app/src/routes/changelog.json.ts @@ -0,0 +1,30 @@ +import { loadChangelog } from "~/lib/changelog" + +const cors = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization", +} + +const ok = "public, max-age=1, s-maxage=300, stale-while-revalidate=86400, stale-if-error=86400" +const error = "public, max-age=1, s-maxage=60, stale-while-revalidate=600, stale-if-error=86400" + +export async function GET() { + const result = await loadChangelog().catch(() => ({ ok: false, releases: [] })) + + return new Response(JSON.stringify({ releases: result.releases }), { + status: result.ok ? 200 : 503, + headers: { + "Content-Type": "application/json", + "Cache-Control": result.ok ? ok : error, + ...cors, + }, + }) +} + +export async function OPTIONS() { + return new Response(null, { + status: 200, + headers: cors, + }) +} diff --git a/packages/console/app/src/routes/changelog/index.css b/packages/console/app/src/routes/changelog/index.css index a445c74474..950762ef6b 100644 --- a/packages/console/app/src/routes/changelog/index.css +++ b/packages/console/app/src/routes/changelog/index.css @@ -367,11 +367,18 @@ display: flex; flex-direction: column; gap: 4px; + position: sticky; + top: 80px; + align-self: start; + background: var(--color-background); + padding: 44px 0 8px; @media (max-width: 50rem) { + position: static; flex-direction: row; align-items: center; gap: 12px; + padding: 0; } [data-slot="version"] { @@ -402,24 +409,26 @@ [data-component="section"] { h3 { - font-size: 14px; + font-size: 13px; font-weight: 600; color: var(--color-text-strong); - margin-bottom: 8px; + margin-bottom: 6px; } ul { list-style: none; padding: 0; margin: 0; + padding-left: 16px; display: flex; flex-direction: column; - gap: 6px; + gap: 4px; li { color: var(--color-text); + font-size: 13px; line-height: 1.5; - padding-left: 16px; + padding-left: 12px; position: relative; &::before { @@ -431,7 +440,7 @@ [data-slot="author"] { color: var(--color-text-weak); - font-size: 13px; + font-size: 12px; margin-left: 4px; text-decoration: none; @@ -465,6 +474,120 @@ } } } + + [data-component="highlights"] { + display: flex; + flex-direction: column; + gap: 3rem; + margin-bottom: 0.75rem; + } + + [data-component="collapsible-sections"] { + display: flex; + flex-direction: column; + gap: 0; + } + + [data-component="collapsible-section"] { + [data-slot="toggle"] { + display: flex; + align-items: center; + gap: 6px; + background: none; + border: none; + padding: 6px 0; + cursor: pointer; + font-family: inherit; + font-size: 13px; + font-weight: 600; + color: var(--color-text-weak); + + &:hover { + color: var(--color-text); + } + + [data-slot="icon"] { + font-size: 10px; + } + } + + ul { + list-style: none; + padding: 0; + margin: 0; + padding-left: 16px; + padding-bottom: 8px; + + li { + color: var(--color-text); + font-size: 13px; + line-height: 1.5; + padding-left: 12px; + position: relative; + + &::before { + content: "-"; + position: absolute; + left: 0; + color: var(--color-text-weak); + } + + [data-slot="author"] { + color: var(--color-text-weak); + font-size: 12px; + margin-left: 4px; + text-decoration: none; + + &:hover { + text-decoration: underline; + text-underline-offset: 2px; + text-decoration-thickness: 1px; + } + } + } + } + } + + [data-component="highlight"] { + h4 { + font-size: 14px; + font-weight: 600; + color: var(--color-text-strong); + margin-bottom: 8px; + } + + hr { + border: none; + border-top: 1px solid var(--color-border-weak); + margin-bottom: 16px; + } + + [data-slot="highlight-item"] { + margin-bottom: 48px; + + &:last-child { + margin-bottom: 0; + } + + p[data-slot="title"] { + font-weight: 600; + font-size: 16px; + margin-bottom: 4px; + } + + p { + font-size: 14px; + margin-bottom: 12px; + } + } + + img, + video { + max-width: 100%; + height: auto; + border-radius: 4px; + } + } } a { diff --git a/packages/console/app/src/routes/changelog/index.tsx b/packages/console/app/src/routes/changelog/index.tsx index 96ef09cffb..e759456ae2 100644 --- a/packages/console/app/src/routes/changelog/index.tsx +++ b/packages/console/app/src/routes/changelog/index.tsx @@ -1,35 +1,13 @@ import "./index.css" import { Title, Meta, Link } from "@solidjs/meta" -import { createAsync, query } from "@solidjs/router" +import { createAsync } from "@solidjs/router" import { Header } from "~/component/header" import { Footer } from "~/component/footer" import { Legal } from "~/component/legal" import { config } from "~/config" -import { For, Show } from "solid-js" - -type Release = { - tag_name: string - name: string - body: string - published_at: string - html_url: string -} - -const getReleases = query(async () => { - "use server" - const response = await fetch("https://api.github.com/repos/Kilo-Org/kilo/releases?per_page=20", { - headers: { - Accept: "application/vnd.github.v3+json", - "User-Agent": "OpenCode-Console", - }, - cf: { - cacheTtl: 60 * 5, - cacheEverything: true, - }, - } as any) - if (!response.ok) return [] - return response.json() as Promise -}, "releases.get") +import { changelog } from "~/lib/changelog" +import type { HighlightGroup } from "~/lib/changelog" +import { For, Show, createSignal } from "solid-js" function formatDate(dateString: string) { const date = new Date(dateString) @@ -40,29 +18,6 @@ function formatDate(dateString: string) { }) } -function parseMarkdown(body: string) { - const lines = body.split("\n") - const sections: { title: string; items: string[] }[] = [] - let current: { title: string; items: string[] } | null = null - let skip = false - - for (const line of lines) { - if (line.startsWith("## ")) { - if (current) sections.push(current) - const title = line.slice(3).trim() - current = { title, items: [] } - skip = false - } else if (line.startsWith("**Thank you")) { - skip = true - } else if (line.startsWith("- ") && !skip) { - current?.items.push(line.slice(2).trim()) - } - } - if (current) sections.push(current) - - return { sections } -} - function ReleaseItem(props: { item: string }) { const parts = () => { const match = props.item.match(/^(.+?)(\s*\(@([\w-]+)\))?$/) @@ -87,8 +42,63 @@ function ReleaseItem(props: { item: string }) { ) } +function HighlightSection(props: { group: HighlightGroup }) { + return ( +
+

{props.group.source}

+
+ + {(item) => ( +
+

{item.title}

+

{item.description}

+ + + + {item.title} + +
+ )} +
+
+ ) +} + +function CollapsibleSection(props: { section: { title: string; items: string[] } }) { + const [open, setOpen] = createSignal(false) + + return ( +
+ + +
    + {(item) => } +
+
+
+ ) +} + +function CollapsibleSections(props: { sections: { title: string; items: string[] }[] }) { + return ( +
+ {(section) => } +
+ ) +} + export default function Changelog() { - const releases = createAsync(() => getReleases()) + const data = createAsync(() => changelog()) + const releases = () => data() ?? [] return (
@@ -106,39 +116,53 @@ export default function Changelog() {
+ +

+ No changelog entries found. View JSON +

+ {(release) => { - const parsed = () => parseMarkdown(release.body || "") return (
- +
- - {(section) => ( -
-

{section.title}

-
    - {(item) => } -
-
- )} -
+ 0}> +
+ {(group) => } +
+
+ 0 && release.sections.length > 0}> + + + + + {(section) => ( +
+

{section.title}

+
    + {(item) => } +
+
+ )} +
+
) }}
- -

+ +
diff --git a/packages/console/core/package.json b/packages/console/core/package.json index 95f019b1cd..59a9d2ecc4 100644 --- a/packages/console/core/package.json +++ b/packages/console/core/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@opencode-ai/console-core", - "version": "1.1.36", + "version": "1.1.42", "private": true, "type": "module", "license": "MIT", diff --git a/packages/console/function/package.json b/packages/console/function/package.json index 7202c4cfae..8cfdc1c0af 100644 --- a/packages/console/function/package.json +++ b/packages/console/function/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-function", - "version": "1.1.36", + "version": "1.1.42", "$schema": "https://json.schemastore.org/package.json", "private": true, "type": "module", diff --git a/packages/console/mail/package.json b/packages/console/mail/package.json index fc980b6fbf..622d34815c 100644 --- a/packages/console/mail/package.json +++ b/packages/console/mail/package.json @@ -1,6 +1,6 @@ { "name": "@opencode-ai/console-mail", - "version": "1.1.36", + "version": "1.1.42", "dependencies": { "@jsx-email/all": "2.2.3", "@jsx-email/cli": "1.4.3", diff --git a/packages/desktop/index.html b/packages/desktop/index.html index 6a81ef4a50..a5a8c2571f 100644 --- a/packages/desktop/index.html +++ b/packages/desktop/index.html @@ -17,7 +17,7 @@ -
+