SaylorTwift HF Staff commited on
Commit
9697ede
·
verified ·
1 Parent(s): eb1202c

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .opencode/agent/duplicate-pr.md +26 -0
  2. .opencode/agent/triage.md +43 -0
  3. .opencode/command/ai-deps.md +24 -0
  4. .opencode/command/changelog.md +49 -0
  5. .opencode/command/commit.md +37 -0
  6. .opencode/command/issues.md +23 -0
  7. .opencode/command/learn.md +42 -0
  8. .opencode/command/rmslop.md +15 -0
  9. .opencode/command/spellcheck.md +5 -0
  10. .opencode/command/translate.md +14 -0
  11. .opencode/glossary/README.md +63 -0
  12. .opencode/glossary/ar.md +28 -0
  13. .opencode/glossary/br.md +34 -0
  14. .opencode/glossary/bs.md +33 -0
  15. .opencode/glossary/da.md +27 -0
  16. .opencode/glossary/de.md +27 -0
  17. .opencode/glossary/es.md +27 -0
  18. .opencode/glossary/fr.md +27 -0
  19. .opencode/glossary/ja.md +33 -0
  20. .opencode/glossary/ko.md +27 -0
  21. .opencode/glossary/no.md +38 -0
  22. .opencode/glossary/pl.md +27 -0
  23. .opencode/glossary/ru.md +27 -0
  24. .opencode/glossary/th.md +34 -0
  25. .opencode/glossary/tr.md +38 -0
  26. .opencode/glossary/zh-cn.md +42 -0
  27. .opencode/glossary/zh-tw.md +42 -0
  28. .opencode/plugins/smoke-theme.json +223 -0
  29. .opencode/plugins/tui-smoke.tsx +1019 -0
  30. .opencode/skills/effect/SKILL.md +38 -0
  31. .opencode/skills/rtl-aware-development/SKILL.md +63 -0
  32. .opencode/themes/.gitignore +1 -0
  33. .opencode/themes/mytheme.json +223 -0
  34. .opencode/tool/github-pr-search.ts +64 -0
  35. .opencode/tool/github-triage.ts +60 -0
  36. artifacts/glm52-rise-video/.gitignore +3 -0
  37. artifacts/glm52-rise-video/bun.lock +483 -0
  38. artifacts/glm52-rise-video/out/june-totals.png +0 -0
  39. artifacts/glm52-rise-video/package.json +24 -0
  40. artifacts/glm52-rise-video/src/data.ts +156 -0
  41. artifacts/glm52-rise-video/src/flash.tsx +185 -0
  42. artifacts/glm52-rise-video/src/index.tsx +36 -0
  43. artifacts/glm52-rise-video/src/june.tsx +144 -0
  44. artifacts/glm52-rise-video/src/minimax.tsx +201 -0
  45. artifacts/glm52-rise-video/src/novel.tsx +135 -0
  46. artifacts/glm52-rise-video/src/sheep.tsx +139 -0
  47. artifacts/glm52-rise-video/src/video.tsx +254 -0
  48. artifacts/glm52-rise-video/sst-env.d.ts +10 -0
  49. github/script/publish +15 -0
  50. github/script/release +41 -0
.opencode/agent/duplicate-pr.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ mode: primary
3
+ hidden: true
4
+ model: opencode/claude-haiku-4-5
5
+ color: "#E67E22"
6
+ tools:
7
+ "*": false
8
+ "github-pr-search": true
9
+ ---
10
+
11
+ You are a duplicate PR detection agent. When a PR is opened, your job is to search for potentially duplicate or related open PRs.
12
+
13
+ Use the github-pr-search tool to search for PRs that might be addressing the same issue or feature.
14
+
15
+ IMPORTANT: The input will contain a line `CURRENT_PR_NUMBER: NNNN`. This is the current PR number, you should not mark that the current PR as a duplicate of itself.
16
+
17
+ Search using keywords from the PR title and description. Try multiple searches with different relevant terms.
18
+
19
+ If you find potential duplicates:
20
+
21
+ - List them with their titles and URLs
22
+ - Briefly explain why they might be related
23
+
24
+ If no duplicates are found, say so clearly. BUT ONLY SAY "No duplicate PRs found" (don't say anything else if no dups)
25
+
26
+ Keep your response concise and actionable.
.opencode/agent/triage.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ mode: primary
3
+ hidden: true
4
+ model: opencode/gpt-5.4-mini
5
+ color: "#44BA81"
6
+ tools:
7
+ "*": false
8
+ "github-triage": true
9
+ ---
10
+
11
+ You are a triage agent responsible for triaging github issues.
12
+
13
+ Use your github-triage tool to triage issues.
14
+
15
+ This file is the source of truth for ownership/routing rules.
16
+
17
+ Assign issues by choosing the team with the strongest overlap. The github-triage tool will assign a random member from that team.
18
+
19
+ Do not add labels to issues. Only assign an owner.
20
+
21
+ When calling github-triage, pass one of these team values: tui, desktop_web, core, inference, windows.
22
+
23
+ ## Teams
24
+
25
+ ### TUI
26
+
27
+ Terminal UI issues, including rendering, keybindings, scrolling, terminal compatibility, SSH behavior, crashes in the TUI, and low-level TUI performance.
28
+
29
+ ### Desktop / Web
30
+
31
+ Desktop application and browser-based app issues, including `opencode web`, desktop-specific UI behavior, packaging, and web view problems.
32
+
33
+ ### Core
34
+
35
+ Core opencode server and harness issues, including sqlite, snapshots, memory, API behavior, agent context construction, tool execution, provider integrations, model behavior, documentation, and larger architectural features.
36
+
37
+ ### Inference
38
+
39
+ OpenCode Zen, OpenCode Go, and billing issues.
40
+
41
+ ### Windows
42
+
43
+ Windows-specific issues, including native Windows behavior, WSL interactions, path handling, shell compatibility, and installation or runtime problems that only happen on Windows.
.opencode/command/ai-deps.md ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: "Bump AI sdk dependencies minor / patch versions only"
3
+ ---
4
+
5
+ Please read @package.json and @packages/opencode/package.json.
6
+
7
+ 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).
8
+
9
+ I want a report of every dependency and the version that can be upgraded to.
10
+ 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.
11
+
12
+ Consider using subagents for each dep to save your context window.
13
+
14
+ Here is a short list of some deps (please be comprehensive tho):
15
+
16
+ - "ai"
17
+ - "@ai-sdk/openai"
18
+ - "@ai-sdk/anthropic"
19
+ - "@openrouter/ai-sdk-provider"
20
+ - etc, etc
21
+
22
+ DO NOT upgrade the dependencies yet, just make a list of all dependencies and their versions that can be upgraded to minor or patch versions only.
23
+
24
+ Write up your findings to ai-sdk-updates.md
.opencode/command/changelog.md ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ model: opencode/gpt-5.4
3
+ ---
4
+
5
+ Create `UPCOMING_CHANGELOG.md` from the structured changelog input below.
6
+ If `UPCOMING_CHANGELOG.md` already exists, ignore its current contents completely.
7
+ Do not preserve, merge, or reuse text from the existing file.
8
+
9
+ The input already contains the exact commit range since the last non-draft release.
10
+ The commits are already filtered to the release-relevant packages and grouped into
11
+ the release sections. Do not fetch GitHub releases, PRs, or build your own commit list.
12
+ The input may also include a `## Community Contributors Input` section.
13
+
14
+ Before writing any entry you keep, inspect the real diff with
15
+ `git show --stat --format='' <hash>` or `git show --format='' <hash>` so you can
16
+ understand the actual code changes and not just the commit message (they may be misleading).
17
+ Do not use `git log` or author metadata when deciding attribution.
18
+
19
+ Rules:
20
+
21
+ - Write the final file with release sections in this order:
22
+ `## Core`, `## TUI`, `## Desktop`, `## SDK`, `## Extensions`
23
+ - Only include sections that have at least one notable entry
24
+ - Within each release section, keep bug fixes grouped under `### Bugfixes`
25
+ - Keep other notable entries under `### Improvements` when a section has bug fixes too
26
+ - Omit empty subsections
27
+ - Keep one bullet per commit you keep
28
+ - Skip commits that are entirely internal, CI, tests, refactors, or otherwise not user-facing
29
+ - Start each bullet with a capital letter
30
+ - Prefer what changed for users over what code changed internally
31
+ - Do not copy raw commit prefixes like `fix:` or `feat:` or trailing PR numbers like `(#123)`
32
+ - Community attribution is deterministic: only preserve an existing `(@username)` suffix from the changelog input
33
+ - If an input bullet has no `(@username)` suffix, do not add one
34
+ - Never add a new `(@username)` suffix from `git show`, commit authors, names, or email addresses
35
+ - If no notable entries remain and there is no contributor block, write exactly `No notable changes.`
36
+ - If no notable entries remain but there is a contributor block, omit all release sections and return only the contributor block
37
+ - If the input contains `## Community Contributors Input`, append the block below that heading to the end of the final file verbatim
38
+ - Do not add, remove, rewrite, or reorder contributor names or commit titles in that block
39
+ - Do not derive the thank-you section from the main summary bullets
40
+ - Do not include the heading `## Community Contributors Input` in the final file
41
+ - Focus on writing the least words to get your point across - users will skim read the changelog, so we should be precise
42
+
43
+ **Importantly, the changelog is for users (who are at least slightly technical), they may use the TUI, Desktop, SDK, Plugins and so forth. Be thorough in understanding flow on effects may not be immediately apparent. e.g. a package upgrade looks internal but may patch a bug. Or a refactor may also stabilise some race condition that fixes bugs for users. The PR title/body + commit message will give you the authors context, usually containing the outcome not just technical detail**
44
+
45
+ <changelog_input>
46
+
47
+ !`bun script/raw-changelog.ts $ARGUMENTS`
48
+
49
+ </changelog_input>
.opencode/command/commit.md ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: git commit and push
3
+ model: opencode/kimi-k2.5
4
+ subtask: true
5
+ ---
6
+
7
+ commit and push
8
+
9
+ make sure it includes a prefix like
10
+ docs:
11
+ tui:
12
+ core:
13
+ ci:
14
+ ignore:
15
+ wip:
16
+
17
+ For anything in the packages/web use the docs: prefix.
18
+
19
+ prefer to explain WHY something was done from an end user perspective instead of
20
+ WHAT was done.
21
+
22
+ do not do generic messages like "improved agent experience" be very specific
23
+ about what user facing changes were made
24
+
25
+ if there are conflicts DO NOT FIX THEM. notify me and I will fix them
26
+
27
+ ## GIT DIFF
28
+
29
+ !`git diff`
30
+
31
+ ## GIT DIFF --cached
32
+
33
+ !`git diff --cached`
34
+
35
+ ## GIT STATUS --short
36
+
37
+ !`git status --short`
.opencode/command/issues.md ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: "find issue(s) on github"
3
+ model: opencode/claude-haiku-4-5
4
+ ---
5
+
6
+ Search through existing issues in anomalyco/opencode using the gh cli to find issues matching this query:
7
+
8
+ $ARGUMENTS
9
+
10
+ Consider:
11
+
12
+ 1. Similar titles or descriptions
13
+ 2. Same error messages or symptoms
14
+ 3. Related functionality or components
15
+ 4. Similar feature requests
16
+
17
+ Please list any matching issues with:
18
+
19
+ - Issue number and title
20
+ - Brief explanation of why it matches the query
21
+ - Link to the issue
22
+
23
+ If no clear matches are found, say so.
.opencode/command/learn.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: Extract non-obvious learnings from session to AGENTS.md files to build codebase understanding
3
+ ---
4
+
5
+ Analyze this session and extract non-obvious learnings to add to AGENTS.md files.
6
+
7
+ 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:
8
+
9
+ - Project-wide learnings → root AGENTS.md
10
+ - Package/module-specific → packages/foo/AGENTS.md
11
+ - Feature-specific → src/auth/AGENTS.md
12
+
13
+ What counts as a learning (non-obvious discoveries only):
14
+
15
+ - Hidden relationships between files or modules
16
+ - Execution paths that differ from how code appears
17
+ - Non-obvious configuration, env vars, or flags
18
+ - Debugging breakthroughs when error messages were misleading
19
+ - API/tool quirks and workarounds
20
+ - Build/test commands not in README
21
+ - Architectural decisions and constraints
22
+ - Files that must change together
23
+
24
+ What NOT to include:
25
+
26
+ - Obvious facts from documentation
27
+ - Standard language/framework behavior
28
+ - Things already in an AGENTS.md
29
+ - Verbose explanations
30
+ - Session-specific details
31
+
32
+ Process:
33
+
34
+ 1. Review session for discoveries, errors that took multiple attempts, unexpected connections
35
+ 2. Determine scope - what directory does each learning apply to?
36
+ 3. Read existing AGENTS.md files at relevant levels
37
+ 4. Create or update AGENTS.md at the appropriate level
38
+ 5. Keep entries to 1-3 lines per insight
39
+
40
+ After updating, summarize which AGENTS.md files were created/updated and how many learnings per file.
41
+
42
+ $ARGUMENTS
.opencode/command/rmslop.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: Remove AI code slop
3
+ ---
4
+
5
+ Check the diff against dev, and remove all AI generated slop introduced in this branch.
6
+
7
+ This includes:
8
+
9
+ - Extra comments that a human wouldn't add or is inconsistent with the rest of the file
10
+ - Extra defensive checks or try/catch blocks that are abnormal for that area of the codebase (especially if called by trusted / validated codepaths)
11
+ - Casts to any to get around type issues
12
+ - Any other style that is inconsistent with the file
13
+ - Unnecessary emoji usage
14
+
15
+ Report at the end with only a 1-3 sentence summary of what you changed
.opencode/command/spellcheck.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ ---
2
+ description: spellcheck all markdown file changes
3
+ ---
4
+
5
+ Look at all the unstaged changes to markdown (.md, .mdx) files, pull out the lines that have changed, and check for spelling and grammar errors.
.opencode/command/translate.md ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ description: translate English to other languages
3
+ model: opencode/gpt-5.6-sol
4
+ ---
5
+
6
+ run git diff and translate changed english doc and UI copy files to other international languages. Translate all languages in parallel to save time.
7
+
8
+ Requirements:
9
+
10
+ - Preserve meaning, intent, tone, and formatting (including Markdown/MDX structure).
11
+ - Preserve all technical terms and artifacts exactly: product/company names, API names, identifiers, code, commands/flags, file paths, URLs, versions, error messages, config keys/values, and anything inside inline code or code blocks.
12
+ - Also preserve every term listed in the Do-Not-Translate glossary below.
13
+ - Also apply locale-specific guidance from `.opencode/glossary/<locale>.md` when available (for example, `zh-cn.md`).
14
+ - Do not modify fenced code blocks.
.opencode/glossary/README.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Locale Glossaries
2
+
3
+ Use this folder for locale-specific translation guidance that supplements `.opencode/agent/translator.md`.
4
+
5
+ The global glossary in `translator.md` remains the source of truth for shared do-not-translate terms (commands, code, paths, product names, etc.). These locale files capture community learnings about phrasing and terminology preferences.
6
+
7
+ ## File Naming
8
+
9
+ - One file per locale
10
+ - Use lowercase locale slugs that match docs locales when possible (for example, `zh-cn.md`, `zh-tw.md`)
11
+ - If only language-level guidance exists, use the language code (for example, `fr.md`)
12
+ - Some repo locale slugs may be aliases/non-BCP47 for consistency (for example, `br` for Brazilian Portuguese / `pt-BR`)
13
+
14
+ ## What To Put In A Locale File
15
+
16
+ - **Sources**: PRs/issues/discussions that motivated the guidance
17
+ - **Do Not Translate (Locale Additions)**: locale-specific terms or casing decisions
18
+ - **Preferred Terms**: recurring UI/docs words with preferred translations
19
+ - **Guidance**: tone, style, and consistency notes
20
+ - **Avoid** (optional): common literal translations or wording we should avoid
21
+ - If the repo uses a locale alias slug, document the alias in **Guidance** (for example, prose may mention `pt-BR` while config/examples use `br`)
22
+
23
+ Prefer guidance that is:
24
+
25
+ - Repeated across multiple docs/screens
26
+ - Easy to apply consistently
27
+ - Backed by a community contribution or review discussion
28
+
29
+ ## Template
30
+
31
+ ```md
32
+ # <locale> Glossary
33
+
34
+ ## Sources
35
+
36
+ - PR #12345: https://github.com/anomalyco/opencode/pull/12345
37
+
38
+ ## Do Not Translate (Locale Additions)
39
+
40
+ - `OpenCode` (preserve casing)
41
+
42
+ ## Preferred Terms
43
+
44
+ | English | Preferred | Notes |
45
+ | ------- | --------- | --------- |
46
+ | prompt | ... | preferred |
47
+ | session | ... | preferred |
48
+
49
+ ## Guidance
50
+
51
+ - Prefer natural phrasing over literal translation
52
+
53
+ ## Avoid
54
+
55
+ - Avoid ... when ...
56
+ ```
57
+
58
+ ## Contribution Notes
59
+
60
+ - Mark entries as preferred when they may evolve
61
+ - Keep examples short
62
+ - Add or update the `Sources` section whenever you add a new rule
63
+ - Prefer PR-backed guidance over invented term mappings; start with general guidance if no term-level corrections exist yet
.opencode/glossary/ar.md ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ar Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9947: https://github.com/anomalyco/opencode/pull/9947
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Arabic phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+ - For RTL text, treat code, commands, and paths as LTR artifacts and keep their character order unchanged
24
+
25
+ ## Avoid
26
+
27
+ - Avoid translating product and protocol names that are fixed identifiers
28
+ - Avoid mixing multiple Arabic terms for the same recurring UI action once a preferred term is established
.opencode/glossary/br.md ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # br Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #10086: https://github.com/anomalyco/opencode/pull/10086
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Locale code `br` in repo config, code, and paths (repo alias for Brazilian Portuguese)
13
+
14
+ ## Preferred Terms
15
+
16
+ These are PR-backed locale naming preferences and may evolve.
17
+
18
+ | English / Context | Preferred | Notes |
19
+ | ---------------------------------------- | ------------------------------ | ------------------------------------------------------------- |
20
+ | Brazilian Portuguese (prose locale name) | `pt-BR` | Use standard locale naming in prose when helpful |
21
+ | Repo locale slug (code/config) | `br` | PR #10086 uses `br` for consistency/simplicity |
22
+ | Browser locale detection | `pt`, `pt-br`, `pt-BR` -> `br` | Preserve this mapping in docs/examples about locale detection |
23
+
24
+ ## Guidance
25
+
26
+ - This file covers Brazilian Portuguese (`pt-BR`), but the repo locale code is `br`
27
+ - Use natural Brazilian Portuguese phrasing over literal translation
28
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
29
+ - Keep repo locale identifiers as implemented in code/config (`br`) even when prose mentions `pt-BR`
30
+
31
+ ## Avoid
32
+
33
+ - Avoid changing repo locale code references from `br` to `pt-br` in code snippets, paths, or config examples
34
+ - Avoid mixing Portuguese variants when a Brazilian Portuguese form is established
.opencode/glossary/bs.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # bs Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #12283: https://github.com/anomalyco/opencode/pull/12283
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ These are PR-backed locale naming preferences and may evolve.
17
+
18
+ | English / Context | Preferred | Notes |
19
+ | ---------------------------------- | ---------- | ------------------------------------------------- |
20
+ | Bosnian language label (UI) | `Bosanski` | PR #12283 tested switching language to `Bosanski` |
21
+ | Repo locale slug (code/config) | `bs` | Preserve in code, config, paths, and examples |
22
+ | Browser locale detection (Bosnian) | `bs` | PR #12283 added `bs` locale auto-detection |
23
+
24
+ ## Guidance
25
+
26
+ - Use natural Bosnian phrasing over literal translation
27
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
28
+ - Keep repo locale references as `bs` in code/config, and use `Bosanski` for the user-facing language name when applicable
29
+
30
+ ## Avoid
31
+
32
+ - Avoid changing repo locale references from `bs` to another slug in code snippets or config examples
33
+ - Avoid translating product and protocol names that are fixed identifiers
.opencode/glossary/da.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # da Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9821: https://github.com/anomalyco/opencode/pull/9821
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Danish phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple Danish terms for the same recurring UI action once a preferred term is established
.opencode/glossary/de.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # de Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9817: https://github.com/anomalyco/opencode/pull/9817
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural German phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple German terms for the same recurring UI action once a preferred term is established
.opencode/glossary/es.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # es Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9817: https://github.com/anomalyco/opencode/pull/9817
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Spanish phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple Spanish terms for the same recurring UI action once a preferred term is established
.opencode/glossary/fr.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # fr Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9821: https://github.com/anomalyco/opencode/pull/9821
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural French phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple French terms for the same recurring UI action once a preferred term is established
.opencode/glossary/ja.md ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ja Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9821: https://github.com/anomalyco/opencode/pull/9821
6
+ - PR #13160: https://github.com/anomalyco/opencode/pull/13160
7
+
8
+ ## Do Not Translate (Locale Additions)
9
+
10
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
11
+ - `OpenCode CLI`
12
+ - `CLI`, `TUI`, `MCP`, `OAuth`
13
+ - Commands, flags, file paths, and code literals (keep exactly as written)
14
+
15
+ ## Preferred Terms
16
+
17
+ These are PR-backed wording preferences and may evolve.
18
+
19
+ | English / Context | Preferred | Notes |
20
+ | --------------------------- | ----------------------- | ------------------------------------- |
21
+ | WSL integration (UI label) | `WSL連携` | PR #13160 prefers this over `WSL統合` |
22
+ | WSL integration description | `WindowsのWSL環境で...` | PR #13160 improved phrasing naturally |
23
+
24
+ ## Guidance
25
+
26
+ - Prefer natural Japanese phrasing over literal translation
27
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
28
+ - In WSL integration text, follow PR #13160 wording direction for more natural Japanese phrasing
29
+
30
+ ## Avoid
31
+
32
+ - Avoid `WSL統合` in the WSL integration UI context where `WSL連携` is the reviewed wording
33
+ - Avoid translating product and protocol names that are fixed identifiers
.opencode/glossary/ko.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ko Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9817: https://github.com/anomalyco/opencode/pull/9817
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Korean phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple Korean terms for the same recurring UI action once a preferred term is established
.opencode/glossary/no.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # no Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #10018: https://github.com/anomalyco/opencode/pull/10018
6
+ - PR #12935: https://github.com/anomalyco/opencode/pull/12935
7
+
8
+ ## Do Not Translate (Locale Additions)
9
+
10
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
11
+ - `OpenCode CLI`
12
+ - `CLI`, `TUI`, `MCP`, `OAuth`
13
+ - Sound names (PR #10018 notes these were intentionally left untranslated)
14
+
15
+ ## Preferred Terms
16
+
17
+ These are PR-backed corrections and may evolve.
18
+
19
+ | English / Context | Preferred | Notes |
20
+ | ----------------------------------- | ------------ | ----------------------------- |
21
+ | Save (data persistence action) | `Lagre` | Prefer over `Spare` |
22
+ | Disabled (feature/state) | `deaktivert` | Prefer over `funksjonshemmet` |
23
+ | API keys | `API Nøkler` | Prefer over `API Taster` |
24
+ | Cost (noun) | `Kostnad` | Prefer over verb form `Koste` |
25
+ | Show/View (imperative button label) | `Vis` | Prefer over `Utsikt` |
26
+
27
+ ## Guidance
28
+
29
+ - Prefer natural Norwegian Bokmal (Bokmål) wording over literal translation
30
+ - Keep tone clear and practical in UI labels
31
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
32
+ - Keep recurring UI terms consistent once a preferred term is chosen
33
+
34
+ ## Avoid
35
+
36
+ - Avoid `Spare` for save actions in persistence contexts
37
+ - Avoid `funksjonshemmet` for disabled feature states
38
+ - Avoid `API Taster`, `Koste`, and `Utsikt` in the corrected contexts above
.opencode/glossary/pl.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pl Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9884: https://github.com/anomalyco/opencode/pull/9884
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Polish phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple Polish terms for the same recurring UI action once a preferred term is established
.opencode/glossary/ru.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ru Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #9882: https://github.com/anomalyco/opencode/pull/9882
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
10
+ - `OpenCode CLI`
11
+ - `CLI`, `TUI`, `MCP`, `OAuth`
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ No PR-backed term mappings yet. Add entries here when review PRs introduce repeated wording corrections.
17
+
18
+ ## Guidance
19
+
20
+ - Prefer natural Russian phrasing over literal translation
21
+ - Keep tone clear and direct in UI labels and docs prose
22
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
23
+
24
+ ## Avoid
25
+
26
+ - Avoid translating product and protocol names that are fixed identifiers
27
+ - Avoid mixing multiple Russian terms for the same recurring UI action once a preferred term is established
.opencode/glossary/th.md ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # th Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #10809: https://github.com/anomalyco/opencode/pull/10809
6
+ - PR #11496: https://github.com/anomalyco/opencode/pull/11496
7
+
8
+ ## Do Not Translate (Locale Additions)
9
+
10
+ - `OpenCode` (preserve casing in prose; keep `opencode` only in commands, package names, paths, or code)
11
+ - `OpenCode CLI`
12
+ - `CLI`, `TUI`, `MCP`, `OAuth`
13
+ - Commands, flags, file paths, and code literals (keep exactly as written)
14
+
15
+ ## Preferred Terms
16
+
17
+ These are PR-backed preferences and may evolve.
18
+
19
+ | English / Context | Preferred | Notes |
20
+ | ------------------------------------- | --------------------- | -------------------------------------------------------------------------------- |
21
+ | Thai language label in language lists | `ไทย` | PR #10809 standardized this across locales |
22
+ | Language names in language pickers | Native names (static) | PR #11496: keep names like `English`, `Deutsch`, `ไทย` consistent across locales |
23
+
24
+ ## Guidance
25
+
26
+ - Prefer natural Thai phrasing over literal translation
27
+ - Keep tone short and clear for buttons and labels
28
+ - Preserve technical artifacts exactly: commands, flags, code, URLs, model IDs, and file paths
29
+ - Keep language names static/native in language pickers instead of translating them per current locale (PR #11496)
30
+
31
+ ## Avoid
32
+
33
+ - Avoid translating language names differently per current locale in language lists
34
+ - Avoid changing `ไทย` to another display form for the Thai language option unless the product standard changes
.opencode/glossary/tr.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # tr Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #15835: https://github.com/anomalyco/opencode/pull/15835
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose, docs, and UI copy)
10
+ - Keep lowercase `opencode` in commands, package names, paths, URLs, and other exact identifiers
11
+ - `<TAB>` stays the literal key token in code blocks; use `Tab` for the nearby explanatory label in prose
12
+ - Commands, flags, file paths, and code literals (keep exactly as written)
13
+
14
+ ## Preferred Terms
15
+
16
+ These are PR-backed wording preferences and may evolve.
17
+
18
+ | English / Context | Preferred | Notes |
19
+ | ------------------------- | --------------------------------------- | ------------------------------------------------------------- |
20
+ | available in beta | `beta olarak mevcut` | Prefer this over `beta olarak kullanılabilir` |
21
+ | privacy-first | `Gizlilik öncelikli tasarlandı` | Prefer this over `Önce gizlilik için tasarlandı` |
22
+ | connect your local models | `yerel modellerinizi bağlayabilirsiniz` | Use the fuller, more direct action phrase |
23
+ | `<TAB>` key label | `Tab` | Use `Tab` in prose; keep `<TAB>` in literal UI or code blocks |
24
+ | cross-platform | `cross-platform (tüm platformlarda)` | Keep the English term, add a short clarification when helpful |
25
+
26
+ ## Guidance
27
+
28
+ - Prefer natural Turkish phrasing over literal translation
29
+ - Merge broken sentence fragments into one clear sentence when the source is a single thought
30
+ - Keep product naming consistent: `OpenCode` in prose, `opencode` only for exact technical identifiers
31
+ - When an English technical term is intentionally kept, add a short Turkish clarification only if it improves readability
32
+
33
+ ## Avoid
34
+
35
+ - Avoid `beta olarak kullanılabilir` when `beta olarak mevcut` fits
36
+ - Avoid `Önce gizlilik için tasarlandı`; use the more natural reviewed wording instead
37
+ - Avoid `Sekme` for the translated key label in prose when referring to `<TAB>`
38
+ - Avoid changing `opencode` to `OpenCode` inside commands, URLs, package names, or code literals
.opencode/glossary/zh-cn.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # zh-cn Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #13942: https://github.com/anomalyco/opencode/pull/13942
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only when it is part of commands, package names, paths, or code)
10
+ - `OpenCode Zen`
11
+ - `OpenCode CLI`
12
+ - `CLI`, `TUI`, `MCP`, `OAuth`
13
+ - `Model Context Protocol` (prefer the English expansion when introducing `MCP`)
14
+
15
+ ## Preferred Terms
16
+
17
+ These are preferred terms for docs/UI prose and may evolve.
18
+
19
+ | English | Preferred | Notes |
20
+ | ----------------------- | --------- | ------------------------------------------- |
21
+ | prompt | 提示词 | Keep `--prompt` unchanged in flags/code |
22
+ | session | 会话 | |
23
+ | provider | 提供商 | |
24
+ | share link / shared URL | 分享链接 | Prefer `分享` for user-facing share actions |
25
+ | headless (server) | 无界面 | Docs wording |
26
+ | authentication | 认证 | Prefer in auth/OAuth contexts |
27
+ | cache | 缓存 | |
28
+ | keybind / shortcut | 快捷键 | User-facing docs wording |
29
+ | workflow | 工作流 | e.g. GitHub Actions workflow |
30
+
31
+ ## Guidance
32
+
33
+ - Prefer natural, concise phrasing over literal translation
34
+ - Keep the tone direct and friendly (PR #13942 consistently moved wording in this direction)
35
+ - Preserve technical artifacts exactly: commands, flags, code, inline code, URLs, file paths, model IDs
36
+ - Keep enum-like values in English when they are literals (for example, `default`, `json`)
37
+ - Prefer consistent terminology across pages once a term is chosen (`会话`, `提供商`, `提示词`, etc.)
38
+
39
+ ## Avoid
40
+
41
+ - Avoid `opencode` in prose when referring to the product name; use `OpenCode`
42
+ - Avoid mixing alternative terms for the same concept across docs when a preferred term is already established
.opencode/glossary/zh-tw.md ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # zh-tw Glossary
2
+
3
+ ## Sources
4
+
5
+ - PR #13942: https://github.com/anomalyco/opencode/pull/13942
6
+
7
+ ## Do Not Translate (Locale Additions)
8
+
9
+ - `OpenCode` (preserve casing in prose; keep `opencode` only when it is part of commands, package names, paths, or code)
10
+ - `OpenCode Zen`
11
+ - `OpenCode CLI`
12
+ - `CLI`, `TUI`, `MCP`, `OAuth`
13
+ - `Model Context Protocol` (prefer the English expansion when introducing `MCP`)
14
+
15
+ ## Preferred Terms
16
+
17
+ These are preferred terms for docs/UI prose and may evolve.
18
+
19
+ | English | Preferred | Notes |
20
+ | ----------------------- | --------- | ------------------------------------------- |
21
+ | prompt | 提示詞 | Keep `--prompt` unchanged in flags/code |
22
+ | session | 工作階段 | |
23
+ | provider | 供應商 | |
24
+ | share link / shared URL | 分享連結 | Prefer `分享` for user-facing share actions |
25
+ | headless (server) | 無介面 | Docs wording |
26
+ | authentication | 認證 | Prefer in auth/OAuth contexts |
27
+ | cache | 快取 | |
28
+ | keybind / shortcut | 快捷鍵 | User-facing docs wording |
29
+ | workflow | 工作流程 | e.g. GitHub Actions workflow |
30
+
31
+ ## Guidance
32
+
33
+ - Prefer natural, concise phrasing over literal translation
34
+ - Keep the tone direct and friendly (PR #13942 consistently moved wording in this direction)
35
+ - Preserve technical artifacts exactly: commands, flags, code, inline code, URLs, file paths, model IDs
36
+ - Keep enum-like values in English when they are literals (for example, `default`, `json`)
37
+ - Prefer consistent terminology across pages once a term is chosen (`工作階段`, `供應商`, `提示詞`, etc.)
38
+
39
+ ## Avoid
40
+
41
+ - Avoid `opencode` in prose when referring to the product name; use `OpenCode`
42
+ - Avoid mixing alternative terms for the same concept across docs when a preferred term is already established
.opencode/plugins/smoke-theme.json ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://opencode.ai/theme.json",
3
+ "defs": {
4
+ "nord0": "#2E3440",
5
+ "nord1": "#3B4252",
6
+ "nord2": "#434C5E",
7
+ "nord3": "#4C566A",
8
+ "nord4": "#D8DEE9",
9
+ "nord5": "#E5E9F0",
10
+ "nord6": "#ECEFF4",
11
+ "nord7": "#8FBCBB",
12
+ "nord8": "#88C0D0",
13
+ "nord9": "#81A1C1",
14
+ "nord10": "#5E81AC",
15
+ "nord11": "#BF616A",
16
+ "nord12": "#D08770",
17
+ "nord13": "#EBCB8B",
18
+ "nord14": "#A3BE8C",
19
+ "nord15": "#B48EAD"
20
+ },
21
+ "theme": {
22
+ "primary": {
23
+ "dark": "nord10",
24
+ "light": "nord9"
25
+ },
26
+ "secondary": {
27
+ "dark": "nord9",
28
+ "light": "nord9"
29
+ },
30
+ "accent": {
31
+ "dark": "nord7",
32
+ "light": "nord7"
33
+ },
34
+ "error": {
35
+ "dark": "nord11",
36
+ "light": "nord11"
37
+ },
38
+ "warning": {
39
+ "dark": "nord12",
40
+ "light": "nord12"
41
+ },
42
+ "success": {
43
+ "dark": "nord14",
44
+ "light": "nord14"
45
+ },
46
+ "info": {
47
+ "dark": "nord8",
48
+ "light": "nord10"
49
+ },
50
+ "text": {
51
+ "dark": "nord6",
52
+ "light": "nord0"
53
+ },
54
+ "textMuted": {
55
+ "dark": "#8B95A7",
56
+ "light": "nord1"
57
+ },
58
+ "background": {
59
+ "dark": "nord0",
60
+ "light": "nord6"
61
+ },
62
+ "backgroundPanel": {
63
+ "dark": "nord1",
64
+ "light": "nord5"
65
+ },
66
+ "backgroundElement": {
67
+ "dark": "nord2",
68
+ "light": "nord4"
69
+ },
70
+ "border": {
71
+ "dark": "nord2",
72
+ "light": "nord3"
73
+ },
74
+ "borderActive": {
75
+ "dark": "nord3",
76
+ "light": "nord2"
77
+ },
78
+ "borderSubtle": {
79
+ "dark": "nord2",
80
+ "light": "nord3"
81
+ },
82
+ "diffAdded": {
83
+ "dark": "nord14",
84
+ "light": "nord14"
85
+ },
86
+ "diffRemoved": {
87
+ "dark": "nord11",
88
+ "light": "nord11"
89
+ },
90
+ "diffContext": {
91
+ "dark": "#8B95A7",
92
+ "light": "nord3"
93
+ },
94
+ "diffHunkHeader": {
95
+ "dark": "#8B95A7",
96
+ "light": "nord3"
97
+ },
98
+ "diffHighlightAdded": {
99
+ "dark": "nord14",
100
+ "light": "nord14"
101
+ },
102
+ "diffHighlightRemoved": {
103
+ "dark": "nord11",
104
+ "light": "nord11"
105
+ },
106
+ "diffAddedBg": {
107
+ "dark": "#36413C",
108
+ "light": "#E6EBE7"
109
+ },
110
+ "diffRemovedBg": {
111
+ "dark": "#43393D",
112
+ "light": "#ECE6E8"
113
+ },
114
+ "diffContextBg": {
115
+ "dark": "nord1",
116
+ "light": "nord5"
117
+ },
118
+ "diffLineNumber": {
119
+ "dark": "nord2",
120
+ "light": "nord4"
121
+ },
122
+ "diffAddedLineNumberBg": {
123
+ "dark": "#303A35",
124
+ "light": "#DDE4DF"
125
+ },
126
+ "diffRemovedLineNumberBg": {
127
+ "dark": "#3C3336",
128
+ "light": "#E4DDE0"
129
+ },
130
+ "markdownText": {
131
+ "dark": "nord4",
132
+ "light": "nord0"
133
+ },
134
+ "markdownHeading": {
135
+ "dark": "nord8",
136
+ "light": "nord10"
137
+ },
138
+ "markdownLink": {
139
+ "dark": "nord9",
140
+ "light": "nord9"
141
+ },
142
+ "markdownLinkText": {
143
+ "dark": "nord7",
144
+ "light": "nord7"
145
+ },
146
+ "markdownCode": {
147
+ "dark": "nord14",
148
+ "light": "nord14"
149
+ },
150
+ "markdownBlockQuote": {
151
+ "dark": "#8B95A7",
152
+ "light": "nord3"
153
+ },
154
+ "markdownEmph": {
155
+ "dark": "nord12",
156
+ "light": "nord12"
157
+ },
158
+ "markdownStrong": {
159
+ "dark": "nord13",
160
+ "light": "nord13"
161
+ },
162
+ "markdownHorizontalRule": {
163
+ "dark": "#8B95A7",
164
+ "light": "nord3"
165
+ },
166
+ "markdownListItem": {
167
+ "dark": "nord8",
168
+ "light": "nord10"
169
+ },
170
+ "markdownListEnumeration": {
171
+ "dark": "nord7",
172
+ "light": "nord7"
173
+ },
174
+ "markdownImage": {
175
+ "dark": "nord9",
176
+ "light": "nord9"
177
+ },
178
+ "markdownImageText": {
179
+ "dark": "nord7",
180
+ "light": "nord7"
181
+ },
182
+ "markdownCodeBlock": {
183
+ "dark": "nord4",
184
+ "light": "nord0"
185
+ },
186
+ "syntaxComment": {
187
+ "dark": "#8B95A7",
188
+ "light": "nord3"
189
+ },
190
+ "syntaxKeyword": {
191
+ "dark": "nord9",
192
+ "light": "nord9"
193
+ },
194
+ "syntaxFunction": {
195
+ "dark": "nord8",
196
+ "light": "nord8"
197
+ },
198
+ "syntaxVariable": {
199
+ "dark": "nord7",
200
+ "light": "nord7"
201
+ },
202
+ "syntaxString": {
203
+ "dark": "nord14",
204
+ "light": "nord14"
205
+ },
206
+ "syntaxNumber": {
207
+ "dark": "nord15",
208
+ "light": "nord15"
209
+ },
210
+ "syntaxType": {
211
+ "dark": "nord7",
212
+ "light": "nord7"
213
+ },
214
+ "syntaxOperator": {
215
+ "dark": "nord9",
216
+ "light": "nord9"
217
+ },
218
+ "syntaxPunctuation": {
219
+ "dark": "nord4",
220
+ "light": "nord0"
221
+ }
222
+ }
223
+ }
.opencode/plugins/tui-smoke.tsx ADDED
@@ -0,0 +1,1019 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /** @jsxImportSource @opentui/solid */
2
+ import { useTerminalDimensions, type JSX } from "@opentui/solid"
3
+ import { useBindings, useKeymapSelector } from "@opentui/keymap/solid"
4
+ import { RGBA, VignetteEffect, type KeyEvent, type Renderable } from "@opentui/core"
5
+ import { createBindingLookup, type BindingConfig } from "@opentui/keymap/extras"
6
+ import type { TuiPlugin, TuiPluginApi, TuiPluginMeta, TuiPluginModule, TuiSlotPlugin } from "@opencode-ai/plugin/tui"
7
+
8
+ const tabs = ["overview", "counter", "help"]
9
+ const command = {
10
+ modal: "smoke_modal",
11
+ screen: "smoke_screen",
12
+ alert: "smoke_alert",
13
+ confirm: "smoke_confirm",
14
+ prompt: "smoke_prompt",
15
+ select: "smoke_select",
16
+ host: "smoke_host",
17
+ home: "smoke_home",
18
+ toast: "smoke_toast",
19
+ dialog_close: "smoke_dialog_close",
20
+ local_push: "smoke_local_push",
21
+ local_pop: "smoke_local_pop",
22
+ screen_home: "smoke_screen_home",
23
+ screen_left: "smoke_screen_left",
24
+ screen_right: "smoke_screen_right",
25
+ screen_up: "smoke_screen_up",
26
+ screen_down: "smoke_screen_down",
27
+ screen_modal: "smoke_screen_modal",
28
+ screen_local: "smoke_screen_local",
29
+ screen_host: "smoke_screen_host",
30
+ screen_alert: "smoke_screen_alert",
31
+ screen_confirm: "smoke_screen_confirm",
32
+ screen_prompt: "smoke_screen_prompt",
33
+ screen_select: "smoke_screen_select",
34
+ modal_accept: "smoke_modal_accept",
35
+ modal_close: "smoke_modal_close",
36
+ }
37
+
38
+ type SmokeBindings = BindingConfig<Renderable, KeyEvent>
39
+
40
+ const defaultKeymap = {
41
+ [command.modal]: "ctrl+shift+m",
42
+ [command.screen]: "ctrl+shift+o",
43
+ [command.dialog_close]: "escape",
44
+ [command.local_push]: "enter,return",
45
+ [command.local_pop]: "escape,q,backspace",
46
+ [command.screen_home]: "escape,ctrl+h",
47
+ [command.screen_left]: "left,h",
48
+ [command.screen_right]: "right,l",
49
+ [command.screen_up]: "up,k",
50
+ [command.screen_down]: "down,j",
51
+ [command.screen_modal]: "ctrl+shift+m",
52
+ [command.screen_local]: "x",
53
+ [command.screen_host]: "z",
54
+ [command.screen_alert]: "a",
55
+ [command.screen_confirm]: "c",
56
+ [command.screen_prompt]: "p",
57
+ [command.screen_select]: "s",
58
+ [command.modal_accept]: "enter,return",
59
+ [command.modal_close]: "escape",
60
+ }
61
+
62
+ const pick = (value: unknown, fallback: string) => {
63
+ if (typeof value !== "string") return fallback
64
+ if (!value.trim()) return fallback
65
+ return value
66
+ }
67
+
68
+ const num = (value: unknown, fallback: number) => {
69
+ if (typeof value !== "number") return fallback
70
+ return value
71
+ }
72
+
73
+ const record = (value: unknown): value is Record<string, unknown> =>
74
+ !!value && typeof value === "object" && !Array.isArray(value)
75
+
76
+ type Cfg = {
77
+ label: string
78
+ route: string
79
+ vignette: number
80
+ keybinds: SmokeBindings | undefined
81
+ }
82
+
83
+ type Route = {
84
+ modal: string
85
+ screen: string
86
+ }
87
+
88
+ type State = {
89
+ tab: number
90
+ count: number
91
+ source: string
92
+ note: string
93
+ selected: string
94
+ local: number
95
+ }
96
+
97
+ const cfg = (options: Record<string, unknown> | undefined) => {
98
+ return {
99
+ label: pick(options?.label, "smoke"),
100
+ route: pick(options?.route, "workspace-smoke"),
101
+ vignette: Math.max(0, num(options?.vignette, 0.35)),
102
+ keybinds: record(options?.keybinds) ? (options.keybinds as SmokeBindings) : undefined,
103
+ }
104
+ }
105
+
106
+ const names = (input: Cfg) => {
107
+ return {
108
+ modal: `${input.route}.modal`,
109
+ screen: `${input.route}.screen`,
110
+ }
111
+ }
112
+
113
+ function createKeys(input: SmokeBindings | undefined) {
114
+ return createBindingLookup({ ...defaultKeymap, ...input })
115
+ }
116
+
117
+ type Keys = ReturnType<typeof createKeys>
118
+
119
+ const ui = {
120
+ panel: "#1d1d1d",
121
+ border: "#4a4a4a",
122
+ text: "#f0f0f0",
123
+ muted: "#a5a5a5",
124
+ accent: "#5f87ff",
125
+ }
126
+
127
+ type Color = RGBA | string
128
+
129
+ const ink = (map: Record<string, unknown>, name: string, fallback: string): Color => {
130
+ const value = map[name]
131
+ if (typeof value === "string") return value
132
+ if (value instanceof RGBA) return value
133
+ return fallback
134
+ }
135
+
136
+ const look = (map: Record<string, unknown>) => {
137
+ return {
138
+ panel: ink(map, "backgroundPanel", ui.panel),
139
+ border: ink(map, "border", ui.border),
140
+ text: ink(map, "text", ui.text),
141
+ muted: ink(map, "textMuted", ui.muted),
142
+ accent: ink(map, "primary", ui.accent),
143
+ selected: ink(map, "selectedListItemText", ui.text),
144
+ }
145
+ }
146
+
147
+ const tone = (api: TuiPluginApi) => {
148
+ return look(api.theme.current)
149
+ }
150
+
151
+ type Skin = {
152
+ panel: Color
153
+ border: Color
154
+ text: Color
155
+ muted: Color
156
+ accent: Color
157
+ selected: Color
158
+ }
159
+
160
+ const Btn = (props: { txt: string; run: () => void; skin: Skin; on?: boolean }) => {
161
+ return (
162
+ <box
163
+ onMouseUp={() => {
164
+ props.run()
165
+ }}
166
+ backgroundColor={props.on ? props.skin.accent : props.skin.border}
167
+ paddingLeft={1}
168
+ paddingRight={1}
169
+ >
170
+ <text fg={props.on ? props.skin.selected : props.skin.text}>{props.txt}</text>
171
+ </box>
172
+ )
173
+ }
174
+
175
+ const parse = (params: Record<string, unknown> | undefined) => {
176
+ const tab = typeof params?.tab === "number" ? params.tab : 0
177
+ const count = typeof params?.count === "number" ? params.count : 0
178
+ const source = typeof params?.source === "string" ? params.source : "unknown"
179
+ const note = typeof params?.note === "string" ? params.note : ""
180
+ const selected = typeof params?.selected === "string" ? params.selected : ""
181
+ const local = typeof params?.local === "number" ? params.local : 0
182
+ return {
183
+ tab: Math.max(0, Math.min(tab, tabs.length - 1)),
184
+ count,
185
+ source,
186
+ note,
187
+ selected,
188
+ local: Math.max(0, local),
189
+ }
190
+ }
191
+
192
+ const current = (api: TuiPluginApi, route: Route) => {
193
+ const value = api.route.current
194
+ const ok = Object.values(route).includes(value.name)
195
+ if (!ok) return parse(undefined)
196
+ if (!("params" in value)) return parse(undefined)
197
+ return parse(value.params)
198
+ }
199
+
200
+ const opts = [
201
+ {
202
+ title: "Overview",
203
+ value: 0,
204
+ description: "Switch to overview tab",
205
+ },
206
+ {
207
+ title: "Counter",
208
+ value: 1,
209
+ description: "Switch to counter tab",
210
+ },
211
+ {
212
+ title: "Help",
213
+ value: 2,
214
+ description: "Switch to help tab",
215
+ },
216
+ ]
217
+
218
+ const host = (api: TuiPluginApi, input: Cfg, skin: Skin) => {
219
+ api.ui.dialog.setSize("medium")
220
+ api.ui.dialog.replace(() => (
221
+ <box paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1} flexDirection="column">
222
+ <text fg={skin.text}>
223
+ <b>{input.label} host overlay</b>
224
+ </text>
225
+ <text fg={skin.muted}>Using api.ui.dialog stack with built-in backdrop</text>
226
+ <text fg={skin.muted}>esc closes · depth {api.ui.dialog.depth}</text>
227
+ <box flexDirection="row" gap={1}>
228
+ <Btn txt="close" run={() => api.ui.dialog.clear()} skin={skin} on />
229
+ </box>
230
+ </box>
231
+ ))
232
+ }
233
+
234
+ const warn = (api: TuiPluginApi, route: Route, value: State) => {
235
+ const DialogAlert = api.ui.DialogAlert
236
+ api.ui.dialog.setSize("medium")
237
+ api.ui.dialog.replace(() => (
238
+ <DialogAlert
239
+ title="Smoke alert"
240
+ message="Testing built-in alert dialog"
241
+ onConfirm={() => api.route.navigate(route.screen, { ...value, source: "alert" })}
242
+ />
243
+ ))
244
+ }
245
+
246
+ const check = (api: TuiPluginApi, route: Route, value: State) => {
247
+ const DialogConfirm = api.ui.DialogConfirm
248
+ api.ui.dialog.setSize("medium")
249
+ api.ui.dialog.replace(() => (
250
+ <DialogConfirm
251
+ title="Smoke confirm"
252
+ message="Apply +1 to counter?"
253
+ onConfirm={() => api.route.navigate(route.screen, { ...value, count: value.count + 1, source: "confirm" })}
254
+ onCancel={() => api.route.navigate(route.screen, { ...value, source: "confirm-cancel" })}
255
+ />
256
+ ))
257
+ }
258
+
259
+ const entry = (api: TuiPluginApi, route: Route, value: State) => {
260
+ const DialogPrompt = api.ui.DialogPrompt
261
+ api.ui.dialog.setSize("medium")
262
+ api.ui.dialog.replace(() => (
263
+ <DialogPrompt
264
+ title="Smoke prompt"
265
+ value={value.note}
266
+ onConfirm={(note) => {
267
+ api.ui.dialog.clear()
268
+ api.route.navigate(route.screen, { ...value, note, source: "prompt" })
269
+ }}
270
+ onCancel={() => {
271
+ api.ui.dialog.clear()
272
+ api.route.navigate(route.screen, value)
273
+ }}
274
+ />
275
+ ))
276
+ }
277
+
278
+ const picker = (api: TuiPluginApi, route: Route, value: State) => {
279
+ const DialogSelect = api.ui.DialogSelect
280
+ api.ui.dialog.setSize("medium")
281
+ api.ui.dialog.replace(() => (
282
+ <DialogSelect
283
+ title="Smoke select"
284
+ options={opts}
285
+ current={value.tab}
286
+ onSelect={(item) => {
287
+ api.ui.dialog.clear()
288
+ api.route.navigate(route.screen, {
289
+ ...value,
290
+ tab: typeof item.value === "number" ? item.value : value.tab,
291
+ selected: item.title,
292
+ source: "select",
293
+ })
294
+ }}
295
+ />
296
+ ))
297
+ }
298
+
299
+ const Screen = (props: {
300
+ api: TuiPluginApi
301
+ input: Cfg
302
+ route: Route
303
+ keys: Keys
304
+ meta: TuiPluginMeta
305
+ params?: Record<string, unknown>
306
+ }) => {
307
+ const dim = useTerminalDimensions()
308
+ const value = parse(props.params)
309
+ const skin = tone(props.api)
310
+ const set = (local: number, base?: State) => {
311
+ const next = base ?? current(props.api, props.route)
312
+ props.api.route.navigate(props.route.screen, { ...next, local: Math.max(0, local), source: "local" })
313
+ }
314
+ const push = (base?: State) => {
315
+ const next = base ?? current(props.api, props.route)
316
+ set(next.local + 1, next)
317
+ }
318
+ const open = () => {
319
+ const next = current(props.api, props.route)
320
+ if (next.local > 0) return
321
+ set(1, next)
322
+ }
323
+ const pop = (base?: State) => {
324
+ const next = base ?? current(props.api, props.route)
325
+ set(Math.max(0, next.local - 1), next)
326
+ }
327
+ const show = () => {
328
+ setTimeout(() => {
329
+ open()
330
+ }, 0)
331
+ }
332
+ const screenActive = () => props.api.route.current.name === props.route.screen
333
+
334
+ useBindings(() => ({
335
+ enabled: () => screenActive() && props.api.ui.dialog.open,
336
+ commands: [
337
+ {
338
+ name: command.dialog_close,
339
+ run() {
340
+ props.api.ui.dialog.clear()
341
+ },
342
+ },
343
+ ],
344
+ bindings: props.keys.gather("smoke.dialog", [command.dialog_close]),
345
+ }))
346
+
347
+ useBindings(() => ({
348
+ enabled: () => screenActive() && !props.api.ui.dialog.open && current(props.api, props.route).local > 0,
349
+ commands: [
350
+ {
351
+ name: command.local_push,
352
+ run() {
353
+ push(current(props.api, props.route))
354
+ },
355
+ },
356
+ {
357
+ name: command.local_pop,
358
+ run() {
359
+ pop(current(props.api, props.route))
360
+ },
361
+ },
362
+ ],
363
+ bindings: props.keys.gather("smoke.local", [command.local_push, command.local_pop]),
364
+ }))
365
+
366
+ useBindings(() => ({
367
+ enabled: () => screenActive() && !props.api.ui.dialog.open && current(props.api, props.route).local === 0,
368
+ commands: [
369
+ {
370
+ name: command.screen_home,
371
+ run() {
372
+ props.api.route.navigate("home")
373
+ },
374
+ },
375
+ {
376
+ name: command.screen_left,
377
+ run() {
378
+ const next = current(props.api, props.route)
379
+ props.api.route.navigate(props.route.screen, { ...next, tab: (next.tab - 1 + tabs.length) % tabs.length })
380
+ },
381
+ },
382
+ {
383
+ name: command.screen_right,
384
+ run() {
385
+ const next = current(props.api, props.route)
386
+ props.api.route.navigate(props.route.screen, { ...next, tab: (next.tab + 1) % tabs.length })
387
+ },
388
+ },
389
+ {
390
+ name: command.screen_up,
391
+ run() {
392
+ const next = current(props.api, props.route)
393
+ props.api.route.navigate(props.route.screen, { ...next, count: next.count + 1 })
394
+ },
395
+ },
396
+ {
397
+ name: command.screen_down,
398
+ run() {
399
+ const next = current(props.api, props.route)
400
+ props.api.route.navigate(props.route.screen, { ...next, count: next.count - 1 })
401
+ },
402
+ },
403
+ {
404
+ name: command.screen_modal,
405
+ run() {
406
+ props.api.route.navigate(props.route.modal, current(props.api, props.route))
407
+ },
408
+ },
409
+ {
410
+ name: command.screen_local,
411
+ run() {
412
+ open()
413
+ },
414
+ },
415
+ {
416
+ name: command.screen_host,
417
+ run() {
418
+ host(props.api, props.input, skin)
419
+ },
420
+ },
421
+ {
422
+ name: command.screen_alert,
423
+ run() {
424
+ warn(props.api, props.route, current(props.api, props.route))
425
+ },
426
+ },
427
+ {
428
+ name: command.screen_confirm,
429
+ run() {
430
+ check(props.api, props.route, current(props.api, props.route))
431
+ },
432
+ },
433
+ {
434
+ name: command.screen_prompt,
435
+ run() {
436
+ entry(props.api, props.route, current(props.api, props.route))
437
+ },
438
+ },
439
+ {
440
+ name: command.screen_select,
441
+ run() {
442
+ picker(props.api, props.route, current(props.api, props.route))
443
+ },
444
+ },
445
+ ],
446
+ bindings: props.keys.gather("smoke.screen", [
447
+ command.screen_home,
448
+ command.screen_left,
449
+ command.screen_right,
450
+ command.screen_up,
451
+ command.screen_down,
452
+ command.screen_modal,
453
+ command.screen_local,
454
+ command.screen_host,
455
+ command.screen_alert,
456
+ command.screen_confirm,
457
+ command.screen_prompt,
458
+ command.screen_select,
459
+ ]),
460
+ }))
461
+ const shortcuts = useKeymapSelector((keymap) => {
462
+ const bindings = keymap.getCommandBindings({
463
+ visibility: "registered",
464
+ commands: [
465
+ command.screen_home,
466
+ command.screen_up,
467
+ command.screen_down,
468
+ command.screen_modal,
469
+ command.screen_alert,
470
+ command.screen_confirm,
471
+ command.screen_prompt,
472
+ command.screen_select,
473
+ command.screen_local,
474
+ command.screen_host,
475
+ command.local_push,
476
+ command.local_pop,
477
+ ],
478
+ })
479
+
480
+ return {
481
+ screen_home: props.api.keys.formatBindings(bindings.get(command.screen_home)) ?? "",
482
+ screen_up: props.api.keys.formatBindings(bindings.get(command.screen_up)) ?? "",
483
+ screen_down: props.api.keys.formatBindings(bindings.get(command.screen_down)) ?? "",
484
+ screen_modal: props.api.keys.formatBindings(bindings.get(command.screen_modal)) ?? "",
485
+ screen_alert: props.api.keys.formatBindings(bindings.get(command.screen_alert)) ?? "",
486
+ screen_confirm: props.api.keys.formatBindings(bindings.get(command.screen_confirm)) ?? "",
487
+ screen_prompt: props.api.keys.formatBindings(bindings.get(command.screen_prompt)) ?? "",
488
+ screen_select: props.api.keys.formatBindings(bindings.get(command.screen_select)) ?? "",
489
+ screen_local: props.api.keys.formatBindings(bindings.get(command.screen_local)) ?? "",
490
+ screen_host: props.api.keys.formatBindings(bindings.get(command.screen_host)) ?? "",
491
+ local_push: props.api.keys.formatBindings(bindings.get(command.local_push)) ?? "",
492
+ local_pop: props.api.keys.formatBindings(bindings.get(command.local_pop)) ?? "",
493
+ }
494
+ })
495
+
496
+ return (
497
+ <box width={dim().width} height={dim().height} backgroundColor={skin.panel} position="relative">
498
+ <box
499
+ flexDirection="column"
500
+ width="100%"
501
+ height="100%"
502
+ paddingTop={1}
503
+ paddingBottom={1}
504
+ paddingLeft={2}
505
+ paddingRight={2}
506
+ >
507
+ <box flexDirection="row" justifyContent="space-between" paddingBottom={1}>
508
+ <text fg={skin.text}>
509
+ <b>{props.input.label} screen</b>
510
+ <span style={{ fg: skin.muted }}> plugin route</span>
511
+ </text>
512
+ <text fg={skin.muted}>{shortcuts().screen_home} home</text>
513
+ </box>
514
+
515
+ <box flexDirection="row" gap={1} paddingBottom={1}>
516
+ {tabs.map((item, i) => {
517
+ const on = value.tab === i
518
+ return (
519
+ <Btn
520
+ txt={item}
521
+ run={() => props.api.route.navigate(props.route.screen, { ...value, tab: i })}
522
+ skin={skin}
523
+ on={on}
524
+ />
525
+ )
526
+ })}
527
+ </box>
528
+
529
+ <box
530
+ border
531
+ borderColor={skin.border}
532
+ paddingTop={1}
533
+ paddingBottom={1}
534
+ paddingLeft={2}
535
+ paddingRight={2}
536
+ flexGrow={1}
537
+ >
538
+ {value.tab === 0 ? (
539
+ <box flexDirection="column" gap={1}>
540
+ <text fg={skin.text}>Route: {props.route.screen}</text>
541
+ <text fg={skin.muted}>plugin state: {props.meta.state}</text>
542
+ <text fg={skin.muted}>
543
+ first: {props.meta.state === "first" ? "yes" : "no"} · updated:{" "}
544
+ {props.meta.state === "updated" ? "yes" : "no"} · loads: {props.meta.load_count}
545
+ </text>
546
+ <text fg={skin.muted}>plugin source: {props.meta.source}</text>
547
+ <text fg={skin.muted}>source: {value.source}</text>
548
+ <text fg={skin.muted}>note: {value.note || "(none)"}</text>
549
+ <text fg={skin.muted}>selected: {value.selected || "(none)"}</text>
550
+ <text fg={skin.muted}>local stack depth: {value.local}</text>
551
+ <text fg={skin.muted}>host stack open: {props.api.ui.dialog.open ? "yes" : "no"}</text>
552
+ </box>
553
+ ) : null}
554
+
555
+ {value.tab === 1 ? (
556
+ <box flexDirection="column" gap={1}>
557
+ <text fg={skin.text}>Counter: {value.count}</text>
558
+ <text fg={skin.muted}>
559
+ {shortcuts().screen_up} / {shortcuts().screen_down} change value
560
+ </text>
561
+ </box>
562
+ ) : null}
563
+
564
+ {value.tab === 2 ? (
565
+ <box flexDirection="column" gap={1}>
566
+ <text fg={skin.muted}>
567
+ {shortcuts().screen_modal} modal | {shortcuts().screen_alert} alert | {shortcuts().screen_confirm}{" "}
568
+ confirm | {shortcuts().screen_prompt} prompt | {shortcuts().screen_select} select
569
+ </text>
570
+ <text fg={skin.muted}>
571
+ {shortcuts().screen_local} local stack | {shortcuts().screen_host} host stack
572
+ </text>
573
+ <text fg={skin.muted}>
574
+ local open: {shortcuts().local_push} push nested · {shortcuts().local_pop} close
575
+ </text>
576
+ <text fg={skin.muted}>{shortcuts().screen_home} returns home</text>
577
+ </box>
578
+ ) : null}
579
+ </box>
580
+
581
+ <box flexDirection="row" gap={1} paddingTop={1}>
582
+ <Btn txt="go home" run={() => props.api.route.navigate("home")} skin={skin} />
583
+ <Btn txt="modal" run={() => props.api.route.navigate(props.route.modal, value)} skin={skin} on />
584
+ <Btn txt="local overlay" run={show} skin={skin} />
585
+ <Btn txt="host overlay" run={() => host(props.api, props.input, skin)} skin={skin} />
586
+ <Btn txt="alert" run={() => warn(props.api, props.route, value)} skin={skin} />
587
+ <Btn txt="confirm" run={() => check(props.api, props.route, value)} skin={skin} />
588
+ <Btn txt="prompt" run={() => entry(props.api, props.route, value)} skin={skin} />
589
+ <Btn txt="select" run={() => picker(props.api, props.route, value)} skin={skin} />
590
+ </box>
591
+ </box>
592
+
593
+ <box
594
+ visible={value.local > 0}
595
+ width={dim().width}
596
+ height={dim().height}
597
+ alignItems="center"
598
+ position="absolute"
599
+ zIndex={3000}
600
+ paddingTop={dim().height / 4}
601
+ left={0}
602
+ top={0}
603
+ backgroundColor={RGBA.fromInts(0, 0, 0, 160)}
604
+ onMouseUp={() => {
605
+ pop()
606
+ }}
607
+ >
608
+ <box
609
+ onMouseUp={(evt) => {
610
+ evt.stopPropagation()
611
+ }}
612
+ width={60}
613
+ maxWidth={dim().width - 2}
614
+ backgroundColor={skin.panel}
615
+ border
616
+ borderColor={skin.border}
617
+ paddingTop={1}
618
+ paddingBottom={1}
619
+ paddingLeft={2}
620
+ paddingRight={2}
621
+ gap={1}
622
+ flexDirection="column"
623
+ >
624
+ <text fg={skin.text}>
625
+ <b>{props.input.label} local overlay</b>
626
+ </text>
627
+ <text fg={skin.muted}>Plugin-owned stack depth: {value.local}</text>
628
+ <text fg={skin.muted}>
629
+ {shortcuts().local_push} push nested · {shortcuts().local_pop} pop/close
630
+ </text>
631
+ <box flexDirection="row" gap={1}>
632
+ <Btn txt="push" run={push} skin={skin} on />
633
+ <Btn txt="pop" run={pop} skin={skin} />
634
+ </box>
635
+ </box>
636
+ </box>
637
+ </box>
638
+ )
639
+ }
640
+
641
+ const Modal = (props: {
642
+ api: TuiPluginApi
643
+ input: Cfg
644
+ route: Route
645
+ keys: Keys
646
+ params?: Record<string, unknown>
647
+ }) => {
648
+ const Dialog = props.api.ui.Dialog
649
+ const value = parse(props.params)
650
+ const skin = tone(props.api)
651
+
652
+ useBindings(() => ({
653
+ enabled: () => props.api.route.current.name === props.route.modal,
654
+ commands: [
655
+ {
656
+ name: command.modal_accept,
657
+ run() {
658
+ props.api.route.navigate(props.route.screen, { ...parse(props.params), source: "modal" })
659
+ },
660
+ },
661
+ {
662
+ name: command.modal_close,
663
+ run() {
664
+ props.api.route.navigate("home")
665
+ },
666
+ },
667
+ ],
668
+ bindings: props.keys.gather("smoke.modal", [command.modal_accept, command.modal_close]),
669
+ }))
670
+ const shortcuts = useKeymapSelector((keymap) => {
671
+ const bindings = keymap.getCommandBindings({
672
+ visibility: "registered",
673
+ commands: [command.modal, command.screen, command.modal_accept, command.modal_close],
674
+ })
675
+
676
+ return {
677
+ modal: props.api.keys.formatBindings(bindings.get(command.modal)) ?? "",
678
+ screen: props.api.keys.formatBindings(bindings.get(command.screen)) ?? "",
679
+ modal_accept: props.api.keys.formatBindings(bindings.get(command.modal_accept)) ?? "",
680
+ modal_close: props.api.keys.formatBindings(bindings.get(command.modal_close)) ?? "",
681
+ }
682
+ })
683
+
684
+ return (
685
+ <box width="100%" height="100%" backgroundColor={skin.panel}>
686
+ <Dialog onClose={() => props.api.route.navigate("home")}>
687
+ <box paddingBottom={1} paddingLeft={2} paddingRight={2} gap={1} flexDirection="column">
688
+ <text fg={skin.text}>
689
+ <b>{props.input.label} modal</b>
690
+ </text>
691
+ <text fg={skin.muted}>{shortcuts().modal} modal command</text>
692
+ <text fg={skin.muted}>{shortcuts().screen} screen command</text>
693
+ <text fg={skin.muted}>
694
+ {shortcuts().modal_accept} opens screen · {shortcuts().modal_close} closes
695
+ </text>
696
+ <box flexDirection="row" gap={1}>
697
+ <Btn
698
+ txt="open screen"
699
+ run={() => props.api.route.navigate(props.route.screen, { ...value, source: "modal" })}
700
+ skin={skin}
701
+ on
702
+ />
703
+ <Btn txt="cancel" run={() => props.api.route.navigate("home")} skin={skin} />
704
+ </box>
705
+ </box>
706
+ </Dialog>
707
+ </box>
708
+ )
709
+ }
710
+
711
+ const home = (api: TuiPluginApi, input: Cfg) => ({
712
+ slots: {
713
+ home_logo(ctx) {
714
+ const map = ctx.theme.current
715
+ const skin = look(map)
716
+ const art = [
717
+ " $$\\",
718
+ " $$ |",
719
+ " $$$$$$$\\ $$$$$$\\$$$$\\ $$$$$$\\ $$ | $$\\ $$$$$$\\",
720
+ "$$ _____|$$ _$$ _$$\\ $$ __$$\\ $$ | $$ |$$ __$$\\",
721
+ "\\$$$$$$\\ $$ / $$ / $$ |$$ / $$ |$$$$$$ / $$$$$$$$ |",
722
+ " \\____$$\\ $$ | $$ | $$ |$$ | $$ |$$ _$$< $$ ____|",
723
+ "$$$$$$$ |$$ | $$ | $$ |\\$$$$$$ |$$ | \\$$\\ \\$$$$$$$\\",
724
+ "\\_______/ \\__| \\__| \\__| \\______/ \\__| \\__| \\_______|",
725
+ ]
726
+ const fill = [
727
+ skin.accent,
728
+ skin.muted,
729
+ ink(map, "info", ui.accent),
730
+ skin.text,
731
+ ink(map, "success", ui.accent),
732
+ ink(map, "warning", ui.accent),
733
+ ink(map, "secondary", ui.accent),
734
+ ink(map, "error", ui.accent),
735
+ ]
736
+
737
+ return (
738
+ <box flexDirection="column">
739
+ {art.map((line, i) => (
740
+ <text fg={fill[i]}>{line}</text>
741
+ ))}
742
+ </box>
743
+ )
744
+ },
745
+ home_prompt(ctx, value) {
746
+ const skin = look(ctx.theme.current)
747
+ const Prompt = api.ui.Prompt
748
+ const Slot = api.ui.Slot
749
+ const normal = [
750
+ `[SMOKE] route check for ${input.label}`,
751
+ "[SMOKE] confirm home_prompt slot override",
752
+ "[SMOKE] verify prompt-right slot passthrough",
753
+ ]
754
+ const shell = ["printf '[SMOKE] home prompt\n'", "git status --short", "bun --version"]
755
+ const hint = (
756
+ <box flexShrink={0} flexDirection="row" gap={1}>
757
+ <text fg={skin.muted}>
758
+ <span style={{ fg: skin.accent }}>•</span> smoke home prompt
759
+ </text>
760
+ </box>
761
+ )
762
+
763
+ return (
764
+ <Prompt
765
+ workspaceID={value.workspace_id}
766
+ hint={hint}
767
+ right={
768
+ <box flexDirection="row" gap={1}>
769
+ <Slot name="home_prompt_right" workspace_id={value.workspace_id} />
770
+ <Slot name="smoke_prompt_right" workspace_id={value.workspace_id} label={input.label} />
771
+ </box>
772
+ }
773
+ placeholders={{ normal, shell }}
774
+ />
775
+ )
776
+ },
777
+ home_prompt_right(ctx, value) {
778
+ const skin = look(ctx.theme.current)
779
+ const id = value.workspace_id?.slice(0, 8) ?? "none"
780
+ return (
781
+ <text fg={skin.muted}>
782
+ <span style={{ fg: skin.accent }}>{input.label}</span> home:{id}
783
+ </text>
784
+ )
785
+ },
786
+ session_prompt_right(ctx, value) {
787
+ const skin = look(ctx.theme.current)
788
+ return (
789
+ <text fg={skin.muted}>
790
+ <span style={{ fg: skin.accent }}>{input.label}</span> session:{value.session_id.slice(0, 8)}
791
+ </text>
792
+ )
793
+ },
794
+ smoke_prompt_right(ctx, value) {
795
+ const skin = look(ctx.theme.current)
796
+ const id = typeof value.workspace_id === "string" ? value.workspace_id.slice(0, 8) : "none"
797
+ const label = typeof value.label === "string" ? value.label : input.label
798
+ return (
799
+ <text fg={skin.muted}>
800
+ <span style={{ fg: skin.accent }}>{label}</span> custom:{id}
801
+ </text>
802
+ )
803
+ },
804
+ home_bottom(ctx) {
805
+ const skin = look(ctx.theme.current)
806
+ const text = "extra content in the unified home bottom slot"
807
+
808
+ return (
809
+ <box width="100%" maxWidth={75} alignItems="center" paddingTop={1} flexShrink={0} gap={1}>
810
+ <box
811
+ border
812
+ borderColor={skin.border}
813
+ backgroundColor={skin.panel}
814
+ paddingTop={1}
815
+ paddingBottom={1}
816
+ paddingLeft={2}
817
+ paddingRight={2}
818
+ width="100%"
819
+ >
820
+ <text fg={skin.muted}>
821
+ <span style={{ fg: skin.accent }}>{input.label}</span> {text}
822
+ </text>
823
+ </box>
824
+ </box>
825
+ )
826
+ },
827
+ },
828
+ })
829
+
830
+ const block = (input: Cfg, order: number, title: string, text: string): TuiSlotPlugin => ({
831
+ order,
832
+ slots: {
833
+ sidebar_content(ctx, value) {
834
+ const skin = look(ctx.theme.current)
835
+
836
+ return (
837
+ <box
838
+ border
839
+ borderColor={skin.border}
840
+ backgroundColor={skin.panel}
841
+ paddingTop={1}
842
+ paddingBottom={1}
843
+ paddingLeft={2}
844
+ paddingRight={2}
845
+ flexDirection="column"
846
+ gap={1}
847
+ >
848
+ <text fg={skin.accent}>
849
+ <b>{title}</b>
850
+ </text>
851
+ <text fg={skin.text}>{text}</text>
852
+ <text fg={skin.muted}>
853
+ {input.label} order {order} · session {value.session_id.slice(0, 8)}
854
+ </text>
855
+ </box>
856
+ )
857
+ },
858
+ },
859
+ })
860
+
861
+ const slot = (api: TuiPluginApi, input: Cfg): TuiSlotPlugin[] => [
862
+ home(api, input),
863
+ block(input, 50, "Smoke above", "renders above internal sidebar blocks"),
864
+ block(input, 250, "Smoke between", "renders between internal sidebar blocks"),
865
+ block(input, 650, "Smoke below", "renders below internal sidebar blocks"),
866
+ ]
867
+
868
+ const reg = (api: TuiPluginApi, input: Cfg, keys: Keys) => {
869
+ const route = names(input)
870
+ api.keymap.registerLayer({
871
+ commands: [
872
+ {
873
+ name: command.modal,
874
+ title: `${input.label} modal`,
875
+ category: "Plugin",
876
+ namespace: "palette",
877
+ slashName: "smoke",
878
+ run() {
879
+ api.route.navigate(route.modal, { source: "command" })
880
+ },
881
+ },
882
+ {
883
+ name: command.screen,
884
+ title: `${input.label} screen`,
885
+ category: "Plugin",
886
+ namespace: "palette",
887
+ slashName: "smoke-screen",
888
+ run() {
889
+ api.route.navigate(route.screen, { source: "command", tab: 0, count: 0 })
890
+ },
891
+ },
892
+ {
893
+ name: command.alert,
894
+ title: `${input.label} alert dialog`,
895
+ category: "Plugin",
896
+ namespace: "palette",
897
+ slashName: "smoke-alert",
898
+ run() {
899
+ warn(api, route, current(api, route))
900
+ },
901
+ },
902
+ {
903
+ name: command.confirm,
904
+ title: `${input.label} confirm dialog`,
905
+ category: "Plugin",
906
+ namespace: "palette",
907
+ slashName: "smoke-confirm",
908
+ run() {
909
+ check(api, route, current(api, route))
910
+ },
911
+ },
912
+ {
913
+ name: command.prompt,
914
+ title: `${input.label} prompt dialog`,
915
+ category: "Plugin",
916
+ namespace: "palette",
917
+ slashName: "smoke-prompt",
918
+ run() {
919
+ entry(api, route, current(api, route))
920
+ },
921
+ },
922
+ {
923
+ name: command.select,
924
+ title: `${input.label} select dialog`,
925
+ category: "Plugin",
926
+ namespace: "palette",
927
+ slashName: "smoke-select",
928
+ run() {
929
+ picker(api, route, current(api, route))
930
+ },
931
+ },
932
+ {
933
+ name: command.host,
934
+ title: `${input.label} host overlay`,
935
+ category: "Plugin",
936
+ namespace: "palette",
937
+ slashName: "smoke-host",
938
+ run() {
939
+ host(api, input, tone(api))
940
+ },
941
+ },
942
+ {
943
+ name: command.home,
944
+ title: `${input.label} go home`,
945
+ category: "Plugin",
946
+ namespace: "palette",
947
+ enabled: () => api.route.current.name !== "home",
948
+ run() {
949
+ api.route.navigate("home")
950
+ },
951
+ },
952
+ {
953
+ name: command.toast,
954
+ title: `${input.label} toast`,
955
+ category: "Plugin",
956
+ namespace: "palette",
957
+ run() {
958
+ api.ui.toast({
959
+ variant: "info",
960
+ title: "Smoke",
961
+ message: "Plugin toast works",
962
+ duration: 2000,
963
+ })
964
+ },
965
+ },
966
+ ],
967
+ bindings: keys.gather("smoke.global", [
968
+ command.modal,
969
+ command.screen,
970
+ command.alert,
971
+ command.confirm,
972
+ command.prompt,
973
+ command.select,
974
+ command.host,
975
+ command.home,
976
+ command.toast,
977
+ ]),
978
+ })
979
+ }
980
+
981
+ const tui: TuiPlugin = async (api, options, meta) => {
982
+ if (options?.enabled === false) return
983
+
984
+ await api.theme.install("./smoke-theme.json")
985
+ api.theme.set("smoke-theme")
986
+
987
+ const value = cfg(options)
988
+ const route = names(value)
989
+ const keys = createKeys(value.keybinds)
990
+ const fx = new VignetteEffect(value.vignette)
991
+ const post = fx.apply.bind(fx)
992
+ api.renderer.addPostProcessFn(post)
993
+ api.lifecycle.onDispose(() => {
994
+ api.renderer.removePostProcessFn(post)
995
+ })
996
+
997
+ api.route.register([
998
+ {
999
+ name: route.screen,
1000
+ render: ({ params }) => <Screen api={api} input={value} route={route} keys={keys} meta={meta} params={params} />,
1001
+ },
1002
+ {
1003
+ name: route.modal,
1004
+ render: ({ params }) => <Modal api={api} input={value} route={route} keys={keys} params={params} />,
1005
+ },
1006
+ ])
1007
+
1008
+ reg(api, value, keys)
1009
+ for (const item of slot(api, value)) {
1010
+ api.slots.register(item)
1011
+ }
1012
+ }
1013
+
1014
+ const plugin: TuiPluginModule & { id: string } = {
1015
+ id: "tui-smoke",
1016
+ tui,
1017
+ }
1018
+
1019
+ export default plugin
.opencode/skills/effect/SKILL.md ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: effect
3
+ description: Work with Effect v4 / effect-smol TypeScript code in this repo
4
+ ---
5
+
6
+ # Effect
7
+
8
+ This codebase uses Effect for typed, composable TypeScript services, schemas, and workflows.
9
+
10
+ ## Source Of Truth
11
+
12
+ Use the current Effect v4 / effect-smol source, not memory or older Effect v2/v3 examples.
13
+
14
+ 1. If `.opencode/references/effect-smol` is missing, clone `https://github.com/Effect-TS/effect-smol` there. Do this in the project, not in the skill folder.
15
+ 2. Search `.opencode/references/effect-smol` for exact APIs, examples, tests, and naming patterns before answering or implementing Effect-specific code.
16
+ 3. Also inspect existing repo code for local house style before introducing new patterns.
17
+ 4. Prefer answers and implementations backed by specific source files or nearby repo examples.
18
+
19
+ ## Guidelines
20
+
21
+ - Prefer current Effect v4 APIs and project-local patterns over old blog posts, examples, or package-memory guesses.
22
+ - Use `Effect.gen(function* () { ... })` for multi-step workflows.
23
+ - Use `Effect.fn("Name")` or `Effect.fnUntraced(...)` for named effects when adding reusable service methods or important workflows.
24
+ - Prefer Effect `Schema` for API and domain data shapes. Use branded schemas for IDs and `Schema.TaggedErrorClass` for typed domain errors when modeling new error surfaces.
25
+ - Keep HTTP handlers thin: decode input, read request context, call services, and map transport errors. Put business rules in services.
26
+ - In Effect service code, prefer Effect-aware platform abstractions and dependencies over ad hoc promises where the surrounding code already does so.
27
+ - Keep layer composition explicit. Avoid broad hidden provisioning that makes missing dependencies hard to see.
28
+ - In tests, prefer the repo's existing Effect test helpers and live tests for filesystem, git, child process, locks, or timing behavior.
29
+ - Do not introduce `any`, non-null assertions, unchecked casts, or older Effect APIs just to satisfy types.
30
+ - Do not answer from memory. Verify against `.opencode/references/effect-smol` or nearby code first.
31
+
32
+ ## Testing Patterns
33
+
34
+ - Use `testEffect(...)` from `packages/opencode/test/lib/effect.ts` for tests that exercise Effect services, layers, runtime context, scoped resources, or platform integrations.
35
+ - Use `it.live(...)` for filesystem, git repositories, HTTP servers, sockets, child processes, locks, real time, and other live platform behavior.
36
+ - Run tests from package directories such as `packages/opencode`; never run package tests from the repo root.
37
+ - Prefer explicit test layers over ad hoc managed runtimes. Keep dependency provisioning visible in the test file.
38
+ - Use scoped fixtures and finalizers for resources that must be cleaned up, including temporary directories, flags, databases, fibers, servers, and global state.
.opencode/skills/rtl-aware-development/SKILL.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: rtl-aware-development
3
+ description: OpenCode Desktop should be RTL-aware. Use when implementing or reviewing RTL/LTR behavior in the web app, desktop app, CSS, menus, scrolling, resizing, icons, mixed-direction text, or Electron title bars.
4
+ ---
5
+
6
+ # RTL-Aware Development
7
+
8
+ Treat direction as independent from language. Test English in both directions as well as real RTL and mixed-script content.
9
+
10
+ ## Guidelines
11
+
12
+ - Set `lang` and `dir` on the document, and propagate direction through component providers used by portaled menus and popovers. Do not change the selected locale merely to force RTL.
13
+ - Keep DOM and focus order semantic. Flexbox and Grid already follow `dir`; do not add `row-reverse`, CSS `order`, or reversed markup just to mirror a layout.
14
+ - Prefer logical CSS for semantic layout. Reserve physical coordinates for pointer positions, canvas geometry, native window controls, and other genuinely physical placement.
15
+
16
+ ```css
17
+ /* Avoid */
18
+ padding-left: 12px;
19
+ right: 0;
20
+ border-right: 1px solid;
21
+ text-align: left;
22
+
23
+ /* Prefer */
24
+ padding-inline-start: 12px;
25
+ inset-inline-end: 0;
26
+ border-inline-end: 1px solid;
27
+ text-align: start;
28
+ ```
29
+
30
+ - Isolate mixed-direction text. Use `dir="auto"` or `<bdi>` for unknown text; keep code, URLs, IDs, and filesystem paths LTR without forcing the surrounding component LTR.
31
+
32
+ ```html
33
+ <span class="file-row"><bdi dir="auto">README.md</bdi></span> <bdi dir="ltr"><code>C:\src\app.ts</code></bdi>
34
+ ```
35
+
36
+ - Mirror directional meaning, not every image. Back/forward, previous/next, disclosure, indentation, and directional progress may need mirroring. Do not mirror brands, clocks, media controls, charts, or text. Reverse physical gradients, `translateX`, SVG transforms, and animation deltas explicitly.
37
+ - Map interactions through direction. `clientX` remains physical; resizing a logical edge needs an RTL-aware delta. Logical previous/next keyboard controls may swap ArrowLeft/ArrowRight. Follow the relevant WAI-ARIA widget pattern.
38
+ - Do not assume LTR scrolling. RTL `scrollLeft` can start at `0` and become negative. Prefer `scrollIntoView({ inline: "nearest" })` or a tested direction-normalizing helper.
39
+ - For Electron title bars, prefer native caption controls and use `titleBarOverlay` plus `env(titlebar-area-*)` for the safe content rectangle. Keep Windows/macOS native-control avoidance and `trafficLightPosition` physical; keep app navigation inside that rectangle logical. Mark interactive titlebar children `app-region: no-drag`.
40
+ - Verify behavior, not screenshots alone. Check computed styles, pseudo-element geometry, hit zones, focus order, keyboard behavior, submenu direction, zoom/scaling, and both LTR and RTL scroll endpoints.
41
+
42
+ ## Test Matrix
43
+
44
+ - English + LTR
45
+ - English + forced RTL
46
+ - A real RTL locale + RTL
47
+ - Mixed RTL/LTR content, long labels, numbers, code, and paths
48
+ - Keyboard, pointer resize, scrolling, menus/submenus, and Electron titlebar controls in both directions
49
+
50
+ ## References
51
+
52
+ - [RTL Styling 101, Ahmad Shadeed](https://rtlstyling.com/posts/rtl-styling/)
53
+ - [CSS-Tricks: RTL Styling 101](https://css-tricks.com/rtl-styling-101/)
54
+ - [CSS-Tricks: CSS Logical Properties and Values](https://css-tricks.com/css-logical-properties-and-values/)
55
+ - [W3C: Structural markup and right-to-left text](https://www.w3.org/International/questions/qa-html-dir)
56
+ - [W3C: Inline bidirectional markup](https://www.w3.org/International/articles/inline-bidi-markup/)
57
+ - [MDN: CSS logical properties and values](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Logical_properties_and_values)
58
+ - [MDN: `dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/dir)
59
+ - [MDN: `scrollLeft`](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollLeft)
60
+ - [web.dev: Logical properties](https://web.dev/learn/css/logical-properties/)
61
+ - [Electron: Custom title bar](https://www.electronjs.org/docs/latest/tutorial/custom-title-bar)
62
+ - [WAI-ARIA: Window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/)
63
+ - [Kobalte: I18n Provider](https://kobalte.dev/docs/core/components/i18n-provider/)
.opencode/themes/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ smoke-theme.json
.opencode/themes/mytheme.json ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://opencode.ai/theme.json",
3
+ "defs": {
4
+ "nord0": "#2E3440",
5
+ "nord1": "#3B4252",
6
+ "nord2": "#434C5E",
7
+ "nord3": "#4C566A",
8
+ "nord4": "#D8DEE9",
9
+ "nord5": "#E5E9F0",
10
+ "nord6": "#ECEFF4",
11
+ "nord7": "#8FBCBB",
12
+ "nord8": "#88C0D0",
13
+ "nord9": "#81A1C1",
14
+ "nord10": "#5E81AC",
15
+ "nord11": "#BF616A",
16
+ "nord12": "#D08770",
17
+ "nord13": "#EBCB8B",
18
+ "nord14": "#A3BE8C",
19
+ "nord15": "#B48EAD"
20
+ },
21
+ "theme": {
22
+ "primary": {
23
+ "dark": "nord8",
24
+ "light": "nord10"
25
+ },
26
+ "secondary": {
27
+ "dark": "nord9",
28
+ "light": "nord9"
29
+ },
30
+ "accent": {
31
+ "dark": "nord7",
32
+ "light": "nord7"
33
+ },
34
+ "error": {
35
+ "dark": "nord11",
36
+ "light": "nord11"
37
+ },
38
+ "warning": {
39
+ "dark": "nord12",
40
+ "light": "nord12"
41
+ },
42
+ "success": {
43
+ "dark": "nord14",
44
+ "light": "nord14"
45
+ },
46
+ "info": {
47
+ "dark": "nord8",
48
+ "light": "nord10"
49
+ },
50
+ "text": {
51
+ "dark": "nord4",
52
+ "light": "nord0"
53
+ },
54
+ "textMuted": {
55
+ "dark": "nord3",
56
+ "light": "nord1"
57
+ },
58
+ "background": {
59
+ "dark": "nord0",
60
+ "light": "nord6"
61
+ },
62
+ "backgroundPanel": {
63
+ "dark": "nord1",
64
+ "light": "nord5"
65
+ },
66
+ "backgroundElement": {
67
+ "dark": "nord1",
68
+ "light": "nord4"
69
+ },
70
+ "border": {
71
+ "dark": "nord2",
72
+ "light": "nord3"
73
+ },
74
+ "borderActive": {
75
+ "dark": "nord3",
76
+ "light": "nord2"
77
+ },
78
+ "borderSubtle": {
79
+ "dark": "nord2",
80
+ "light": "nord3"
81
+ },
82
+ "diffAdded": {
83
+ "dark": "nord14",
84
+ "light": "nord14"
85
+ },
86
+ "diffRemoved": {
87
+ "dark": "nord11",
88
+ "light": "nord11"
89
+ },
90
+ "diffContext": {
91
+ "dark": "nord3",
92
+ "light": "nord3"
93
+ },
94
+ "diffHunkHeader": {
95
+ "dark": "nord3",
96
+ "light": "nord3"
97
+ },
98
+ "diffHighlightAdded": {
99
+ "dark": "nord14",
100
+ "light": "nord14"
101
+ },
102
+ "diffHighlightRemoved": {
103
+ "dark": "nord11",
104
+ "light": "nord11"
105
+ },
106
+ "diffAddedBg": {
107
+ "dark": "#3B4252",
108
+ "light": "#E5E9F0"
109
+ },
110
+ "diffRemovedBg": {
111
+ "dark": "#3B4252",
112
+ "light": "#E5E9F0"
113
+ },
114
+ "diffContextBg": {
115
+ "dark": "nord1",
116
+ "light": "nord5"
117
+ },
118
+ "diffLineNumber": {
119
+ "dark": "#abafb7",
120
+ "light": "textMuted"
121
+ },
122
+ "diffAddedLineNumberBg": {
123
+ "dark": "#3B4252",
124
+ "light": "#E5E9F0"
125
+ },
126
+ "diffRemovedLineNumberBg": {
127
+ "dark": "#3B4252",
128
+ "light": "#E5E9F0"
129
+ },
130
+ "markdownText": {
131
+ "dark": "nord4",
132
+ "light": "nord0"
133
+ },
134
+ "markdownHeading": {
135
+ "dark": "nord8",
136
+ "light": "nord10"
137
+ },
138
+ "markdownLink": {
139
+ "dark": "nord9",
140
+ "light": "nord9"
141
+ },
142
+ "markdownLinkText": {
143
+ "dark": "nord7",
144
+ "light": "nord7"
145
+ },
146
+ "markdownCode": {
147
+ "dark": "nord14",
148
+ "light": "nord14"
149
+ },
150
+ "markdownBlockQuote": {
151
+ "dark": "nord3",
152
+ "light": "nord3"
153
+ },
154
+ "markdownEmph": {
155
+ "dark": "nord12",
156
+ "light": "nord12"
157
+ },
158
+ "markdownStrong": {
159
+ "dark": "nord13",
160
+ "light": "nord13"
161
+ },
162
+ "markdownHorizontalRule": {
163
+ "dark": "nord3",
164
+ "light": "nord3"
165
+ },
166
+ "markdownListItem": {
167
+ "dark": "nord8",
168
+ "light": "nord10"
169
+ },
170
+ "markdownListEnumeration": {
171
+ "dark": "nord7",
172
+ "light": "nord7"
173
+ },
174
+ "markdownImage": {
175
+ "dark": "nord9",
176
+ "light": "nord9"
177
+ },
178
+ "markdownImageText": {
179
+ "dark": "nord7",
180
+ "light": "nord7"
181
+ },
182
+ "markdownCodeBlock": {
183
+ "dark": "nord4",
184
+ "light": "nord0"
185
+ },
186
+ "syntaxComment": {
187
+ "dark": "nord3",
188
+ "light": "nord3"
189
+ },
190
+ "syntaxKeyword": {
191
+ "dark": "nord9",
192
+ "light": "nord9"
193
+ },
194
+ "syntaxFunction": {
195
+ "dark": "nord8",
196
+ "light": "nord8"
197
+ },
198
+ "syntaxVariable": {
199
+ "dark": "nord7",
200
+ "light": "nord7"
201
+ },
202
+ "syntaxString": {
203
+ "dark": "nord14",
204
+ "light": "nord14"
205
+ },
206
+ "syntaxNumber": {
207
+ "dark": "nord15",
208
+ "light": "nord15"
209
+ },
210
+ "syntaxType": {
211
+ "dark": "nord7",
212
+ "light": "nord7"
213
+ },
214
+ "syntaxOperator": {
215
+ "dark": "nord9",
216
+ "light": "nord9"
217
+ },
218
+ "syntaxPunctuation": {
219
+ "dark": "nord4",
220
+ "light": "nord0"
221
+ }
222
+ }
223
+ }
.opencode/tool/github-pr-search.ts ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /// <reference path="../env.d.ts" />
2
+ import { tool } from "@opencode-ai/plugin"
3
+ async function githubFetch(endpoint: string, options: RequestInit = {}) {
4
+ const response = await fetch(`https://api.github.com${endpoint}`, {
5
+ ...options,
6
+ headers: {
7
+ Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
8
+ Accept: "application/vnd.github+json",
9
+ "Content-Type": "application/json",
10
+ ...(options.headers instanceof Headers ? Object.fromEntries(options.headers.entries()) : options.headers),
11
+ },
12
+ })
13
+ if (!response.ok) {
14
+ throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
15
+ }
16
+ return response.json()
17
+ }
18
+
19
+ interface PR {
20
+ title: string
21
+ html_url: string
22
+ }
23
+
24
+ export default tool({
25
+ description: `Use this tool to search GitHub pull requests by title and description.
26
+
27
+ This tool searches PRs in the anomalyco/opencode repository and returns LLM-friendly results including:
28
+ - PR number and title
29
+ - Author
30
+ - State (open/closed/merged)
31
+ - Labels
32
+ - Description snippet
33
+
34
+ Use the query parameter to search for keywords that might appear in PR titles or descriptions.`,
35
+ args: {
36
+ query: tool.schema.string().describe("Search query for PR titles and descriptions"),
37
+ limit: tool.schema.number().describe("Maximum number of results to return").default(10),
38
+ offset: tool.schema.number().describe("Number of results to skip for pagination").default(0),
39
+ },
40
+ async execute(args) {
41
+ const owner = "anomalyco"
42
+ const repo = "opencode"
43
+
44
+ const page = Math.floor(args.offset / args.limit) + 1
45
+ const searchQuery = encodeURIComponent(`${args.query} repo:${owner}/${repo} type:pr state:open`)
46
+ const result = await githubFetch(
47
+ `/search/issues?q=${searchQuery}&per_page=${args.limit}&page=${page}&sort=updated&order=desc`,
48
+ )
49
+
50
+ if (result.total_count === 0) {
51
+ return `No PRs found matching "${args.query}"`
52
+ }
53
+
54
+ const prs = result.items as PR[]
55
+
56
+ if (prs.length === 0) {
57
+ return `No other PRs found matching "${args.query}"`
58
+ }
59
+
60
+ const formatted = prs.map((pr) => `${pr.title}\n${pr.html_url}`).join("\n\n")
61
+
62
+ return `Found ${result.total_count} PRs (showing ${prs.length}):\n\n${formatted}`
63
+ },
64
+ })
.opencode/tool/github-triage.ts ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /// <reference path="../env.d.ts" />
2
+ import { tool } from "@opencode-ai/plugin"
3
+
4
+ const TEAM = {
5
+ tui: ["kommander", "simonklee"],
6
+ desktop_web: ["Hona", "Brendonovich"],
7
+ core: ["jlongster", "rekram1-node", "neriousy", "nexxeln", "kitlangton"],
8
+ inference: ["fwang", "MrMushrooooom", "starptech"],
9
+ windows: ["Hona"],
10
+ } as const
11
+
12
+ function pick<T>(items: readonly T[]) {
13
+ return items[Math.floor(Math.random() * items.length)]!
14
+ }
15
+
16
+ function getIssueNumber(): number {
17
+ const issue = parseInt(process.env.ISSUE_NUMBER ?? "", 10)
18
+ if (!issue) throw new Error("ISSUE_NUMBER env var not set")
19
+ return issue
20
+ }
21
+
22
+ async function githubFetch(endpoint: string, options: RequestInit = {}) {
23
+ const response = await fetch(`https://api.github.com${endpoint}`, {
24
+ ...options,
25
+ headers: {
26
+ Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
27
+ Accept: "application/vnd.github+json",
28
+ "Content-Type": "application/json",
29
+ ...(options.headers instanceof Headers ? Object.fromEntries(options.headers.entries()) : options.headers),
30
+ },
31
+ })
32
+ if (!response.ok) {
33
+ throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
34
+ }
35
+ return response.json()
36
+ }
37
+
38
+ export default tool({
39
+ description: `Use this tool to assign a GitHub issue.
40
+
41
+ Provide the team that should own the issue. This tool picks a random assignee from that team and does not apply labels.`,
42
+ args: {
43
+ team: tool.schema
44
+ .enum(Object.keys(TEAM) as [keyof typeof TEAM, ...(keyof typeof TEAM)[]])
45
+ .describe("The owning team"),
46
+ },
47
+ async execute(args) {
48
+ const issue = getIssueNumber()
49
+ const owner = "anomalyco"
50
+ const repo = "opencode"
51
+ const assignee = pick(TEAM[args.team])
52
+
53
+ await githubFetch(`/repos/${owner}/${repo}/issues/${issue}/assignees`, {
54
+ method: "POST",
55
+ body: JSON.stringify({ assignees: [assignee] }),
56
+ })
57
+
58
+ return `Assigned @${assignee} from ${args.team} to issue #${issue}`
59
+ },
60
+ })
artifacts/glm52-rise-video/.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ node_modules
2
+ .remotion
3
+ out/frame-*.png
artifacts/glm52-rise-video/bun.lock ADDED
@@ -0,0 +1,483 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "glm52-rise-video",
7
+ "dependencies": {
8
+ "@remotion/cli": "^4.0.384",
9
+ "react": "^19.2.3",
10
+ "react-dom": "^19.2.3",
11
+ "remotion": "^4.0.384",
12
+ },
13
+ "devDependencies": {
14
+ "@types/react": "^19.2.8",
15
+ "@types/react-dom": "^19.2.3",
16
+ "typescript": "^5.8.2",
17
+ },
18
+ },
19
+ },
20
+ "packages": {
21
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
22
+
23
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
24
+
25
+ "@babel/parser": ["@babel/parser@7.24.1", "", { "bin": "./bin/babel-parser.js" }, "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg=="],
26
+
27
+ "@babel/types": ["@babel/types@7.24.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w=="],
28
+
29
+ "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
30
+
31
+ "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
32
+
33
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
34
+
35
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="],
36
+
37
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="],
38
+
39
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="],
40
+
41
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="],
42
+
43
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="],
44
+
45
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="],
46
+
47
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="],
48
+
49
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="],
50
+
51
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="],
52
+
53
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="],
54
+
55
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="],
56
+
57
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="],
58
+
59
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="],
60
+
61
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="],
62
+
63
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="],
64
+
65
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="],
66
+
67
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="],
68
+
69
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="],
70
+
71
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="],
72
+
73
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="],
74
+
75
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="],
76
+
77
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="],
78
+
79
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="],
80
+
81
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="],
82
+
83
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="],
84
+
85
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
86
+
87
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
88
+
89
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
90
+
91
+ "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
92
+
93
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
94
+
95
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
96
+
97
+ "@mediabunny/aac-encoder": ["@mediabunny/aac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JNzgdJoHMFFnv5imi1+dmjZMudsJ1zNCUCEkKjBh90cqGhAFg8xu4V2gsyxE2i6oq/YpWx23P+OvoANLSMcDzA=="],
98
+
99
+ "@mediabunny/flac-encoder": ["@mediabunny/flac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-VpKmJO0xlYcFCRD6JvJlMbNQ6d/6YMHdO1gFIqWlZABHjSSL6BquNNEgWSCv5vdF8ELDBwIYBVZEslakIB/7GA=="],
100
+
101
+ "@mediabunny/mp3-encoder": ["@mediabunny/mp3-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JyzZyGeGRm2HVUQaGJ/VZT9OG+kG00mA8SLP/f3CO7+qWAmBncKc16WYXWHbZEo8Jn/ZGA6De32S5R2bTQbDqA=="],
102
+
103
+ "@module-federation/error-codes": ["@module-federation/error-codes@0.22.0", "", {}, "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug=="],
104
+
105
+ "@module-federation/runtime": ["@module-federation/runtime@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/runtime-core": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA=="],
106
+
107
+ "@module-federation/runtime-core": ["@module-federation/runtime-core@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA=="],
108
+
109
+ "@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/webpack-bundler-runtime": "0.22.0" } }, "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA=="],
110
+
111
+ "@module-federation/sdk": ["@module-federation/sdk@0.22.0", "", {}, "sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g=="],
112
+
113
+ "@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA=="],
114
+
115
+ "@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=="],
116
+
117
+ "@remotion/bundler": ["@remotion/bundler@4.0.483", "", { "dependencies": { "@remotion/media-parser": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@rspack/core": "1.7.11", "@rspack/plugin-react-refresh": "1.6.1", "css-loader": "7.1.4", "esbuild": "0.28.1", "react-refresh": "0.18.0", "remotion": "4.0.483", "style-loader": "4.0.0", "webpack": "5.105.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-5fQRMYgr2sxZPBOThnIVuFwHBq/FhusJ+Ke6xopga8io8ecK/mj9GaRXC3tgfMa+YWuu8ZSXZ0U9EsMZjjP5YQ=="],
118
+
119
+ "@remotion/canvas-capture": ["@remotion/canvas-capture@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JABgbfvXwjFp1E61tlDN9gVAH8OoeF4kUUELNwG9kcNOE4ex8+vCYEO6VKIaXZ4l8A1PEAQ5EK//NheTJ80gfw=="],
120
+
121
+ "@remotion/cli": ["@remotion/cli@4.0.483", "", { "dependencies": { "@remotion/bundler": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-server": "4.0.483", "@remotion/studio-shared": "4.0.483", "dotenv": "17.3.1", "minimist": "1.2.6", "prompts": "2.4.2", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" }, "bin": { "remotion": "remotion-cli.js", "remotionb": "remotionb-cli.js", "remotiond": "remotiond-cli.js" } }, "sha512-z4TQcgTfQbSIV4GQpCvIihDL77M+leQelbxv962PmfSKTT7z3XnNN732PcZ4sei2+Xg+d2SD95K4tI5XBYs5Gw=="],
122
+
123
+ "@remotion/compositor-darwin-arm64": ["@remotion/compositor-darwin-arm64@4.0.483", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CkEJXouGEoCs5PX3KOufkXrlT/Kgn0ZF7SEQ4meCYGYMZD+QPVtsmS1MXH8pQ4RHlFO6Tk7g0CIHMT3Y4yzpuA=="],
124
+
125
+ "@remotion/compositor-darwin-x64": ["@remotion/compositor-darwin-x64@4.0.483", "", { "os": "darwin", "cpu": "x64" }, "sha512-vDZK5U8FYbHGMjFC2lUgJRBz8KXwbwFSvEQi8FATD0roNg75SoaEJWrqAOIVv8v5eBjPvo18znDc36NLRYn1Eg=="],
126
+
127
+ "@remotion/compositor-linux-arm64-gnu": ["@remotion/compositor-linux-arm64-gnu@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-1LzfYDY/DQxy3MIc9pCbTn1ObcBDcyI6MzODOwe1bTZl8TZxdUUt1M3hDrQ60AB6iHwruBAnzT9dnogiMIdSew=="],
128
+
129
+ "@remotion/compositor-linux-arm64-musl": ["@remotion/compositor-linux-arm64-musl@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-nG1btxg0HXuLzulIqAg9NnxWyewZNrA0iLe82HdniaJjeWLORreGo4cEEJz1SjbDpQuPEY562XGkTO2DLKK5mA=="],
130
+
131
+ "@remotion/compositor-linux-x64-gnu": ["@remotion/compositor-linux-x64-gnu@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-CV4h6r2rNYh4P8utUzP6RM2vW2vq43nA3IvVOwRSuh9LwJh/7rwG53Oco4HanY/sstaNuymGpT57wdXwONU5CQ=="],
132
+
133
+ "@remotion/compositor-linux-x64-musl": ["@remotion/compositor-linux-x64-musl@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-moKvavbkoz5nteJZA4K6LMgTTlewhwIbtO7DYARZ3LK3ClGUKnYfFcmaPS15hMun02JPTOMIWbrlaszdR75mxA=="],
134
+
135
+ "@remotion/compositor-win32-x64-msvc": ["@remotion/compositor-win32-x64-msvc@4.0.483", "", { "os": "win32", "cpu": "x64" }, "sha512-eDpWe6Vy7ySHugwxlgaeohqdBwR1etxiymXzT13cgbPw2+p6d55z1tJ7VPTXyfu0o+UdyRTauWqD4msoxN0wow=="],
136
+
137
+ "@remotion/licensing": ["@remotion/licensing@4.0.483", "", {}, "sha512-GRtjykrxMmB5Cjpq1oVqeYIRXI95vid6afX0LTLfp1shD6MR4lTZRoRuopxrrZp1E4XFGXoY64b6dlIudgTyBQ=="],
138
+
139
+ "@remotion/media-parser": ["@remotion/media-parser@4.0.483", "", {}, "sha512-iva9Eof7QQX+3hGxH/N8pGi80wgdGuzOr825Zn7IuEe7IWdtRYWlFpCEghmyfhrwgaWa7RY51wg77ycR3c3nRg=="],
140
+
141
+ "@remotion/media-utils": ["@remotion/media-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4T4WQh/U95kCBzgmz/EL/HL8Zeox/AKAL5ufsehrZFgwlcvH1EsKNJH/RWaAtNPRLF+pskEOgFzPYaczHeI8hg=="],
142
+
143
+ "@remotion/player": ["@remotion/player@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yyIQ9vinUqqS0fQeL52bPCWQIr8qDXCqQ4iys8P7dSZncdu8V29p4W2a0/4eKV8bv5+mjnJQ/U6nl9NxBF1hdA=="],
144
+
145
+ "@remotion/renderer": ["@remotion/renderer@4.0.483", "", { "dependencies": { "@remotion/licensing": "4.0.483", "@remotion/streaming": "4.0.483", "execa": "5.1.1", "remotion": "4.0.483", "source-map": "0.8.0-beta.0", "ws": "8.21.0" }, "optionalDependencies": { "@remotion/compositor-darwin-arm64": "4.0.483", "@remotion/compositor-darwin-x64": "4.0.483", "@remotion/compositor-linux-arm64-gnu": "4.0.483", "@remotion/compositor-linux-arm64-musl": "4.0.483", "@remotion/compositor-linux-x64-gnu": "4.0.483", "@remotion/compositor-linux-x64-musl": "4.0.483", "@remotion/compositor-win32-x64-msvc": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-eSKdQqm8rcl+GNyOhFsBgcPYWMcxTJWHL5xaNrd037piCaL3sdJ57OEO/AbfEvvOO14zwUvlsONKjlkLlEVyKg=="],
146
+
147
+ "@remotion/streaming": ["@remotion/streaming@4.0.483", "", {}, "sha512-96rqrk+l5AfriHOqmqxMn8rI6UJfFY7r5UMDZoSKqXWzTOwj+0VWHTRl9ilZQMXhYACaMSA/5yrL9jgQEK8Yuw=="],
148
+
149
+ "@remotion/studio": ["@remotion/studio@4.0.483", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.31", "@remotion/canvas-capture": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@remotion/web-renderer": "4.0.483", "@remotion/zod-types": "4.0.483", "mediabunny": "1.47.0", "memfs": "3.4.3", "open": "8.4.2", "remotion": "4.0.483", "semver": "7.5.3", "zod": "4.3.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-gNa1Lw8NmHl0jwFb5fk7rzA+WFTJQpGDT/49A38t9jpEwoF+h1mKTgY8gA202apzjBHrEECdFE450npnBOUpUw=="],
150
+
151
+ "@remotion/studio-server": ["@remotion/studio-server@4.0.483", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", "@remotion/bundler": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "memfs": "3.4.3", "open": "8.4.2", "prettier": "3.8.1", "recast": "0.23.11", "remotion": "4.0.483", "semver": "7.5.3" } }, "sha512-2FSLbVN5N8bgtQPX+RQRbis557tJJnVTOZuEBZndfC9NOoPdARlSgEnwVer9tBNczUlc6B3KrPxyPSlS3UjL+Q=="],
152
+
153
+ "@remotion/studio-shared": ["@remotion/studio-shared@4.0.483", "", { "dependencies": { "remotion": "4.0.483" } }, "sha512-aXxBYUgsWgphHVq7T7bz+ICMGzfii7pcX1IxS5hbLMLJHqlDtk9g+qcxm4kJ2Fjj/Gb5gERKiNzYym8WZTIM2Q=="],
154
+
155
+ "@remotion/timeline-utils": ["@remotion/timeline-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0" } }, "sha512-KTTMdpNA5uRLX+iisAITO+V9cJBk17F8EWvuUnAEVmAFOQTbGIyPI9HNw5pZmL7SlzOJdFjAtksTjipeYGkEug=="],
156
+
157
+ "@remotion/web-renderer": ["@remotion/web-renderer@4.0.483", "", { "dependencies": { "@mediabunny/aac-encoder": "1.47.0", "@mediabunny/flac-encoder": "1.47.0", "@mediabunny/mp3-encoder": "1.47.0", "@remotion/licensing": "4.0.483", "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-14iURfVWA/hcF/rJvkid1ZR5nmnVhkTIf071FabCFi6kdViOSVBugSglJ8tUPvWVbWmxlXGDGQD9CSU18IATww=="],
158
+
159
+ "@remotion/zod-types": ["@remotion/zod-types@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "zod": "4.3.6" } }, "sha512-KIVYIzFpZBDB0wxGGQu5tDBr4XOYRzvrPXjmo6O/FI5Xx7O8hgvJmBs9VDkEwonAOft86sg79hI19F1DTX1p4w=="],
160
+
161
+ "@rspack/binding": ["@rspack/binding@1.7.11", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.7.11", "@rspack/binding-darwin-x64": "1.7.11", "@rspack/binding-linux-arm64-gnu": "1.7.11", "@rspack/binding-linux-arm64-musl": "1.7.11", "@rspack/binding-linux-x64-gnu": "1.7.11", "@rspack/binding-linux-x64-musl": "1.7.11", "@rspack/binding-wasm32-wasi": "1.7.11", "@rspack/binding-win32-arm64-msvc": "1.7.11", "@rspack/binding-win32-ia32-msvc": "1.7.11", "@rspack/binding-win32-x64-msvc": "1.7.11" } }, "sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q=="],
162
+
163
+ "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.7.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig=="],
164
+
165
+ "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.7.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA=="],
166
+
167
+ "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA=="],
168
+
169
+ "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw=="],
170
+
171
+ "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ=="],
172
+
173
+ "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg=="],
174
+
175
+ "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.7.11", "", { "dependencies": { "@napi-rs/wasm-runtime": "1.0.7" }, "cpu": "none" }, "sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ=="],
176
+
177
+ "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.7.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA=="],
178
+
179
+ "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.7.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw=="],
180
+
181
+ "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.7.11", "", { "os": "win32", "cpu": "x64" }, "sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q=="],
182
+
183
+ "@rspack/core": ["@rspack/core@1.7.11", "", { "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.11", "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew=="],
184
+
185
+ "@rspack/lite-tapable": ["@rspack/lite-tapable@1.1.0", "", {}, "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw=="],
186
+
187
+ "@rspack/plugin-react-refresh": ["@rspack/plugin-react-refresh@1.6.1", "", { "dependencies": { "error-stack-parser": "^2.1.4", "html-entities": "^2.6.0" }, "peerDependencies": { "react-refresh": ">=0.10.0 <1.0.0", "webpack-hot-middleware": "2.x" }, "optionalPeers": ["webpack-hot-middleware"] }, "sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw=="],
188
+
189
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="],
190
+
191
+ "@types/dom-mediacapture-transform": ["@types/dom-mediacapture-transform@0.1.11", "", { "dependencies": { "@types/dom-webcodecs": "*" } }, "sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ=="],
192
+
193
+ "@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="],
194
+
195
+ "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="],
196
+
197
+ "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="],
198
+
199
+ "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
200
+
201
+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
202
+
203
+ "@types/node": ["@types/node@26.0.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw=="],
204
+
205
+ "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="],
206
+
207
+ "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
208
+
209
+ "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="],
210
+
211
+ "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="],
212
+
213
+ "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="],
214
+
215
+ "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="],
216
+
217
+ "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="],
218
+
219
+ "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="],
220
+
221
+ "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="],
222
+
223
+ "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="],
224
+
225
+ "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="],
226
+
227
+ "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="],
228
+
229
+ "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="],
230
+
231
+ "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="],
232
+
233
+ "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="],
234
+
235
+ "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="],
236
+
237
+ "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="],
238
+
239
+ "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="],
240
+
241
+ "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="],
242
+
243
+ "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
244
+
245
+ "acorn-import-phases": ["acorn-import-phases@1.0.4", "", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="],
246
+
247
+ "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="],
248
+
249
+ "ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
250
+
251
+ "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="],
252
+
253
+ "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
254
+
255
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.10.40", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw=="],
256
+
257
+ "browserslist": ["browserslist@4.28.4", "", { "dependencies": { "baseline-browser-mapping": "^2.10.38", "caniuse-lite": "^1.0.30001799", "electron-to-chromium": "^1.5.376", "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw=="],
258
+
259
+ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
260
+
261
+ "caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="],
262
+
263
+ "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
264
+
265
+ "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
266
+
267
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
268
+
269
+ "css-loader": ["css-loader@7.1.4", "", { "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.40", "postcss-modules-extract-imports": "^3.1.0", "postcss-modules-local-by-default": "^4.0.5", "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.6.3" }, "peerDependencies": { "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "webpack": "^5.27.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw=="],
270
+
271
+ "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
272
+
273
+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
274
+
275
+ "define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
276
+
277
+ "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="],
278
+
279
+ "electron-to-chromium": ["electron-to-chromium@1.5.379", "", {}, "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA=="],
280
+
281
+ "enhanced-resolve": ["enhanced-resolve@5.24.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw=="],
282
+
283
+ "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="],
284
+
285
+ "es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="],
286
+
287
+ "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="],
288
+
289
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
290
+
291
+ "eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="],
292
+
293
+ "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
294
+
295
+ "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
296
+
297
+ "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="],
298
+
299
+ "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
300
+
301
+ "execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
302
+
303
+ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
304
+
305
+ "fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="],
306
+
307
+ "fs-monkey": ["fs-monkey@1.0.3", "", {}, "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="],
308
+
309
+ "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
310
+
311
+ "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="],
312
+
313
+ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
314
+
315
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
316
+
317
+ "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
318
+
319
+ "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
320
+
321
+ "icss-utils": ["icss-utils@5.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="],
322
+
323
+ "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
324
+
325
+ "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
326
+
327
+ "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
328
+
329
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
330
+
331
+ "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="],
332
+
333
+ "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
334
+
335
+ "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
336
+
337
+ "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
338
+
339
+ "loader-runner": ["loader-runner@4.3.2", "", {}, "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w=="],
340
+
341
+ "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="],
342
+
343
+ "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
344
+
345
+ "mediabunny": ["mediabunny@1.47.0", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-XQMZAcaKPkJ7hQ/Q2fvBdl3ZazQl2WVxDysUbJWh4PuAnLoerdsQBdPTDWdUdK6hh26LQ8Ue94MLLnmpWvlUYg=="],
346
+
347
+ "memfs": ["memfs@3.4.3", "", { "dependencies": { "fs-monkey": "1.0.3" } }, "sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg=="],
348
+
349
+ "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
350
+
351
+ "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
352
+
353
+ "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
354
+
355
+ "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
356
+
357
+ "minimist": ["minimist@1.2.6", "", {}, "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="],
358
+
359
+ "nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
360
+
361
+ "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
362
+
363
+ "node-releases": ["node-releases@2.0.50", "", {}, "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg=="],
364
+
365
+ "npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
366
+
367
+ "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
368
+
369
+ "open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
370
+
371
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
372
+
373
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
374
+
375
+ "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
376
+
377
+ "postcss-modules-extract-imports": ["postcss-modules-extract-imports@3.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q=="],
378
+
379
+ "postcss-modules-local-by-default": ["postcss-modules-local-by-default@4.2.0", "", { "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw=="],
380
+
381
+ "postcss-modules-scope": ["postcss-modules-scope@3.2.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA=="],
382
+
383
+ "postcss-modules-values": ["postcss-modules-values@4.0.0", "", { "dependencies": { "icss-utils": "^5.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ=="],
384
+
385
+ "postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="],
386
+
387
+ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
388
+
389
+ "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
390
+
391
+ "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
392
+
393
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
394
+
395
+ "react": ["react@19.2.7", "", {}, "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ=="],
396
+
397
+ "react-dom": ["react-dom@19.2.7", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.7" } }, "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ=="],
398
+
399
+ "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
400
+
401
+ "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="],
402
+
403
+ "remotion": ["remotion@4.0.483", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-lf4xq4Twn75TQeTavFLrTE4zdck7EKBSx07ZrPv4om40Sist+3G0kq7NNzSjMeJ6G2Wx6vI+0oICD/vv4sGWtg=="],
404
+
405
+ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
406
+
407
+ "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
408
+
409
+ "schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="],
410
+
411
+ "semver": ["semver@7.5.3", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ=="],
412
+
413
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
414
+
415
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
416
+
417
+ "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
418
+
419
+ "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
420
+
421
+ "source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="],
422
+
423
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
424
+
425
+ "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
426
+
427
+ "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
428
+
429
+ "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
430
+
431
+ "style-loader": ["style-loader@4.0.0", "", { "peerDependencies": { "webpack": "^5.27.0" } }, "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA=="],
432
+
433
+ "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
434
+
435
+ "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
436
+
437
+ "terser": ["terser@5.48.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-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q=="],
438
+
439
+ "terser-webpack-plugin": ["terser-webpack-plugin@5.6.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ=="],
440
+
441
+ "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
442
+
443
+ "to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="],
444
+
445
+ "tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="],
446
+
447
+ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
448
+
449
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
450
+
451
+ "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
452
+
453
+ "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=="],
454
+
455
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
456
+
457
+ "watchpack": ["watchpack@2.5.2", "", { "dependencies": { "graceful-fs": "^4.1.2" } }, "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg=="],
458
+
459
+ "webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
460
+
461
+ "webpack": ["webpack@5.105.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.19.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.16", "watchpack": "^2.5.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw=="],
462
+
463
+ "webpack-sources": ["webpack-sources@3.5.0", "", {}, "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ=="],
464
+
465
+ "whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="],
466
+
467
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
468
+
469
+ "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
470
+
471
+ "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
472
+
473
+ "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
474
+
475
+ "css-loader/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
476
+
477
+ "esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
478
+
479
+ "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
480
+
481
+ "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
482
+ }
483
+ }
artifacts/glm52-rise-video/out/june-totals.png ADDED
artifacts/glm52-rise-video/package.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "glm52-rise-video",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "render": "remotion render src/index.tsx GLM52Rise out/glm-52-broke-out.mp4 --codec h264 --pixel-format yuv420p",
7
+ "render:sheep": "remotion render src/index.tsx NZSheep out/nz-sheep.mp4 --codec h264 --pixel-format yuv420p",
8
+ "render:novel": "remotion render src/index.tsx NovelTokens out/novel-1984.mp4 --codec h264 --pixel-format yuv420p",
9
+ "render:flash": "remotion render src/index.tsx FlashShare out/flash-share.mp4 --codec h264 --pixel-format yuv420p",
10
+ "render:minimax": "remotion render src/index.tsx MiniMaxClimb out/minimax-climb.mp4 --codec h264 --pixel-format yuv420p",
11
+ "still:june": "remotion still src/index.tsx JuneTotals out/june-totals.png --frame=0"
12
+ },
13
+ "dependencies": {
14
+ "@remotion/cli": "^4.0.384",
15
+ "react": "^19.2.3",
16
+ "react-dom": "^19.2.3",
17
+ "remotion": "^4.0.384"
18
+ },
19
+ "devDependencies": {
20
+ "@types/react": "^19.2.8",
21
+ "@types/react-dom": "^19.2.3",
22
+ "typescript": "^5.8.2"
23
+ }
24
+ }
artifacts/glm52-rise-video/src/data.ts ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Verified against the production opencode-stats PlanetScale DB.
2
+ // Scope: tier='Go' (OpenCode Go), dataset='zen', client='all', source='all', grain='day'.
3
+ // metric = total_tokens. Daily token volume per model; GLM-5.2 (zhipu) launched Jun 17.
4
+ // Segments per day (tokens): glm-5.2, deepseek-v4-flash, deepseek-v4-pro, minimax-m3, all others.
5
+
6
+ export type Day = {
7
+ date: string
8
+ total: number
9
+ glm: number
10
+ dsf: number
11
+ dsp: number
12
+ mm: number
13
+ others: number
14
+ }
15
+
16
+ export const days: Day[] = [
17
+ {
18
+ date: "Jun 12",
19
+ total: 2_283_799_449_383,
20
+ glm: 0,
21
+ dsf: 1_176_701_653_509,
22
+ dsp: 569_527_034_307,
23
+ mm: 159_016_250_684,
24
+ others: 378_554_510_883,
25
+ },
26
+ {
27
+ date: "Jun 13",
28
+ total: 2_008_462_388_420,
29
+ glm: 0,
30
+ dsf: 995_338_131_997,
31
+ dsp: 445_817_536_548,
32
+ mm: 211_743_241_967,
33
+ others: 355_563_477_908,
34
+ },
35
+ {
36
+ date: "Jun 14",
37
+ total: 2_007_785_405_251,
38
+ glm: 0,
39
+ dsf: 983_954_176_228,
40
+ dsp: 428_151_999_341,
41
+ mm: 262_476_527_930,
42
+ others: 333_202_701_752,
43
+ },
44
+ {
45
+ date: "Jun 15",
46
+ total: 2_694_736_103_062,
47
+ glm: 0,
48
+ dsf: 1_255_893_953_859,
49
+ dsp: 632_223_338_376,
50
+ mm: 352_507_442_991,
51
+ others: 454_111_367_836,
52
+ },
53
+ {
54
+ date: "Jun 16",
55
+ total: 2_838_153_758_908,
56
+ glm: 0,
57
+ dsf: 1_336_625_283_800,
58
+ dsp: 676_480_415_730,
59
+ mm: 305_268_829_013,
60
+ others: 519_779_230_365,
61
+ },
62
+ {
63
+ date: "Jun 17",
64
+ total: 2_778_964_711_109,
65
+ glm: 70_095_977_043,
66
+ dsf: 1_339_831_523_555,
67
+ dsp: 660_414_395_220,
68
+ mm: 251_302_096_157,
69
+ others: 457_320_719_134,
70
+ },
71
+ {
72
+ date: "Jun 18",
73
+ total: 2_806_992_430_656,
74
+ glm: 201_130_231_172,
75
+ dsf: 1_295_599_996_869,
76
+ dsp: 595_665_008_776,
77
+ mm: 322_205_104_324,
78
+ others: 392_392_089_515,
79
+ },
80
+ {
81
+ date: "Jun 19",
82
+ total: 2_419_611_630_232,
83
+ glm: 199_086_413_910,
84
+ dsf: 1_115_750_468_802,
85
+ dsp: 475_965_869_304,
86
+ mm: 303_586_698_735,
87
+ others: 325_222_179_481,
88
+ },
89
+ {
90
+ date: "Jun 20",
91
+ total: 2_188_278_916_865,
92
+ glm: 193_931_516_396,
93
+ dsf: 1_050_194_681_012,
94
+ dsp: 395_303_435_278,
95
+ mm: 281_998_000_337,
96
+ others: 266_851_283_842,
97
+ },
98
+ {
99
+ date: "Jun 21",
100
+ total: 2_042_309_961_344,
101
+ glm: 181_894_043_118,
102
+ dsf: 985_164_570_580,
103
+ dsp: 368_194_079_542,
104
+ mm: 259_812_551_324,
105
+ others: 247_244_716_780,
106
+ },
107
+ {
108
+ date: "Jun 22",
109
+ total: 2_893_934_325_663,
110
+ glm: 301_759_048_475,
111
+ dsf: 1_298_124_282_989,
112
+ dsp: 581_012_596_194,
113
+ mm: 371_581_117_839,
114
+ others: 341_457_280_166,
115
+ },
116
+ {
117
+ date: "Jun 23",
118
+ total: 3_109_009_321_480,
119
+ glm: 282_277_235_158,
120
+ dsf: 1_423_571_678_821,
121
+ dsp: 627_374_654_587,
122
+ mm: 429_416_300_508,
123
+ others: 346_369_452_406,
124
+ },
125
+ {
126
+ date: "Jun 24",
127
+ total: 2_939_149_971_595,
128
+ glm: 256_497_442_533,
129
+ dsf: 1_373_583_023_234,
130
+ dsp: 601_270_997_775,
131
+ mm: 391_586_493_231,
132
+ others: 316_212_014_822,
133
+ },
134
+ {
135
+ date: "Jun 25",
136
+ total: 3_029_641_552_948,
137
+ glm: 256_279_657_734,
138
+ dsf: 1_481_084_002_776,
139
+ dsp: 602_077_167_287,
140
+ mm: 375_985_302_874,
141
+ others: 314_215_422_277,
142
+ },
143
+ ]
144
+
145
+ export const launchIndex = 5 // Jun 17, first day of GLM-5.2 usage
146
+ // GLM-5.2 weekly token volume, Jun 19-25 (sum of glm): 1,671,725,357,324 = 1.67T
147
+ export const glmWeekTokensT = 1.672
148
+
149
+ // stacked segments, bottom -> top. GLM-5.2 is the hero (blue); the rest are the field it cut into.
150
+ export const segments = [
151
+ { key: "glm", label: "GLM-5.2", color: "#3b5cf6", hero: true },
152
+ { key: "dsf", label: "deepseek-v4-flash", color: "#9ca3ad" },
153
+ { key: "dsp", label: "deepseek-v4-pro", color: "#b3b9c1" },
154
+ { key: "mm", label: "minimax-m3", color: "#c8cdd3" },
155
+ { key: "others", label: "other models", color: "#dde0e4" },
156
+ ] as const
artifacts/glm52-rise-video/src/flash.tsx ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill, Easing, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"
3
+
4
+ // stats.opencode.ai design tokens (light theme)
5
+ const c = {
6
+ bg: "#ffffff",
7
+ ink: "#161616",
8
+ muted: "#5c5c5c",
9
+ faint: "#808080",
10
+ line: "#e6e6e6",
11
+ dot: "#e4e4e4",
12
+ gray: "#aab0b8",
13
+ accent: "#3b5cf6",
14
+ accentHi: "#5b78ff",
15
+ }
16
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
17
+
18
+ const DOT_MASK =
19
+ "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
20
+
21
+ // verified: OpenCode Go, week of Jun 22-28, 2026 (2026-W26). share = % of 19.64T total Go tokens.
22
+ const bars = [
23
+ { label: "deepseek-v4-flash", share: 48.3, hero: true },
24
+ { label: "deepseek-v4-pro", share: 19.4 },
25
+ { label: "minimax-m3", share: 13.0 },
26
+ { label: "glm-5.2", share: 8.3 },
27
+ { label: "mimo-v2.5", share: 4.3 },
28
+ { label: "kimi-k2.7-code", share: 2.6 },
29
+ { label: "other models", share: 4.1 },
30
+ ]
31
+
32
+ function DataWordmark({ height = 30 }: { height?: number }) {
33
+ return (
34
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
35
+ <path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
36
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
37
+ <path
38
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
39
+ fill="currentColor"
40
+ />
41
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
42
+ <path
43
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
44
+ fill="currentColor"
45
+ />
46
+ <path
47
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
48
+ fill="currentColor"
49
+ />
50
+ </svg>
51
+ )
52
+ }
53
+
54
+ export function FlashShare() {
55
+ const frame = useCurrentFrame()
56
+ const { fps } = useVideoConfig()
57
+
58
+ const grow = (i: number) =>
59
+ Math.min(
60
+ 1,
61
+ Math.max(0, spring({ frame: frame - 18 - i * 7, fps, config: { damping: 18, stiffness: 120, mass: 0.6 } })),
62
+ )
63
+
64
+ return (
65
+ <AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
66
+ <div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
67
+ {/* header */}
68
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
69
+ <DataWordmark height={30} />
70
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 22–28, 2026</div>
71
+ </div>
72
+
73
+ {/* headline (static) */}
74
+ <div style={{ marginTop: 50 }}>
75
+ <div style={{ fontSize: 23, fontWeight: 600, color: c.muted, letterSpacing: 2 }}>
76
+ OPENCODE GO · SHARE OF TOKENS
77
+ </div>
78
+ <div
79
+ style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 24, marginTop: 14 }}
80
+ >
81
+ <div style={{ fontSize: 62, fontWeight: 600, letterSpacing: -2, lineHeight: 1 }}>DeepSeek V4 Flash</div>
82
+ <div
83
+ style={{
84
+ fontSize: 88,
85
+ fontWeight: 600,
86
+ letterSpacing: -2,
87
+ lineHeight: 1,
88
+ color: c.accent,
89
+ fontVariantNumeric: "tabular-nums",
90
+ }}
91
+ >
92
+ 48%
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ {/* bar chart */}
98
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center", gap: 16 }}>
99
+ {bars.map((b, i) => {
100
+ const g = grow(i)
101
+ const pct = b.share * g
102
+ return (
103
+ <div key={b.label} style={{ display: "flex", alignItems: "center", gap: 18 }}>
104
+ <div
105
+ style={{
106
+ width: 268,
107
+ fontSize: 23,
108
+ fontWeight: b.hero ? 600 : 500,
109
+ color: b.hero ? c.ink : c.muted,
110
+ textAlign: "right",
111
+ whiteSpace: "nowrap",
112
+ }}
113
+ >
114
+ {b.label}
115
+ </div>
116
+ <div style={{ position: "relative", flex: 1, height: 48 }}>
117
+ {/* dotted 100% track — height is a multiple of the 12px tile, anchored bottom, so dots never clip */}
118
+ <div
119
+ style={{
120
+ position: "absolute",
121
+ inset: 0,
122
+ background: c.dot,
123
+ WebkitMaskImage: DOT_MASK,
124
+ maskImage: DOT_MASK,
125
+ WebkitMaskSize: "12px 12px",
126
+ maskSize: "12px 12px",
127
+ WebkitMaskRepeat: "repeat",
128
+ maskRepeat: "repeat",
129
+ WebkitMaskPosition: "left bottom",
130
+ maskPosition: "left bottom",
131
+ }}
132
+ />
133
+ {/* fill */}
134
+ <div
135
+ style={{
136
+ position: "absolute",
137
+ left: 0,
138
+ top: 0,
139
+ bottom: 0,
140
+ width: `${pct}%`,
141
+ background: b.hero ? c.accent : c.gray,
142
+ borderRight: b.hero ? `2px solid ${c.accentHi}` : "none",
143
+ }}
144
+ />
145
+ </div>
146
+ <div
147
+ style={{
148
+ width: 84,
149
+ fontSize: 24,
150
+ fontWeight: b.hero ? 600 : 500,
151
+ color: b.hero ? c.accent : c.muted,
152
+ textAlign: "right",
153
+ fontVariantNumeric: "tabular-nums",
154
+ }}
155
+ >
156
+ {Math.round(pct)}%
157
+ </div>
158
+ </div>
159
+ )
160
+ })}
161
+ </div>
162
+
163
+ {/* footer */}
164
+ <div
165
+ style={{
166
+ display: "flex",
167
+ justifyContent: "space-between",
168
+ alignItems: "center",
169
+ marginTop: 24,
170
+ paddingTop: 22,
171
+ borderTop: `1px solid ${c.line}`,
172
+ fontSize: 20,
173
+ fontWeight: 500,
174
+ }}
175
+ >
176
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
177
+ <span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
178
+ DeepSeek V4 Flash · 9.48T tokens · 83.6M requests
179
+ </div>
180
+ <div style={{ color: c.ink }}>opencode.ai/data</div>
181
+ </div>
182
+ </div>
183
+ </AbsoluteFill>
184
+ )
185
+ }
artifacts/glm52-rise-video/src/index.tsx ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Composition, registerRoot } from "remotion"
2
+ import { GLM52Rise } from "./video"
3
+ import { NZSheep } from "./sheep"
4
+ import { NovelTokens } from "./novel"
5
+ import { FlashShare } from "./flash"
6
+ import { MiniMaxClimb } from "./minimax"
7
+ import { JuneTotals } from "./june"
8
+
9
+ function Root() {
10
+ return (
11
+ <>
12
+ <Composition id="GLM52Rise" component={GLM52Rise} durationInFrames={240} fps={30} width={1080} height={1080} />
13
+ <Composition id="NZSheep" component={NZSheep} durationInFrames={150} fps={30} width={1080} height={1080} />
14
+ <Composition
15
+ id="NovelTokens"
16
+ component={NovelTokens}
17
+ durationInFrames={150}
18
+ fps={30}
19
+ width={1080}
20
+ height={1080}
21
+ />
22
+ <Composition id="FlashShare" component={FlashShare} durationInFrames={165} fps={30} width={1080} height={1080} />
23
+ <Composition
24
+ id="MiniMaxClimb"
25
+ component={MiniMaxClimb}
26
+ durationInFrames={165}
27
+ fps={30}
28
+ width={1080}
29
+ height={1080}
30
+ />
31
+ <Composition id="JuneTotals" component={JuneTotals} durationInFrames={1} fps={30} width={1080} height={1080} />
32
+ </>
33
+ )
34
+ }
35
+
36
+ registerRoot(Root)
artifacts/glm52-rise-video/src/june.tsx ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill } from "remotion"
3
+
4
+ const c = {
5
+ bg: "#ffffff",
6
+ ink: "#161616",
7
+ muted: "#5c5c5c",
8
+ faint: "#808080",
9
+ line: "#e6e6e6",
10
+ dot: "#dcdcdc",
11
+ accent: "#3b5cf6",
12
+ }
13
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
14
+
15
+ const DOT_MASK =
16
+ "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
17
+
18
+ // verified: OpenCode Go (tier=Go, dataset=zen), June 1-30, 2026.
19
+ // 72.78T tokens · 651.4M requests · 11.42M sessions -> rounded headline figures.
20
+
21
+ function DataWordmark({ height = 30 }: { height?: number }) {
22
+ return (
23
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
24
+ <path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
25
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
26
+ <path
27
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
28
+ fill="currentColor"
29
+ />
30
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
31
+ <path
32
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
33
+ fill="currentColor"
34
+ />
35
+ <path
36
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
37
+ fill="currentColor"
38
+ />
39
+ </svg>
40
+ )
41
+ }
42
+
43
+ function DotBand() {
44
+ return (
45
+ <div
46
+ style={{
47
+ height: 12,
48
+ background: c.dot,
49
+ WebkitMaskImage: DOT_MASK,
50
+ maskImage: DOT_MASK,
51
+ WebkitMaskSize: "12px 12px",
52
+ maskSize: "12px 12px",
53
+ WebkitMaskRepeat: "repeat",
54
+ maskRepeat: "repeat",
55
+ WebkitMaskPosition: "left top",
56
+ maskPosition: "left top",
57
+ }}
58
+ />
59
+ )
60
+ }
61
+
62
+ function Metric({ value, label }: { value: string; label: string }) {
63
+ return (
64
+ <div>
65
+ <div
66
+ style={{
67
+ fontSize: 92,
68
+ fontWeight: 600,
69
+ letterSpacing: -3,
70
+ lineHeight: 1,
71
+ fontVariantNumeric: "tabular-nums",
72
+ marginLeft: -8, // align the glyph's visual left edge to the column
73
+ }}
74
+ >
75
+ {value}
76
+ </div>
77
+ <div style={{ marginTop: 16, fontSize: 24, fontWeight: 500, color: c.muted, letterSpacing: 1 }}>{label}</div>
78
+ </div>
79
+ )
80
+ }
81
+
82
+ export function JuneTotals() {
83
+ return (
84
+ <AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
85
+ <div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
86
+ {/* header */}
87
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 22 }}>
88
+ <DataWordmark height={30} />
89
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>MONTHLY RECAP</div>
90
+ </div>
91
+ <DotBand />
92
+
93
+ {/* hero */}
94
+ <div style={{ flex: 1, display: "flex", flexDirection: "column", justifyContent: "center" }}>
95
+ <div style={{ fontSize: 25, fontWeight: 600, color: c.muted, letterSpacing: 3 }}>OPENCODE GO · JUNE 2026</div>
96
+ <div style={{ marginTop: 14 }}>
97
+ <div
98
+ style={{
99
+ fontSize: 300,
100
+ fontWeight: 600,
101
+ letterSpacing: -10,
102
+ lineHeight: 0.82,
103
+ color: c.accent,
104
+ marginLeft: -22,
105
+ }}
106
+ >
107
+ 73T
108
+ </div>
109
+ <div style={{ fontSize: 50, fontWeight: 600, color: c.ink, marginTop: 10 }}>tokens processed</div>
110
+ </div>
111
+
112
+ {/* supporting metrics */}
113
+ <div
114
+ style={{
115
+ display: "grid",
116
+ gridTemplateColumns: "1fr 1fr",
117
+ marginTop: 60,
118
+ paddingTop: 40,
119
+ borderTop: `1px solid ${c.line}`,
120
+ }}
121
+ >
122
+ <Metric value="650M" label="requests" />
123
+ <Metric value="11M" label="sessions" />
124
+ </div>
125
+ </div>
126
+
127
+ {/* footer */}
128
+ <DotBand />
129
+ <div
130
+ style={{
131
+ display: "flex",
132
+ justifyContent: "flex-end",
133
+ alignItems: "center",
134
+ marginTop: 22,
135
+ fontSize: 20,
136
+ fontWeight: 500,
137
+ }}
138
+ >
139
+ <div style={{ color: c.ink }}>opencode.ai/data</div>
140
+ </div>
141
+ </div>
142
+ </AbsoluteFill>
143
+ )
144
+ }
artifacts/glm52-rise-video/src/minimax.tsx ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"
3
+
4
+ const c = {
5
+ bg: "#ffffff",
6
+ ink: "#161616",
7
+ muted: "#5c5c5c",
8
+ faint: "#808080",
9
+ line: "#e6e6e6",
10
+ dot: "#e4e4e4",
11
+ accent: "#3b5cf6",
12
+ accentHi: "#5b78ff",
13
+ accentDim: "#aebcf3",
14
+ }
15
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
16
+
17
+ const DOT_MASK =
18
+ "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
19
+
20
+ // verified: minimax-m3, OpenCode Go (tier=Go, dataset=zen), weekly total_tokens.
21
+ // W26 2.559T is +23.2% / +482.3B vs W25 2.077T.
22
+ const weeks = [
23
+ { label: "May 25", t: 0.008 },
24
+ { label: "Jun 1", t: 0.429 },
25
+ { label: "Jun 8", t: 1.192 },
26
+ { label: "Jun 15", t: 2.077 },
27
+ { label: "Jun 22", t: 2.559, latest: true },
28
+ ]
29
+ const AXIS_MAX = 3.0
30
+
31
+ function DataWordmark({ height = 30 }: { height?: number }) {
32
+ return (
33
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.ink }}>
34
+ <path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
35
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
36
+ <path
37
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
38
+ fill="currentColor"
39
+ />
40
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
41
+ <path
42
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
43
+ fill="currentColor"
44
+ />
45
+ <path
46
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
47
+ fill="currentColor"
48
+ />
49
+ </svg>
50
+ )
51
+ }
52
+
53
+ const CHART_H = 420 // multiple of 12 so the dotted tracks never clip
54
+
55
+ export function MiniMaxClimb() {
56
+ const frame = useCurrentFrame()
57
+ const { fps } = useVideoConfig()
58
+
59
+ const grow = (i: number) =>
60
+ Math.min(
61
+ 1,
62
+ Math.max(0, spring({ frame: frame - 22 - i * 9, fps, config: { damping: 18, stiffness: 110, mass: 0.6 } })),
63
+ )
64
+
65
+ return (
66
+ <AbsoluteFill style={{ background: c.bg, color: c.ink, fontFamily: MONO, padding: 72, boxSizing: "border-box" }}>
67
+ <div style={{ height: "100%", display: "flex", flexDirection: "column" }}>
68
+ {/* header */}
69
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
70
+ <DataWordmark height={30} />
71
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 22–28, 2026</div>
72
+ </div>
73
+
74
+ {/* headline (static) */}
75
+ <div style={{ marginTop: 50 }}>
76
+ <div style={{ fontSize: 23, fontWeight: 600, color: c.muted, letterSpacing: 2 }}>
77
+ OPENCODE GO · WEEKLY TOKENS
78
+ </div>
79
+ <div
80
+ style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 24, marginTop: 14 }}
81
+ >
82
+ <div style={{ fontSize: 62, fontWeight: 600, letterSpacing: -2, lineHeight: 1 }}>MiniMax M3</div>
83
+ <div style={{ textAlign: "right", flexShrink: 0 }}>
84
+ <div
85
+ style={{
86
+ fontSize: 84,
87
+ fontWeight: 600,
88
+ letterSpacing: -2,
89
+ lineHeight: 1,
90
+ color: c.accent,
91
+ fontVariantNumeric: "tabular-nums",
92
+ }}
93
+ >
94
+ +23.2%
95
+ </div>
96
+ <div style={{ fontSize: 19, fontWeight: 500, color: c.muted, letterSpacing: 1, marginTop: 6 }}>
97
+ WEEK OVER WEEK
98
+ </div>
99
+ </div>
100
+ </div>
101
+ </div>
102
+
103
+ {/* column chart */}
104
+ <div style={{ flex: 1, display: "flex", alignItems: "flex-end", marginTop: 30 }}>
105
+ <div style={{ width: "100%", display: "flex", alignItems: "flex-end", gap: 30 }}>
106
+ {weeks.map((w, i) => {
107
+ const g = grow(i)
108
+ const h = Math.round((w.t / AXIS_MAX) * CHART_H * g)
109
+ return (
110
+ <div key={w.label} style={{ flex: 1, display: "flex", flexDirection: "column", alignItems: "center" }}>
111
+ {/* value + bar */}
112
+ <div style={{ position: "relative", width: "100%", height: CHART_H }}>
113
+ {/* dotted track */}
114
+ <div
115
+ style={{
116
+ position: "absolute",
117
+ inset: 0,
118
+ background: c.dot,
119
+ WebkitMaskImage: DOT_MASK,
120
+ maskImage: DOT_MASK,
121
+ WebkitMaskSize: "12px 12px",
122
+ maskSize: "12px 12px",
123
+ WebkitMaskRepeat: "repeat",
124
+ maskRepeat: "repeat",
125
+ WebkitMaskPosition: "left bottom",
126
+ maskPosition: "left bottom",
127
+ }}
128
+ />
129
+ {/* fill */}
130
+ <div
131
+ style={{
132
+ position: "absolute",
133
+ left: 0,
134
+ right: 0,
135
+ bottom: 0,
136
+ height: h,
137
+ background: w.latest ? c.accent : c.accentDim,
138
+ borderTop: w.latest ? `3px solid ${c.accentHi}` : "none",
139
+ }}
140
+ />
141
+ {/* value label */}
142
+ <div
143
+ style={{
144
+ position: "absolute",
145
+ left: 0,
146
+ right: 0,
147
+ bottom: h + 10,
148
+ textAlign: "center",
149
+ fontSize: 26,
150
+ fontWeight: w.latest ? 600 : 500,
151
+ color: w.latest ? c.accent : c.muted,
152
+ fontVariantNumeric: "tabular-nums",
153
+ opacity: interpolate(g, [0.5, 1], [0, 1], {
154
+ extrapolateLeft: "clamp",
155
+ extrapolateRight: "clamp",
156
+ }),
157
+ }}
158
+ >
159
+ {w.t.toFixed(2)}T
160
+ </div>
161
+ </div>
162
+ {/* week label */}
163
+ <div
164
+ style={{
165
+ marginTop: 14,
166
+ fontSize: 18,
167
+ fontWeight: 500,
168
+ color: w.latest ? c.ink : c.faint,
169
+ }}
170
+ >
171
+ {w.label}
172
+ </div>
173
+ </div>
174
+ )
175
+ })}
176
+ </div>
177
+ </div>
178
+
179
+ {/* footer */}
180
+ <div
181
+ style={{
182
+ display: "flex",
183
+ justifyContent: "space-between",
184
+ alignItems: "center",
185
+ marginTop: 22,
186
+ paddingTop: 22,
187
+ borderTop: `1px solid ${c.line}`,
188
+ fontSize: 20,
189
+ fontWeight: 500,
190
+ }}
191
+ >
192
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
193
+ <span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
194
+ 2.56T tokens last week · +482.3B added
195
+ </div>
196
+ <div style={{ color: c.ink }}>opencode.ai/data</div>
197
+ </div>
198
+ </div>
199
+ </AbsoluteFill>
200
+ )
201
+ }
artifacts/glm52-rise-video/src/novel.tsx ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill, Easing, Img, interpolate, staticFile, useCurrentFrame } from "remotion"
3
+
4
+ const c = {
5
+ white: "#ffffff",
6
+ dim: "rgba(255,255,255,0.74)",
7
+ }
8
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
9
+
10
+ // verified: OpenCode Go, week of Jun 22-28, 2026 (2026-W26)
11
+ // 19,642,742,937,105 tokens / 173,651,197 requests = 113,116 tokens/request
12
+ const AVG = 113116
13
+ const K = Math.round(AVG / 1000) // 113
14
+
15
+ const nf = new Intl.NumberFormat("en-US")
16
+
17
+ function DataWordmark({ height = 30 }: { height?: number }) {
18
+ return (
19
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.white }}>
20
+ <path opacity="0.35" d="M12 16H4V8H12V16Z" fill="currentColor" />
21
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
22
+ <path
23
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
24
+ fill="currentColor"
25
+ />
26
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
27
+ <path
28
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
29
+ fill="currentColor"
30
+ />
31
+ <path
32
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
33
+ fill="currentColor"
34
+ />
35
+ </svg>
36
+ )
37
+ }
38
+
39
+ export function NovelTokens() {
40
+ const frame = useCurrentFrame()
41
+
42
+ const k = Math.round(
43
+ K *
44
+ interpolate(frame, [18, 92], [0, 1], {
45
+ extrapolateLeft: "clamp",
46
+ extrapolateRight: "clamp",
47
+ easing: Easing.out(Easing.cubic),
48
+ }),
49
+ )
50
+
51
+ const zoom = interpolate(frame, [0, 150], [1.06, 1.12], {
52
+ extrapolateRight: "clamp",
53
+ easing: Easing.inOut(Easing.quad),
54
+ })
55
+
56
+ return (
57
+ <AbsoluteFill style={{ background: "#0c0c0c", overflow: "hidden" }}>
58
+ <Img
59
+ src={staticFile("book.jpg")}
60
+ style={{
61
+ position: "absolute",
62
+ width: "100%",
63
+ height: "100%",
64
+ objectFit: "cover",
65
+ objectPosition: "center 34%",
66
+ transform: `scale(${zoom})`,
67
+ transformOrigin: "center 30%",
68
+ }}
69
+ />
70
+
71
+ {/* legibility scrims */}
72
+ <div
73
+ style={{
74
+ position: "absolute",
75
+ inset: 0,
76
+ background:
77
+ "linear-gradient(to bottom, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0) 20%, rgba(0,0,0,0.1) 44%, rgba(0,0,0,0.86) 100%)",
78
+ }}
79
+ />
80
+
81
+ <div
82
+ style={{
83
+ position: "absolute",
84
+ inset: 0,
85
+ boxSizing: "border-box",
86
+ padding: 64,
87
+ color: c.white,
88
+ fontFamily: MONO,
89
+ display: "flex",
90
+ flexDirection: "column",
91
+ justifyContent: "space-between",
92
+ }}
93
+ >
94
+ {/* header */}
95
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
96
+ <DataWordmark height={30} />
97
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.dim, letterSpacing: 1 }}>JUN 22–28, 2026</div>
98
+ </div>
99
+
100
+ {/* bottom block */}
101
+ <div>
102
+ <div style={{ fontSize: 23, fontWeight: 600, color: c.dim, letterSpacing: 2, marginBottom: 8 }}>
103
+ OPENCODE GO · LAST WEEK
104
+ </div>
105
+ <div
106
+ style={{
107
+ fontSize: 168,
108
+ fontWeight: 600,
109
+ lineHeight: 0.92,
110
+ letterSpacing: -5,
111
+ fontVariantNumeric: "tabular-nums",
112
+ }}
113
+ >
114
+ {k}K
115
+ </div>
116
+ <div style={{ fontSize: 50, fontWeight: 600, letterSpacing: -1, marginTop: 4 }}>tokens per request</div>
117
+
118
+ <div
119
+ style={{
120
+ display: "flex",
121
+ justifyContent: "space-between",
122
+ alignItems: "center",
123
+ marginTop: 30,
124
+ fontSize: 20,
125
+ fontWeight: 500,
126
+ }}
127
+ >
128
+ <div style={{ color: c.dim }}>{nf.format(AVG)} tokens / request · last week</div>
129
+ <div style={{ color: c.white }}>opencode.ai/data</div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </AbsoluteFill>
134
+ )
135
+ }
artifacts/glm52-rise-video/src/sheep.tsx ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill, Easing, Img, interpolate, staticFile, useCurrentFrame } from "remotion"
3
+
4
+ const c = {
5
+ white: "#ffffff",
6
+ dim: "rgba(255,255,255,0.72)",
7
+ faint: "rgba(255,255,255,0.55)",
8
+ }
9
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
10
+
11
+ // verified: NZ OpenCode Go, week of Jun 22-28, 2026 (2026-W26)
12
+ const TOKENS = 40_915_594_381 // 40.9B
13
+ const SHEEP = 23_600_000 // 23.6M
14
+ const PER_SHEEP = Math.round(TOKENS / SHEEP) // 1,734
15
+ const nf = new Intl.NumberFormat("en-US")
16
+
17
+ // the correct opencode "DATA" wordmark (white, over photo)
18
+ function DataWordmark({ height = 30 }: { height?: number }) {
19
+ return (
20
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color: c.white }}>
21
+ <path opacity="0.35" d="M12 16H4V8H12V16Z" fill="currentColor" />
22
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
23
+ <path
24
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
25
+ fill="currentColor"
26
+ />
27
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
28
+ <path
29
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
30
+ fill="currentColor"
31
+ />
32
+ <path
33
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
34
+ fill="currentColor"
35
+ />
36
+ </svg>
37
+ )
38
+ }
39
+
40
+ export function NZSheep() {
41
+ const frame = useCurrentFrame()
42
+
43
+ const count = Math.round(
44
+ PER_SHEEP *
45
+ interpolate(frame, [18, 90], [0, 1], {
46
+ extrapolateLeft: "clamp",
47
+ extrapolateRight: "clamp",
48
+ easing: Easing.out(Easing.cubic),
49
+ }),
50
+ )
51
+
52
+ // slow Ken Burns push-in (scale up only — never reveals an edge)
53
+ const zoom = interpolate(frame, [0, 150], [1.06, 1.12], {
54
+ extrapolateRight: "clamp",
55
+ easing: Easing.inOut(Easing.quad),
56
+ })
57
+
58
+ return (
59
+ <AbsoluteFill style={{ background: "#0c0c0c", overflow: "hidden" }}>
60
+ {/* the sheep, staring */}
61
+ <Img
62
+ src={staticFile("sheep.jpg")}
63
+ style={{
64
+ position: "absolute",
65
+ width: "100%",
66
+ height: "100%",
67
+ objectFit: "cover",
68
+ objectPosition: "center 38%",
69
+ transform: `scale(${zoom})`,
70
+ transformOrigin: "center 35%",
71
+ }}
72
+ />
73
+
74
+ {/* legibility scrims */}
75
+ <div
76
+ style={{
77
+ position: "absolute",
78
+ inset: 0,
79
+ background:
80
+ "linear-gradient(to bottom, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0) 22%, rgba(0,0,0,0) 48%, rgba(0,0,0,0.78) 100%)",
81
+ }}
82
+ />
83
+
84
+ {/* content */}
85
+ <div
86
+ style={{
87
+ position: "absolute",
88
+ inset: 0,
89
+ boxSizing: "border-box",
90
+ padding: 64,
91
+ color: c.white,
92
+ fontFamily: MONO,
93
+ display: "flex",
94
+ flexDirection: "column",
95
+ justifyContent: "space-between",
96
+ }}
97
+ >
98
+ {/* header */}
99
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
100
+ <DataWordmark height={30} />
101
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.dim, letterSpacing: 1 }}>JUN 22–28, 2026</div>
102
+ </div>
103
+
104
+ {/* bottom block */}
105
+ <div>
106
+ <div style={{ fontSize: 23, fontWeight: 600, color: c.dim, letterSpacing: 2, marginBottom: 8 }}>
107
+ OPENCODE GO · NEW ZEALAND
108
+ </div>
109
+ <div
110
+ style={{
111
+ fontSize: 168,
112
+ fontWeight: 600,
113
+ lineHeight: 0.92,
114
+ letterSpacing: -5,
115
+ fontVariantNumeric: "tabular-nums",
116
+ }}
117
+ >
118
+ {nf.format(count)}
119
+ </div>
120
+ <div style={{ fontSize: 50, fontWeight: 600, letterSpacing: -1, marginTop: 4 }}>tokens per sheep</div>
121
+
122
+ <div
123
+ style={{
124
+ display: "flex",
125
+ justifyContent: "space-between",
126
+ alignItems: "center",
127
+ marginTop: 34,
128
+ fontSize: 20,
129
+ fontWeight: 500,
130
+ }}
131
+ >
132
+ <div style={{ color: c.dim }}>40.9B tokens ÷ 23.6M sheep · last week</div>
133
+ <div style={{ color: c.white }}>opencode.ai/data</div>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </AbsoluteFill>
138
+ )
139
+ }
artifacts/glm52-rise-video/src/video.tsx ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React from "react"
2
+ import { AbsoluteFill, Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion"
3
+ import { days, launchIndex, glmWeekTokensT, segments } from "./data"
4
+
5
+ // stats.opencode.ai design tokens (light theme)
6
+ const c = {
7
+ bg: "#ffffff",
8
+ ink: "#161616",
9
+ muted: "#5c5c5c",
10
+ faint: "#808080",
11
+ line: "#e6e6e6",
12
+ dot: "#ededed",
13
+ accent: "#3b5cf6",
14
+ accentHi: "#5b78ff",
15
+ }
16
+
17
+ const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace'
18
+ const W = 1080
19
+
20
+ const DOT_MASK =
21
+ "url(\"data:image/svg+xml,%3Csvg viewBox='0 0 6 6' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0H2V2H0V0Z' fill='black'/%3E%3C/svg%3E\")"
22
+
23
+ const field = segments.filter((s) => !s.hero)
24
+ const glmColor = segments.find((s) => s.hero)!.color
25
+
26
+ const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v))
27
+
28
+ // the correct opencode "DATA" wordmark (from stats.opencode.ai header)
29
+ function DataWordmark({ height = 30, color = c.ink }: { height?: number; color?: string }) {
30
+ return (
31
+ <svg width={(height * 66) / 20} height={height} viewBox="0 0 66 20" fill="none" style={{ color }}>
32
+ <path opacity="0.2" d="M12 16H4V8H12V16Z" fill="currentColor" />
33
+ <path d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="currentColor" />
34
+ <path
35
+ d="M63.3543 16L62.5119 12.8711H58.6437L57.8013 16H55.7383L59.2454 4H61.9618L65.4689 16H63.3543ZM61.0678 7.851L60.6896 5.94269H60.4489L60.0707 7.851L59.1595 11.1347H61.9962L61.0678 7.851Z"
36
+ fill="currentColor"
37
+ />
38
+ <path d="M52.5951 5.87392V16H50.4461V5.87392H47.4375V4H55.6209V5.87392H52.5951Z" fill="currentColor" />
39
+ <path
40
+ d="M45.2059 16L44.3635 12.8711H40.4953L39.6529 16H37.5898L41.097 4H43.8133L47.3205 16H45.2059ZM42.9194 7.851L42.5411 5.94269H42.3004L41.9222 7.851L41.011 11.1347H43.8477L42.9194 7.851Z"
41
+ fill="currentColor"
42
+ />
43
+ <path
44
+ d="M28 4H32.0917C32.8138 4 33.4556 4.11461 34.0172 4.34384C34.5903 4.5616 35.0716 4.9169 35.4613 5.40974C35.8625 5.89112 36.1662 6.51003 36.3725 7.26648C36.5788 8.02292 36.6819 8.9341 36.6819 10C36.6819 11.0659 36.5788 11.9771 36.3725 12.7335C36.1662 13.49 35.8625 14.1146 35.4613 14.6075C35.0716 15.0888 34.5903 15.4441 34.0172 15.6734C33.4556 15.8911 32.8138 16 32.0917 16H28V4ZM32.0917 14.1261C32.8252 14.1261 33.3926 13.9026 33.7937 13.4556C34.1948 12.9971 34.3954 12.3152 34.3954 11.4097V8.59026C34.3954 7.68481 34.1948 7.0086 33.7937 6.5616C33.3926 6.10315 32.8252 5.87392 32.0917 5.87392H30.149V14.1261H32.0917Z"
45
+ fill="currentColor"
46
+ />
47
+ </svg>
48
+ )
49
+ }
50
+
51
+ export function GLM52Rise() {
52
+ const frame = useCurrentFrame()
53
+ const { fps } = useVideoConfig()
54
+
55
+ // ---------- virtual camera ----------
56
+ // open zoomed-in on the field, pan right while the blue fills, then pull back to reveal.
57
+ const K = [0, 32, 150, 206, 240]
58
+ const ease = Easing.inOut(Easing.cubic)
59
+ const opt = { extrapolateLeft: "clamp" as const, extrapolateRight: "clamp" as const, easing: ease }
60
+ const s = interpolate(frame, K, [1.82, 1.72, 1.72, 1.0, 1.0], opt)
61
+ let fx = interpolate(frame, K, [420, 438, 760, 540, 540], opt)
62
+ let fy = interpolate(frame, K, [664, 664, 664, 540, 540], opt)
63
+ // keep the framing inside the 1080 canvas so edges never reveal black
64
+ fx = clamp(fx, 540 / s, W - 540 / s)
65
+ fy = clamp(fy, 540 / s, W - 540 / s)
66
+ const camera = `translate(${540 - fx * s}px, ${540 - fy * s}px) scale(${s})`
67
+
68
+ // ---------- blue sweep (synced to the pan) ----------
69
+ const p = interpolate(frame, [32, 150], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp", easing: ease })
70
+ const revealAmount = p * (days.length - launchIndex) + 0.35
71
+ const fillOf = (i: number) => clamp(revealAmount - (i - launchIndex), 0, 1)
72
+
73
+ // token number climbs as the camera pulls back and the headline re-enters frame
74
+ const tokensT =
75
+ glmWeekTokensT *
76
+ interpolate(frame, [150, 202], [0, 1], {
77
+ extrapolateLeft: "clamp",
78
+ extrapolateRight: "clamp",
79
+ easing: Easing.out(Easing.cubic),
80
+ })
81
+
82
+ // chart geometry
83
+ const chartH = 440
84
+ const chartW = 936
85
+ const gap = 14
86
+ const EXAGGERATE = 2.876 // broken y-axis: GLM-5.2 magnified ~2.9x for emphasis
87
+
88
+ return (
89
+ <AbsoluteFill style={{ background: c.bg, overflow: "hidden" }}>
90
+ <div
91
+ style={{
92
+ position: "absolute",
93
+ width: W,
94
+ height: W,
95
+ background: c.bg,
96
+ transformOrigin: "0 0",
97
+ transform: camera,
98
+ }}
99
+ >
100
+ <div
101
+ style={{
102
+ width: W,
103
+ height: W,
104
+ boxSizing: "border-box",
105
+ padding: 72,
106
+ color: c.ink,
107
+ fontFamily: MONO,
108
+ display: "flex",
109
+ flexDirection: "column",
110
+ }}
111
+ >
112
+ {/* header */}
113
+ <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
114
+ <DataWordmark height={30} />
115
+ <div style={{ fontSize: 20, fontWeight: 500, color: c.faint, letterSpacing: 1 }}>JUN 12–25, 2026</div>
116
+ </div>
117
+
118
+ {/* headline (static) */}
119
+ <div style={{ marginTop: 52 }}>
120
+ <div style={{ fontSize: 92, fontWeight: 600, lineHeight: 0.98, letterSpacing: -2 }}>
121
+ GLM-5.2 <span style={{ color: c.accent }}>broke out</span>
122
+ </div>
123
+ <div style={{ marginTop: 22, fontSize: 30, fontWeight: 500, color: c.muted }}>
124
+ From 0 to <span style={{ color: c.ink }}>{tokensT.toFixed(2)}T tokens</span> in a week.
125
+ </div>
126
+ </div>
127
+
128
+ {/* stacked chart */}
129
+ <div style={{ flex: 1, display: "flex", alignItems: "flex-end", marginTop: 40 }}>
130
+ <div
131
+ style={{
132
+ position: "relative",
133
+ width: chartW,
134
+ height: chartH,
135
+ margin: "0 auto",
136
+ borderBottom: `2px solid ${c.ink}`,
137
+ boxSizing: "border-box",
138
+ }}
139
+ >
140
+ {/* faint dotted backdrop */}
141
+ <div
142
+ style={{
143
+ position: "absolute",
144
+ left: -8,
145
+ right: -8,
146
+ top: -8,
147
+ bottom: 0,
148
+ background: c.dot,
149
+ WebkitMaskImage: DOT_MASK,
150
+ maskImage: DOT_MASK,
151
+ WebkitMaskSize: "12px 12px",
152
+ maskSize: "12px 12px",
153
+ WebkitMaskRepeat: "repeat",
154
+ maskRepeat: "repeat",
155
+ }}
156
+ />
157
+
158
+ {/* columns */}
159
+ <div style={{ position: "absolute", inset: 0, display: "flex", gap, alignItems: "flex-end" }}>
160
+ {days.map((d, i) => {
161
+ const glmShare = d.glm / d.total
162
+ const blueH = Math.round(glmShare * EXAGGERATE * chartH)
163
+ const filled = Math.round(blueH * fillOf(i))
164
+ const slotGap = filled > 2 ? 5 : 0
165
+ const fieldH = chartH - filled - slotGap
166
+ const fieldTotal = d.dsf + d.dsp + d.mm + d.others
167
+ return (
168
+ <div key={i} style={{ position: "relative", flex: 1, height: chartH }}>
169
+ {/* gray field of other models (already in place) */}
170
+ <div
171
+ style={{
172
+ position: "absolute",
173
+ top: 0,
174
+ left: 0,
175
+ right: 0,
176
+ height: fieldH,
177
+ display: "flex",
178
+ flexDirection: "column-reverse",
179
+ }}
180
+ >
181
+ {field.map((seg) => (
182
+ <div
183
+ key={seg.key}
184
+ style={{
185
+ height: Math.round(((d[seg.key as keyof typeof d] as number) / fieldTotal) * fieldH),
186
+ background: seg.color,
187
+ borderTop: `2px solid ${c.bg}`,
188
+ }}
189
+ />
190
+ ))}
191
+ </div>
192
+ {/* GLM-5.2, animates in */}
193
+ {filled > 2 && (
194
+ <div
195
+ style={{
196
+ position: "absolute",
197
+ left: 0,
198
+ right: 0,
199
+ bottom: 0,
200
+ height: filled,
201
+ background: glmColor,
202
+ borderTop: `2px solid ${c.accentHi}`,
203
+ }}
204
+ />
205
+ )}
206
+ </div>
207
+ )
208
+ })}
209
+ </div>
210
+ </div>
211
+ </div>
212
+
213
+ {/* day axis */}
214
+ <div style={{ display: "flex", gap, width: chartW, margin: "14px auto 0" }}>
215
+ {days.map((d, i) => (
216
+ <div
217
+ key={i}
218
+ style={{
219
+ flex: 1,
220
+ textAlign: "center",
221
+ fontSize: 15,
222
+ fontWeight: 500,
223
+ color: i === days.length - 1 ? c.ink : c.faint,
224
+ }}
225
+ >
226
+ {i === 0 || i === launchIndex || i === days.length - 1 ? d.date : ""}
227
+ </div>
228
+ ))}
229
+ </div>
230
+
231
+ {/* footer */}
232
+ <div
233
+ style={{
234
+ display: "flex",
235
+ justifyContent: "space-between",
236
+ alignItems: "center",
237
+ marginTop: 28,
238
+ paddingTop: 22,
239
+ borderTop: `1px solid ${c.line}`,
240
+ fontSize: 20,
241
+ fontWeight: 500,
242
+ }}
243
+ >
244
+ <div style={{ display: "inline-flex", alignItems: "center", gap: 9, color: c.muted }}>
245
+ <span style={{ width: 13, height: 13, background: c.accent, display: "inline-block" }} />
246
+ GLM-5.2
247
+ </div>
248
+ <div style={{ color: c.ink }}>opencode.ai/data</div>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ </AbsoluteFill>
253
+ )
254
+ }
artifacts/glm52-rise-video/sst-env.d.ts ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is auto-generated by SST. Do not edit. */
2
+ /* tslint:disable */
3
+ /* eslint-disable */
4
+ /* deno-fmt-ignore-file */
5
+ /* biome-ignore-all lint: auto-generated */
6
+
7
+ /// <reference path="../../sst-env.d.ts" />
8
+
9
+ import "sst"
10
+ export {}
github/script/publish ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ # Get the latest Git tag
4
+ latest_tag=$(git tag --sort=committerdate | grep -E '^github-v[0-9]+\.[0-9]+\.[0-9]+$' | tail -1)
5
+ if [ -z "$latest_tag" ]; then
6
+ echo "No tags found"
7
+ exit 1
8
+ fi
9
+ echo "Latest tag: $latest_tag"
10
+
11
+ # Update latest tag
12
+ git tag -d latest
13
+ git push origin :refs/tags/latest
14
+ git tag -a latest $latest_tag -m "Update latest to $latest_tag"
15
+ git push origin latest
github/script/release ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ # Parse command line arguments
4
+ minor=false
5
+ while [ "$#" -gt 0 ]; do
6
+ case "$1" in
7
+ --minor) minor=true; shift 1;;
8
+ *) echo "Unknown parameter: $1"; exit 1;;
9
+ esac
10
+ done
11
+
12
+ # Get the latest Git tag
13
+ git fetch --force --tags
14
+ latest_tag=$(git tag --sort=committerdate | grep -E '^github-v[0-9]+\.[0-9]+\.[0-9]+$' | tail -1)
15
+ if [ -z "$latest_tag" ]; then
16
+ echo "No tags found"
17
+ exit 1
18
+ fi
19
+
20
+ echo "Latest tag: $latest_tag"
21
+
22
+ # Split the tag into major, minor, and patch numbers
23
+ IFS='.' read -ra VERSION <<< "$latest_tag"
24
+
25
+ if [ "$minor" = true ]; then
26
+ # Increment the minor version and reset patch to 0
27
+ minor_number=${VERSION[1]}
28
+ let "minor_number++"
29
+ new_version="${VERSION[0]}.$minor_number.0"
30
+ else
31
+ # Increment the patch version
32
+ patch_number=${VERSION[2]}
33
+ let "patch_number++"
34
+ new_version="${VERSION[0]}.${VERSION[1]}.$patch_number"
35
+ fi
36
+
37
+ echo "New version: $new_version"
38
+
39
+ # Tag
40
+ git tag $new_version
41
+ git push --tags