Merge remote-tracking branch 'origin/main' into feat/nested-git-repos
# Conflicts: # packages/web/server/lib/fs/routes.test.js
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
---
|
||||
name: changelog-authoring
|
||||
description: Use when drafting or updating user-facing CHANGELOG.md entries for the OpenChamber `[Unreleased]` section, including the VS Code extension changelog, summarizing changes since the latest git tag.
|
||||
license: MIT
|
||||
compatibility: opencode
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Draft user-facing bullet points for the `## [Unreleased]` section that summarize changes since the latest git tag up to `HEAD`.
|
||||
|
||||
Two files are maintained:
|
||||
|
||||
- `CHANGELOG.md` — main app (Web, Desktop, Mobile/PWA, shared UI).
|
||||
- `packages/vscode/CHANGELOG.md` — VS Code extension only.
|
||||
|
||||
Only update the `[Unreleased]` bullets. Never add a new release header.
|
||||
|
||||
## Gather Context First
|
||||
|
||||
Read recent release sections for style. Determine the latest tag (or initial commit fallback), then inspect every commit and changed path through `HEAD`:
|
||||
|
||||
```bash
|
||||
BASE=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)
|
||||
git log --oneline "$BASE"..HEAD
|
||||
git diff --stat "$BASE"..HEAD
|
||||
```
|
||||
|
||||
Context gathering is complete when each user-visible change has evidence, platform reach, and contributor identity where available.
|
||||
|
||||
## Squashed PR Merges
|
||||
|
||||
A squashed merge commit often collapses a whole PR into a single terse subject line that omits valuable detail. When a commit looks like a squashed PR merge (subject ending in `(#123)`, or a `Merge pull request #123` commit), inspect the PR itself — its title and description usually carry the real user-facing context.
|
||||
|
||||
Use `gh pr view <number> --json number,title,body,author,mergedAt` for PR evidence.
|
||||
|
||||
- Prefer the PR description over the squashed commit subject when the description explains the user-visible change more accurately.
|
||||
- Do not copy PR descriptions verbatim; distill them into the changelog style below.
|
||||
- Use PR author/metadata to attribute contributor credit (see Contributor Credit).
|
||||
- If `gh` is unavailable or the PR cannot be fetched, fall back to the commit message and diff, and note any uncertainty rather than inventing details.
|
||||
|
||||
## Writing Style
|
||||
|
||||
- Match the tone and level of detail of the existing changelog.
|
||||
- Write like release notes for real users, not marketing. Be concrete and plain-spoken.
|
||||
- Avoid generic payoff clauses ("making X faster", "improving reliability", "for a smoother workflow", "so you can...") unless the diff clearly proves that exact user-visible outcome.
|
||||
- Prefer short direct bullets: what changed, where users see it, and only one obvious consequence.
|
||||
- Omit internal implementation details; do not replace them with vague benefits. If a technical change has no user-visible effect, omit it or group under a plain reliability bullet.
|
||||
- Avoid internal component names unless users see them (ex: "VS Code extension", "Desktop app", "Web app").
|
||||
- Use area prefixes in the main changelog when they help grouping (e.g., "Chat:", "VSCode:", "Settings:", "Git:", "Terminal:", "Mobile:", "UI:").
|
||||
- Do not include commit hashes, file paths, or implementation notes in changelog text.
|
||||
- Do not mention low-level mechanics ("local refs first", "source of truth", "route", "store", "cache", "payload", "ref resolution"). Translate only when there is a clear user-facing symptom.
|
||||
- Avoid LinkedIn-style language. Bad: "commit review is faster and branch history is more reliable." Better: "commit history can now show file diffs inline."
|
||||
|
||||
## Highlights and Ordering
|
||||
|
||||
- Sort bullets by user impact, not commit order. Breaking changes first, then significant new capabilities or broad user-visible improvements, then smaller features, fixes, and visual polish.
|
||||
- Mark only the strongest highlights with a bold area prefix, such as `- **Chat attachments:** ...`. Usually the first 1–3 bullets; fewer when the release lacks substantial changes, more only when clearly justified.
|
||||
- Treat a change as a highlight only when it introduces a substantial user-facing capability, materially changes a common workflow, or fixes a severe/widespread problem. Do not bold merely because a bullet is first, has a large diff, or was hard to implement.
|
||||
- Keep related platform bullets together only when that does not push a more important change too far down.
|
||||
- Rank highlights independently in each changelog. A main-app highlight is not automatically a VS Code highlight.
|
||||
|
||||
## VS Code Changelog Rules
|
||||
|
||||
- Craft entries only for behavior present in the VS Code extension. Exclude Desktop, Web, Mobile/PWA, and main-app-only UI.
|
||||
- Do not copy shared/main bullets here unless changed files or code paths show the feature exists in the extension.
|
||||
- Focus on core UI improvements and VS Code integration.
|
||||
- Do NOT use "VSCode:" or "VS Code:" prefixes in this file.
|
||||
- When unsure whether a change reaches the extension, leave it out.
|
||||
|
||||
## Contributor Credit
|
||||
|
||||
- Credit contributors inline with "(thanks to @username)" at the end of the bullet.
|
||||
- Find usernames from commit authors (GitHub username, not email) or PR metadata when available.
|
||||
- Skip credit when the contributor is `btriapitsyn` (repo owner).
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
- For every bullet: "Could a user point to this in the UI or behavior?" If not, rewrite or drop it.
|
||||
- For every VS Code bullet: verify the change applies to the extension, not just shared web UI or server code.
|
||||
- For every bold bullet: "Would a user reasonably call this a headline change?" If not, unbold or move it lower.
|
||||
- Read the finished list top to bottom; confirm each bullet is no more important than those above it, except where keeping related platform bullets together improves readability.
|
||||
- Do not bundle unrelated changes to reduce bullet count. Prefer omitting minor internal fixes over vague catch-all sentences.
|
||||
- Mention mostly-internal refactors only when there is a concrete user-visible fix; otherwise add no bullet.
|
||||
|
||||
The lists are complete when every bullet is supported by inspected evidence, points to user-observable behavior, is ranked by impact, appears only in changelogs whose runtime receives it, and credits eligible contributors.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Gather repo style and complete git/PR context.
|
||||
2. Propose the new `[Unreleased]` bullet list for the main `CHANGELOG.md`.
|
||||
3. Propose the VS Code-specific `[Unreleased]` list for `packages/vscode/CHANGELOG.md`.
|
||||
4. Edit both files to update their respective `[Unreleased]` sections.
|
||||
@@ -17,36 +17,19 @@ Use this skill for terminal CLI work only (for example `packages/web/bin/*`).
|
||||
|
||||
Do not use this skill for web UI or VS Code webview styling work.
|
||||
|
||||
## Mandatory Rules
|
||||
## Mode Contract
|
||||
|
||||
1. **Validation first**
|
||||
- Safety and correctness checks must run in all modes.
|
||||
- Prompts may help collect input, but cannot be the only guard.
|
||||
Run safety and correctness validation before presentation in every mode. Prompts collect missing input; they never enforce policy alone.
|
||||
|
||||
2. **Mode parity is required**
|
||||
- Behavior must be equivalent in:
|
||||
- Interactive TTY
|
||||
- Non-interactive shells
|
||||
- `--quiet`
|
||||
- `--json`
|
||||
- Fully pre-specified flags
|
||||
- Invalid operations must fail deterministically with non-zero exit code.
|
||||
| Mode | Prompt | Output | Failure |
|
||||
|---|---|---|---|
|
||||
| Interactive TTY | Allowed when input is missing | Framed human output | Concise human error, non-zero exit |
|
||||
| Fully specified flags | None required | Human output | Same policy and exit semantics |
|
||||
| Non-TTY/piped | Never | Deterministic script-safe output | Non-zero without hanging |
|
||||
| `--quiet` | Never | Essential result only | Concise error, non-zero exit |
|
||||
| `--json` | Never | JSON only, including warnings/errors | JSON failure payload, non-zero exit |
|
||||
|
||||
3. **Prompt guard contract**
|
||||
- Only prompt when all are true:
|
||||
- stdout is TTY
|
||||
- not `--quiet`
|
||||
- not `--json`
|
||||
- not automated/non-interactive context
|
||||
|
||||
4. **Output contract**
|
||||
- `--json`: machine-readable output only.
|
||||
- `--quiet`: suppress non-essential output only.
|
||||
- Neither mode weakens policy enforcement.
|
||||
|
||||
5. **Cancellation contract**
|
||||
- Handle prompt cancellation with `isCancel` + `cancel(...)`.
|
||||
- Handle SIGINT cleanly and use consistent exit semantics.
|
||||
Handle prompt cancellation with `isCancel` + `cancel(...)` and SIGINT with consistent exit semantics.
|
||||
|
||||
## Clack Primitive Standard
|
||||
|
||||
@@ -140,9 +123,9 @@ Quiet output should still be complete enough for scripts and quick human scannin
|
||||
- Prefer this style over boxed notes for routine follow-up actions.
|
||||
- Reserve `note`/boxed callouts for rare, high-context guidance where a long paragraph is truly necessary.
|
||||
|
||||
## Parity Verification Matrix
|
||||
## Completion Criteria
|
||||
|
||||
For each command/subcommand, manually verify:
|
||||
Every command/subcommand must have a tested answer for:
|
||||
|
||||
1. default interactive TTY output
|
||||
2. `--quiet` output (minimal but informative)
|
||||
@@ -154,13 +137,7 @@ For each command/subcommand, manually verify:
|
||||
|
||||
Load `references/snippets.md` when implementing prompt guards, non-interactive fallback, spinner lifecycle, or JSON/human output branching.
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
1. Add or update core validators first.
|
||||
2. Ensure validators execute in all modes.
|
||||
3. Add interactive Clack UX only as enhancement.
|
||||
4. Verify parity between interactive and non-interactive flows.
|
||||
5. Ensure script-safe deterministic failure behavior.
|
||||
Implementation is complete when validators run before every mode branch, interactive Clack UX is only an enhancement, and all five cases above produce deterministic output and exit behavior.
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
---
|
||||
name: communication-style
|
||||
description: Use it always.
|
||||
author: poteto (pstack)
|
||||
---
|
||||
|
||||
# Communication style
|
||||
|
||||
Edit text to remove AI patterns and add human voice.
|
||||
|
||||
## Process
|
||||
|
||||
1. Scan for the patterns below.
|
||||
2. Rewrite. Preserve meaning, match intended tone.
|
||||
3. Add soul (see next section).
|
||||
4. Self-audit: "What makes this obviously AI generated?" Fix remaining tells.
|
||||
|
||||
## Adding soul
|
||||
|
||||
Removing patterns is half the job. Sterile, voiceless writing is just as obvious.
|
||||
|
||||
- **Have opinions.** React to facts instead of neutrally listing pros and cons.
|
||||
- **Vary rhythm.** Short sentences. Then longer ones that take their time. Mix it up.
|
||||
- **Acknowledge complexity.** "Impressive but also kind of unsettling" beats "impressive."
|
||||
- **Use "I" when it fits.** First person isn't unprofessional.
|
||||
- **Let some mess in.** Perfect structure looks machine-made.
|
||||
- **Be specific.** Not "this is concerning" but "there's something unsettling about agents churning away at 3am."
|
||||
|
||||
## Patterns to detect and fix
|
||||
|
||||
### Content
|
||||
|
||||
1. **Puffery.** "pivotal moment", "testament to", "evolving landscape", "setting the stage for", "indelible mark", "deeply rooted". Cut puffery, state what happened.
|
||||
2. **Name-dropping.** Listing media outlets without context. Pick one, say what was said.
|
||||
3. **Superficial -ing phrases.** "highlighting...", "ensuring...", "reflecting...", "showcasing...", "fostering...". Delete or expand with real sources.
|
||||
4. **Promotional language.** "nestled", "vibrant", "breathtaking", "groundbreaking", "renowned", "stunning", "must-visit". Use neutral descriptions.
|
||||
5. **Vague attributions.** "Experts believe", "Industry reports suggest", "Some critics argue". Name the source or delete.
|
||||
6. **Formulaic challenges.** "Despite challenges... continues to thrive." Replace with specific facts.
|
||||
|
||||
### Language
|
||||
|
||||
7. **AI vocabulary.** Additionally, crucial, delve, enduring, enhance, fostering, garner, interplay, intricate, landscape (abstract), pivotal, showcase, tapestry (abstract), testament, underscore, vibrant. Replace with plain words.
|
||||
8. **Fancy ways to say "is".** "serves as", "stands as", "boasts", "features". Just say "is" or "has".
|
||||
9. **"Not just X, but Y."** State the point directly instead.
|
||||
10. **Rule of three.** Forcing ideas into groups of three. Use the natural number.
|
||||
11. **Synonym cycling.** Protagonist, main character, central figure, hero all in one paragraph. Pick one, repeat it.
|
||||
12. **False ranges.** "from X to Y" where X and Y aren't on a meaningful scale. List topics directly.
|
||||
|
||||
### Style
|
||||
|
||||
13. **Em dash overuse.** Avoid em dashes entirely. Use periods or commas only (no parentheses, no en dashes, no hyphen-as-dash substitutes). Em dashes are an AI tell, and reaching for parentheses instead just trades one tell for another. If a thought needs separation, end the sentence or use a comma.
|
||||
14. **Colon overuse.** Colons are fine before a list or example. Not as mid-sentence connectors. "If you're coming from traditional automation: instead of registering event handlers, you describe conditions" adds nothing with the colon. Rewrite to let the point stand on its own without comparison framing. "Describing when the scheduler should fire works best as plain English." Same meaning, no crutch punctuation.
|
||||
15. **Boldface overuse.** Don't bold every proper noun or acronym.
|
||||
16. **Inline-header lists.** The tell is a bold label and colon that restates the line: "**Performance:** Performance improved...". Convert to prose. A bold lead-in that ends in a period, names the item, and is followed by genuinely new detail ("**Schema in TypeScript.** Tables live in one file.") is fine.
|
||||
17. **Title case headings.** Use sentence case.
|
||||
18. **Decorative emojis.** Remove from headings and bullets.
|
||||
19. **Curly quotes.** Replace with straight quotes.
|
||||
|
||||
### Communication artifacts
|
||||
|
||||
20. **Chatbot phrases.** "I hope this helps!", "Let me know if...", "Of course!", "Certainly!", "Found the smoking gun!" Remove.
|
||||
21. **Cutoff disclaimers.** "While specific details are limited..." Find sources or remove.
|
||||
22. **Sycophantic tone.** "Great question! You're absolutely right!" Respond directly.
|
||||
|
||||
### Filler
|
||||
|
||||
23. **Filler phrases.** "In order to" becomes "To". "Due to the fact that" becomes "Because". "It is important to note that" gets deleted.
|
||||
24. **Excessive hedging.** "could potentially possibly be argued that it might" becomes "may".
|
||||
25. **Generic conclusions.** "The future looks bright." State specific plans or facts.
|
||||
|
||||
### Jargon
|
||||
|
||||
26. **Abstract metaphor nouns.** Substrate, wedge, vector, locus, vantage, nexus, primitive (as noun), harness (as metaphor), surface (as in "API surface"), bedrock, scaffolding (as metaphor), modality, paradigm, gold-plating, ratchet (as metaphor), evacuate (for moving code), endgame, north star, flywheel. These read as technical but usually have a plainer concrete word. "Substrate" becomes "base". "Wedge in" becomes "add". "Vector" becomes "way" or "method". "Gold-plating" becomes "more than the job needs". "Ratchet" becomes the mechanism's real name or "a limit that only tightens". "Evacuate" becomes "move out". "Endgame" becomes "the last phase". Pick the concrete word.
|
||||
|
||||
### Plain speech
|
||||
|
||||
27. **Say what it does, not how it feels.** "the database stays close at hand", "SQL you can read", "types that follow your schema" name a feeling. The fix names the mechanism or a number: "`.toSQL()` returns the exact string sent to the database", "a column rename fails the build". Ask what the sentence tells the reader to do or know, then write it. If you can't restate it as a concrete instruction, fact, or number, cut it. One more check: if the sentence could appear unchanged in another project's docs, it says nothing about this one. Cut it.
|
||||
28. **Shorten or split dense sentences.** If the reader has to backtrack to parse a sentence, break it in two or drop clauses. One idea per sentence.
|
||||
29. **Active voice.** Prefer it. Catch "is/are/was/were + past participle" and name the actor: "queries are validated" becomes "the compiler validates queries", "the file is parsed by the loader" becomes "the loader parses the file". Passive is fine only when the actor is unknown or genuinely doesn't matter.
|
||||
30. **Cut adverbs, or use a stronger verb.** "runs quickly" becomes "is fast" or the number. "significantly improves" becomes the measured delta. An adverb propping up a weak verb means the verb is wrong.
|
||||
31. **Prefer the plain word.** "utilize" becomes "use", "leverage" becomes "use", "facilitate" becomes "help", "numerous" becomes "many", "in the event that" becomes "if". The fancier synonym is rarely clearer.
|
||||
@@ -5,16 +5,16 @@ description: Use when changing Electron main/preload code, desktop IPC, native w
|
||||
|
||||
# Desktop Shell
|
||||
|
||||
## Read First
|
||||
## Required Context
|
||||
|
||||
Read `packages/electron/README.md` and nearby `packages/electron` code before editing.
|
||||
Read `packages/electron/README.md` and nearby `packages/electron` code before editing. Context gathering is complete when each changed behavior is assigned to main, preload, renderer/shared UI, or web/runtime ownership.
|
||||
|
||||
Load `ui-api-decoupling` when a native change adds or alters a renderer-facing capability, `RuntimeAPIs`, runtime auth/URL behavior, or shared bridge contract. This skill owns the Electron privilege boundary; `ui-api-decoupling` owns the shared UI/runtime contract.
|
||||
|
||||
## Runtime Boundary
|
||||
|
||||
- Electron boots `@openchamber/web` in the same Node process and loads the UI over loopback. Do not introduce a sidecar server process.
|
||||
- Keep OpenCode feature backends and shared domain logic in web/server or runtime APIs.
|
||||
- Keep Electron focused on inherently native behavior: windows, menus, dialogs, notifications, updater, deep links, runtime host switching, privileged IPC, SSH, and tunnel lifecycle.
|
||||
- Shared renderer-facing contracts belong in `packages/ui`; shared server behavior belongs in `packages/web`.
|
||||
- Keep renderer contracts and domain logic in `packages/ui`, server behavior in `packages/web`, and Electron focused on inherently native behavior: windows, menus, dialogs, notifications, updater, deep links, runtime host switching, privileged IPC, SSH, and tunnel lifecycle.
|
||||
- Electron is the desktop release target.
|
||||
|
||||
## IPC And Security
|
||||
@@ -47,4 +47,4 @@ Non-user-visible child processes must never flash a console window.
|
||||
|
||||
## Validation
|
||||
|
||||
Run the Electron package type-check/lint commands from `package.json` and focused tests. For startup, preload, routing, or packaging changes, test both HMR development and bundled UI mode. For Windows process work, inspect the complete process tree and verify no console flash; a successful command alone is insufficient.
|
||||
Run focused Electron tests and package checks. For startup, preload, routing, or packaging changes, completion requires both HMR development and bundled UI validation. For Windows process work, completion requires inspection of the complete process tree with no console flash; command success alone is insufficient.
|
||||
|
||||
@@ -79,7 +79,7 @@ const onDragEnd = (e: DragEndEvent) => {
|
||||
|
||||
IDs must be **stable per item** (derive from the item's identity, e.g. `type:name`), never the array index — index ids break tracking after the first move.
|
||||
|
||||
## Minimal working pattern (wrapping, variable width, desktop + touch)
|
||||
## Minimal Wiring
|
||||
|
||||
```tsx
|
||||
import { DndContext, MouseSensor, TouchSensor, closestCenter, useSensor, useSensors, type DragEndEvent } from '@dnd-kit/core';
|
||||
@@ -97,41 +97,21 @@ const Item: React.FC<{ id: string; label: string; onClick: () => void }> = ({ id
|
||||
);
|
||||
};
|
||||
|
||||
const Row: React.FC<{ items: Item[]; onReorder: (next: Item[]) => void }> = ({ items, onReorder }) => {
|
||||
const sensors = useSensors(
|
||||
useSensor(MouseSensor, { activationConstraint: { distance: 8 } }),
|
||||
useSensor(TouchSensor, { activationConstraint: { delay: 200, tolerance: 6 } }),
|
||||
);
|
||||
const onDragEnd = (e: DragEndEvent) => {
|
||||
const { active, over } = e;
|
||||
if (!over || active.id === over.id) return;
|
||||
const from = items.findIndex(i => i.id === active.id);
|
||||
const to = items.findIndex(i => i.id === over.id);
|
||||
onReorder(arrayMove(items, from, to));
|
||||
};
|
||||
return (
|
||||
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={onDragEnd}>
|
||||
<SortableContext items={items.map(i => i.id)} strategy={rectSortingStrategy}>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{items.map(i => <Item key={i.id} id={i.id} label={i.label} onClick={i.onClick} />)}
|
||||
</div>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
);
|
||||
};
|
||||
// Configure sensors per Rule 3, reorder onDragEnd per Rule 5, and choose the
|
||||
// SortableContext strategy from Rule 2. This item wiring preserves item width.
|
||||
```
|
||||
|
||||
A clickable element can be draggable at the same time: keep `onClick` on the button and the activation constraint (distance/delay) lets a plain click/tap through.
|
||||
|
||||
## Pitfalls we already hit (don't repeat)
|
||||
## Symptom Index
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
|---------|-------|-----|
|
||||
| Dragged item **stretches** to the target slot width | `CSS.Transform.toString` applies scaleX/scaleY | Use `CSS.Translate.toString` (Rule 1) |
|
||||
| On narrow/multi-row: items **don't reflow to other rows, overlap**, unclear drop target | `horizontalListSortingStrategy` on a wrapping row | Use `rectSortingStrategy` (Rule 2) |
|
||||
| Dragged item **stretches** to the target slot width | Scale from `CSS.Transform.toString` | Rule 1 |
|
||||
| On narrow/multi-row: items **don't reflow to other rows, overlap**, unclear drop target | Single-row strategy on wrapping layout | Rule 2 |
|
||||
| **"Maximum update depth exceeded"** during drag + dragged element floats **offset from the cursor** | Live-reorder in `onDragOver` (empty strategy + `setState` each over) oscillates A↔B with variable sizes; the empty `DragOverlay` we paired with it was mispositioned | Don't reorder in `onDragOver`. Reorder once in `onDragEnd` (Rule 5). Only reach for live-reorder if you truly need physical row-reflow, and then guard against oscillation. |
|
||||
| Touch drag scrolls the page instead of dragging | Missing `touch-action: none` | Add `touch-none` (Rule 4) |
|
||||
| Touch: every finger move drags, or tap doesn't register | Single `PointerSensor` with distance | Split into MouseSensor + TouchSensor(delay) (Rule 3) |
|
||||
| Touch drag scrolls the page instead of dragging | Missing touch ownership | Rule 4 |
|
||||
| Touch: every finger move drags, or tap doesn't register | One sensor for mouse and touch | Rule 3 |
|
||||
|
||||
## If `rectSortingStrategy` still isn't crisp enough
|
||||
|
||||
@@ -142,3 +122,7 @@ Reordering variable-width chips across wrapped rows is a documented rough edge i
|
||||
- Variable-width wrapping chips: `packages/ui/src/components/chat/DraftPresetChips.tsx`
|
||||
- Single-row tab strip: `packages/ui/src/components/ui/sortable-tabs-strip.tsx`
|
||||
- Library: `@dnd-kit/core`, `@dnd-kit/sortable`, `@dnd-kit/utilities` (already in `packages/ui/package.json`)
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
Verify every applicable rule on desktop and touch. Wrapping layouts must preserve item width, reflow across rows, allow taps and scrolling before long-press activation, and reorder exactly once on drag end with stable IDs.
|
||||
|
||||
@@ -9,8 +9,6 @@ description: Use when creating or modifying OpenChamber UI text, labels, buttons
|
||||
|
||||
User-facing UI text must go through `@/lib/i18n`; do not hardcode English strings in components.
|
||||
|
||||
Use this skill for any React UI change that adds or edits visible text, accessible labels, placeholders, tooltips, toasts, dialogs, settings labels, navigation labels, or empty/error states.
|
||||
|
||||
## Translate everything immediately (no English placeholders)
|
||||
|
||||
Every key you add to a non-English dictionary MUST contain a real translation in that language — never the English source string as a stand-in. There is NO "leave it in English for now" convention in this project; if an agent told you there was, it was wrong. Copying the English value into `es.ts`/`fr.ts`/`ko.ts`/`pl.ts`/`pt-BR.ts`/`uk.ts`/`zh-CN.ts`/`zh-TW.ts` is a defect, not a deferral. The app ships every locale at once, so an untranslated key is a visible bug for those users.
|
||||
@@ -104,20 +102,11 @@ date
|
||||
: t('dialog.delete.description', { count })
|
||||
```
|
||||
|
||||
## What Counts As UI Text
|
||||
## Translation Boundary
|
||||
|
||||
- Button and menu labels
|
||||
- Settings labels and descriptions
|
||||
- Placeholder text
|
||||
- Tooltip content
|
||||
- Dialog titles/descriptions/actions
|
||||
- Toast title/description/action labels
|
||||
- Empty/error/loading states
|
||||
- `aria-label`, `title`, image `alt` text when user-facing
|
||||
Translate visible text, placeholders, tooltips, dialogs, toasts, empty/error/loading states, and user-facing `aria-label`, `title`, and `alt` text.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Do not translate:
|
||||
Keep these literal:
|
||||
|
||||
- Product names: `OpenChamber`, `OpenCode`, `GitHub`
|
||||
- Protocol/tool acronyms: `MCP`, `SSE`, `WebSocket`, `API`
|
||||
@@ -125,10 +114,11 @@ Do not translate:
|
||||
- File paths, command names, environment variables
|
||||
- User/generated content
|
||||
|
||||
## Review Checklist
|
||||
## Completion Criteria
|
||||
|
||||
- No new hardcoded user-facing English in changed UI files.
|
||||
- Every new key exists in all dictionaries.
|
||||
- Every new key exists in all dictionaries with a real translation.
|
||||
- All translated values are resolved inside a reactive render/hook boundary.
|
||||
- No locale state added to broad/shared stores.
|
||||
- No full app remount for locale changes.
|
||||
- Locale switch preserves current UI state.
|
||||
|
||||
@@ -9,15 +9,11 @@ description: Use when implementing, fixing, refactoring, or otherwise modifying
|
||||
|
||||
Make the smallest complete change and validate at the narrowest level that covers the real risk.
|
||||
|
||||
Identify existing behavior covered by tests or callers; preserve it unless the requested change explicitly replaces it.
|
||||
|
||||
## Before Editing
|
||||
|
||||
1. Read the nearest `DOCUMENTATION.md` and package `README.md` when present.
|
||||
2. Inspect nearby implementation and tests before introducing a pattern.
|
||||
3. Load every additional project skill whose trigger matches the change.
|
||||
4. Classify the highest applicable change risk below.
|
||||
5. Identify affected consumers, runtimes, persisted data, and public exports.
|
||||
1. Inspect nearby implementation, callers, and tests before introducing a pattern.
|
||||
2. Classify every applicable change risk below.
|
||||
3. Identify every affected consumer, runtime, persisted format, and public export. This step is complete only when each risk has an owner and required validation.
|
||||
|
||||
When instructions materially conflict, stop and resolve the conflict instead of silently choosing one.
|
||||
|
||||
@@ -33,30 +29,23 @@ When instructions materially conflict, stop and resolve the conflict instead of
|
||||
|
||||
Apply every matching category. Do not escalate local work into workspace-wide ritual, and do not treat a type-only export as local merely because it emits no JavaScript.
|
||||
|
||||
## Mandatory Rules
|
||||
## Structural Discipline
|
||||
|
||||
- Identify existing behavior covered by tests or callers; preserve it unless explicitly replaced.
|
||||
- Do not add dependencies unless explicitly requested.
|
||||
- Do not add compatibility paths without a concrete persisted or external consumer.
|
||||
- Enforce security and correctness in core logic, not only UI controls or prompts.
|
||||
- Never add, persist, or log secrets, bearer tokens, pairing data, or sensitive user content.
|
||||
- Make data loss, partial failure, rollback, and fallback behavior explicit.
|
||||
- Update owning documentation when module ownership, contracts, or invariants change.
|
||||
- Complete the cumulative validation required by every applicable risk category.
|
||||
|
||||
## Engineering Preferences
|
||||
|
||||
- Prefer the smallest correct change; avoid drive-by refactors.
|
||||
- Keep orchestration entrypoints thin and move domain logic to focused modules.
|
||||
- Preserve behavior established by callers and tests unless the request replaces it. Keep the diff scoped to the complete requested behavior.
|
||||
- Make the normal use-case path read top to bottom in domain terms. Keep orchestration entrypoints thin and move mechanics or domain logic behind focused, intention-revealing boundaries.
|
||||
- Pull complexity downward only when a boundary hides meaningful mechanics, owns an invariant, isolates a proven integration, or captures stable repetition. Do not spread obvious code across pass-through layers.
|
||||
- Prefer explicit dependencies and dependency injection over hidden module coupling.
|
||||
- Follow local TypeScript types; avoid `any`, blind casts, and guessed payload shapes.
|
||||
- Prefer early returns and explicit branches over nested conditionals.
|
||||
- Reject invalid inputs and broken preconditions early so the valid path stays flat. Do not force a numeric happy-path/error-path ratio when correctness requires substantial failure handling.
|
||||
- Require evidence before adding retries, caches, compatibility paths, lifecycle machinery, or generalized race handling. Security, data-loss, destructive-operation, and concurrency invariants still require proactive design when the risk is inherent to the operation.
|
||||
- Make partial failure, rollback, cleanup, and user-visible outcomes explicit for destructive or multi-step work.
|
||||
|
||||
## Review Prompts
|
||||
|
||||
Before broadening a change, ask:
|
||||
|
||||
- Is the new abstraction reused or merely possible to reuse?
|
||||
- What concrete complexity, invariant, stable repetition, or boundary does each new helper, interface, layer, and file pay for?
|
||||
- Is the code in the package that owns the behavior?
|
||||
- Does the change alter shared UI contracts across web, desktop, VS Code, or mobile?
|
||||
- Does it change persisted data, IDs, routes, exports, generated files, or package entrypoints?
|
||||
@@ -75,8 +64,6 @@ Do not hide a required architectural migration behind a local heuristic. Do not
|
||||
|
||||
## Validation Matrix
|
||||
|
||||
Use `package.json` scripts as the command source of truth.
|
||||
|
||||
| Change | Minimum validation |
|
||||
|---|---|
|
||||
| Executable source | Focused tests plus package-scoped type-check and lint |
|
||||
@@ -108,15 +95,4 @@ For type-only shared contracts, validate compile-time consumers. Add runtime ser
|
||||
- Run focused regression tests for the changed contract.
|
||||
- Preserve unrelated changes encountered in shared files.
|
||||
- Re-read the owning docs and update them when the implementation changed their truth.
|
||||
- Do not claim runtime, relay, performance, or platform correctness from type-check/lint alone.
|
||||
|
||||
## Common Failure Modes
|
||||
|
||||
| Failure | Correction |
|
||||
|---|---|
|
||||
| Refactoring nearby code while fixing one bug | Keep the diff scoped unless the nearby change is required |
|
||||
| Adding a helper used once | Keep direct code until reuse or composability is real |
|
||||
| Swallowing an error for smoother UX | Preserve the failure signal and handle presentation separately |
|
||||
| Updating a bridge without all runtimes | Load the runtime/API skill and make parity explicit |
|
||||
| Running only broad checks | Add focused tests that exercise the changed behavior |
|
||||
| Running only focused checks after a shared-contract change | Add workspace-wide validation |
|
||||
- Perform a final simplification pass: remove speculative branches, shallow wrappers, stale compatibility, and names that do not clarify intent.
|
||||
|
||||
@@ -11,6 +11,8 @@ Optimize the amount and frequency of work before optimizing individual operation
|
||||
|
||||
**Core principle:** Make expensive work structurally unnecessary. A fast inner function still freezes the app when called millions of times on the main thread.
|
||||
|
||||
Load `sync-state-invariants` when an optimization changes state authority, reconciliation, optimistic data, event ordering, cache lifecycle, or destructive cleanup. This skill owns measured cost; `sync-state-invariants` owns state correctness.
|
||||
|
||||
## Start With A Performance Contract
|
||||
|
||||
Define before editing:
|
||||
@@ -27,6 +29,8 @@ Do not optimize against a toy fixture when the report provides production scale.
|
||||
|
||||
## Workflow
|
||||
|
||||
Complete the numbered workflow in order. An optimization is complete only when the exact measured scenario meets its budget and separate correctness checks preserve every applicable state, identity, layout, and lifecycle transition.
|
||||
|
||||
### 0. Trust The Measurement Before Trusting The Number
|
||||
|
||||
A measurement setup that is wrong produces clean, confident, wrong numbers, and
|
||||
@@ -65,6 +69,8 @@ validity checks ran.
|
||||
|
||||
Do not infer a bottleneck from code appearance when a trace or counter can identify it.
|
||||
|
||||
Treat every proposed optimization as a hypothesis. Memoization, caches, indexes, workers, scheduling, retries, and lifecycle machinery must address an observed cost or failure in the measured path; “could be slow” or “might race” is not evidence. Keep only the smallest mechanism that meets the contract, except where an inherent security, data-loss, destructive-operation, or concurrency invariant requires proactive protection.
|
||||
|
||||
**Never accept an "after" without a "before" on the identical scenario and
|
||||
build.** Measuring a fixed build against a remembered number, a different
|
||||
scenario, or a nearby baseline proves nothing: the mechanism you changed may
|
||||
@@ -193,6 +199,8 @@ Add a cache only when all are explicit:
|
||||
- runtime/project/user isolation where identities can collide;
|
||||
- proof that caching removes enough work to meet the budget.
|
||||
|
||||
Do not introduce a cache merely to make an abstraction reusable or prepare for future consumers. First prove repeated work in the real path; then place the cache with the narrowest owner and lifetime that can invalidate it correctly.
|
||||
|
||||
A cache inside an `O(consumers × entities × candidates)` loop is a mitigation, not automatically a complete fix.
|
||||
|
||||
## Repository Tooling
|
||||
@@ -276,24 +284,6 @@ Ship a bounded cache-only or local mitigation under deadline pressure only when:
|
||||
|
||||
If the interaction remains above budget, do not call the mitigation the completed performance fix.
|
||||
|
||||
## Common Rationalizations
|
||||
|
||||
| Rationalization | Reality |
|
||||
|---|---|
|
||||
| "The helper is cheap" | Multiply it by events, entities, candidates, and consumers. |
|
||||
| "No component rerendered" | Selectors and equality comparisons may still burn CPU. |
|
||||
| "`useMemo` fixes it" | Memoization does not help when dependencies churn or consumers duplicate work. |
|
||||
| "The cache made it 10× faster" | Compare the result with the interaction budget, not only the baseline. |
|
||||
| "Projects are few" | Identify the dimension that is large and the dimensions multiplying it. |
|
||||
| "Move it to a worker" | Moving waste changes responsiveness, not total cost or data correctness. |
|
||||
| "Empty means nothing exists" | Empty after failure or partial loading is not authoritative absence. |
|
||||
| "We can optimize later" | Add a scale regression now or the multiplier will return. |
|
||||
| "The profile is clean" | Prove the instrument fired and the renderer was not throttled. A disabled instrument looks identical to a fast app. |
|
||||
| "It is much faster now" | Against which baseline, on which build, in which scenario? Re-run the unchanged build. |
|
||||
| "Most of the time is `(program)`" | The sampler cannot see native work. Read the timeline trace. |
|
||||
| "It does not reproduce here" | Compare your scale to the reporter's on the dimension the code keys on. |
|
||||
| "It cannot hurt to keep the change" | An unmeasured change is unvalidated complexity that hides the path from the next investigation. |
|
||||
|
||||
## Exit Checklist
|
||||
|
||||
- [ ] Measurement validity established: no throttling, instruments confirmed firing, workload comparable.
|
||||
|
||||
@@ -11,6 +11,8 @@ OpenChamber has a private relay: a client (mobile app, browser, another desktop)
|
||||
|
||||
Architecture overview: `packages/web/server/lib/relay/DOCUMENTATION.md`. Code: `packages/ui/src/lib/relay/` (client + shared, TS) and `packages/web/server/lib/relay/` (host, JS).
|
||||
|
||||
Load `ui-api-decoupling` when the change adds or alters a shared runtime API, URL/auth contract, bridge, proxy, or runtime-switch behavior. This skill owns relay mechanics; `ui-api-decoupling` owns the shared UI/runtime boundary.
|
||||
|
||||
**Why this skill exists:** relay bugs do not show up in normal testing. The event stream is SSE (which behaves differently from WebSockets), so a new WebSocket feature is often the *first* real WebSocket to cross the tunnel on mobile — and it fails there while working everywhere else. We have fixed the same class of bug across several iterations. The rules below are those lessons.
|
||||
|
||||
## The core mental model
|
||||
@@ -20,7 +22,7 @@ Architecture overview: `packages/web/server/lib/relay/DOCUMENTATION.md`. Code: `
|
||||
- HTTP and SSE authenticate with the client's **bearer token** (a header). They "just work" through the tunnel for any allowlisted `/api/*`, `/auth/*`, `/health` path.
|
||||
- **WebSockets cannot send headers.** They authenticate with a short-lived **URL-scoped token** (`oc_url_token`) that must be minted first and passed as a query parameter. This is the source of most relay WS bugs.
|
||||
|
||||
## Rules for adding or changing a WebSocket endpoint
|
||||
## WebSocket Endpoint Branch
|
||||
|
||||
Adding a new WS endpoint (or porting one, e.g. the planned terminal port) requires ALL of these, or it breaks over the relay:
|
||||
|
||||
@@ -32,19 +34,19 @@ Adding a new WS endpoint (or porting one, e.g. the planned terminal port) requir
|
||||
4. **Do not touch origin handling.** The server rejects WS upgrades whose `Origin` it does not trust. Over the tunnel the host dials loopback and presents the loopback origin (`http://127.0.0.1:<port>`), which the server trusts as same-origin — this already covers every allowlisted WS path. **Never reintroduce reliance on `window.location.origin`**: in the iOS WKWebView it is `"null"`/empty for the custom scheme, so forwarding it produces a 403.
|
||||
5. **Test over the relay, not just direct/desktop.** A new WS may be the first WebSocket the mobile client runs through the tunnel (events are SSE-locked on Capacitor). Passing on desktop or a direct connection proves nothing about the relay path.
|
||||
|
||||
## Rules for the tunnel/crypto/codec internals
|
||||
## Wire Format And Codec Branch
|
||||
|
||||
- **Two implementations must stay byte-compatible.** The E2EE and framing exist as TS (`packages/ui/src/lib/relay/{crypto,handshake,tunnel-codec}.ts`, normative) and a JS host mirror (`packages/web/server/lib/relay/{e2ee,tunnel-codec}.js`). Any wire-format, frame-type, handshake, or batching change must update **both** and keep `packages/web/server/lib/relay/cross-compat.test.js` green.
|
||||
- **Frame types live in `protocol.ts`** and must match across `protocol.ts`, `tunnel-codec.ts`, and `tunnel-codec.js`. Adding a frame type without mirroring it corrupts the stream on one side.
|
||||
- **Frame batching is capability-negotiated** in the handshake with a legacy fallback, so mixed client/host app versions still interoperate. Preserve the negotiation and the single-frame fallback; do not make batching unconditional.
|
||||
- **The encrypted-frame counter/IV is per-direction and strictly increasing.** One encrypted WS message = one encrypt call = one counter tick. Keep encrypt+send serialized per direction; do not reorder or parallelize it.
|
||||
|
||||
## Rules for the runtime transport layer
|
||||
## Runtime Transport Branch
|
||||
|
||||
- Relay mode routes through `runtime-switch` (activates the tunnel singleton), `runtime-fetch` (routes runtime requests through it), `runtime-url`/`runtime-socket` (tunnel-backed URLs/sockets), and `runtime-auth` (mints the URL token through the tunnel). When refactoring any of these, preserve the relay branch and the direct-URL/Electron-realtime-proxy branches — they must remain byte-identical in behavior for non-relay runtimes.
|
||||
- **The host dispatcher never injects credentials.** Tunneled requests carry the client's own token; the server authenticates them. Do not add host-side auth shortcuts, and do not trust loopback source address as authentication (relay traffic arrives at loopback but represents remote clients).
|
||||
|
||||
## Reconnect pacing
|
||||
## Reconnect Branch
|
||||
|
||||
For indefinite SSE/WebSocket reconnect loops:
|
||||
|
||||
@@ -56,17 +58,10 @@ For indefinite SSE/WebSocket reconnect loops:
|
||||
|
||||
Blind short retries on hidden, offline, unauthorized, or stale-path clients waste battery and flood server logs.
|
||||
|
||||
## Testing guidance (a stub that skips auth/origin hides the exact bugs)
|
||||
## Verification
|
||||
|
||||
- Exercise the real auth and origin gates. An end-to-end test whose stub server accepts any WS upgrade will pass while the real server rejects it — this is precisely how the origin-check bug shipped. When writing a relay integration test, mirror the real gates (`ensureSessionToken` via `oc_url_token`, `isRequestOriginAllowed`) or run against the real server pieces.
|
||||
- Run relay tests per file (`bun test <file>`); the suite has order sensitivity.
|
||||
- Validate both sides: `packages/ui` `type-check`/`lint`, and `node --check` on changed JS host files.
|
||||
|
||||
## Quick checklist before finishing relay-adjacent work
|
||||
|
||||
- [ ] New WS endpoint added to `ALLOWED_WS_PATHS` AND `isUrlAuthWebSocketPath`?
|
||||
- [ ] UI opens it via `openRuntimeWebSocket`, not `new WebSocket`?
|
||||
- [ ] URL token minted before the WS connects?
|
||||
- [ ] No new dependence on `window.location.origin`?
|
||||
- [ ] Wire/codec/handshake change mirrored in TS and JS, cross-compat test green?
|
||||
- [ ] Direct and relay paths both still work; verified over the relay on the transport that actually uses it?
|
||||
Completion requires every applicable branch above: WS path allowlists/auth/origin and real relay exercise; mirrored TS/JS wire changes with cross-compat coverage; preserved direct and relay runtime branches; or reconnect pacing under offline, hidden, permanent-failure, recovery, and abort conditions.
|
||||
|
||||
@@ -7,44 +7,34 @@ description: Use when working with the OpenChamber iOS Simulator app without ope
|
||||
|
||||
Use `serve-sim` to stream and control a booted Apple Simulator from the terminal. It captures the simulator framebuffer, serves a browser preview, and exposes CLI controls for taps, typing, gestures, hardware buttons, rotation, memory warnings, permissions, camera injection, and accessibility inspection.
|
||||
|
||||
## OpenChamber Defaults
|
||||
## Scripted Workflow
|
||||
|
||||
- Mobile package: `packages/mobile`
|
||||
- iOS bundle id: `com.openchamber.app`
|
||||
- Headless env wrapper: `packages/mobile/scripts/with-mobile-env.mjs`
|
||||
- iOS simulator helper: `packages/mobile/scripts/ios-sim.mjs`
|
||||
- Preferred scripts:
|
||||
- `bun run mobile:build:ios:simulator`
|
||||
- `bun run mobile:sim:run`
|
||||
- `bun run mobile:sim:serve`
|
||||
- `bun run mobile:sim:list`
|
||||
- `bun run mobile:sim:kill`
|
||||
- `bun run mobile:sim:dev` — foreground build + run + stream in one command (`--no-build` to skip the build); intended for the user, agents should prefer the discrete scripts above
|
||||
Run the discrete scripts from the repository root so each step has an observable completion boundary:
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Build the simulator app without opening Xcode:
|
||||
1. Build the simulator app:
|
||||
```sh
|
||||
bun run mobile:build:ios:simulator
|
||||
```
|
||||
|
||||
2. Boot a simulator if needed, install, and launch the app:
|
||||
2. Boot if needed, install, and launch:
|
||||
```sh
|
||||
bun run mobile:sim:run
|
||||
```
|
||||
|
||||
3. Start the browser stream in detached JSON mode:
|
||||
3. Start the detached browser stream:
|
||||
```sh
|
||||
bun run mobile:sim:serve
|
||||
```
|
||||
Surface the returned `url` to the user. It normally starts at `http://127.0.0.1:3100`; always use the `url` from the JSON output rather than assuming the port.
|
||||
Surface the returned JSON `url`; it is the only authoritative stream address.
|
||||
|
||||
4. Stop helpers when finished unless the user asks to keep them running:
|
||||
```sh
|
||||
bun run mobile:sim:kill
|
||||
```
|
||||
|
||||
## Direct CLI Controls
|
||||
Completion means the app launched, the returned stream URL was surfaced, requested interactions were verified, and helpers were stopped or intentionally left running.
|
||||
|
||||
## Manual Controls
|
||||
|
||||
- Tap normalized coordinates: `bunx serve-sim tap 0.5 0.5`
|
||||
- Type focused text: `bunx serve-sim type "hello"`
|
||||
@@ -64,9 +54,4 @@ Coordinates are normalized `0..1`, not pixels. Prefer `tap` for simple taps; do
|
||||
- Node 18+.
|
||||
- At least one simulator can be booted with `xcrun simctl`.
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Do not open Xcode just to build/install/launch during agent work; use the scripts above.
|
||||
- Do not parse human output from `serve-sim`; use `-q` for JSON.
|
||||
- Do not leave helper streams running unintentionally.
|
||||
- Do not guess coordinates after accessibility lookup fails; report the missing target instead.
|
||||
Use the scripts above instead of opening Xcode for build/install/launch. Consume JSON output rather than parsing human output. If accessibility lookup cannot identify a target, report the missing target instead of guessing coordinates.
|
||||
|
||||
@@ -36,7 +36,7 @@ shape is genuinely missing.
|
||||
| Field rows, checkboxes, radios, chips, selects, inputs, numeric steppers, info hints | `references/controls.md` |
|
||||
| Adding/moving controls, pages, availability, anchors, or search entries | `references/search.md` |
|
||||
|
||||
Load every matching reference before editing.
|
||||
Load each reference whose task branch applies; reference loading is complete when layout, control, and search implications are each classified.
|
||||
|
||||
## Quick Primitive Selection
|
||||
|
||||
@@ -77,7 +77,7 @@ Every stable Settings control addition or move must consider search in the same
|
||||
|
||||
Dynamic entity rows normally are not indexed. Load `references/search.md` for exact rules.
|
||||
|
||||
## Review Checklist
|
||||
## Completion Criteria
|
||||
|
||||
- Built from shared primitives; no ad-hoc page/section/row markup.
|
||||
- Explanatory text hidden behind `info`; warnings/syntax/status still visible.
|
||||
|
||||
@@ -5,9 +5,9 @@ description: Use when changing session synchronization, bootstrap or reconnect s
|
||||
|
||||
# Sync State Invariants
|
||||
|
||||
## Read First
|
||||
## Required Context
|
||||
|
||||
Read `packages/ui/src/sync/DOCUMENTATION.md` and the nearest owning module documentation before editing.
|
||||
Read `packages/ui/src/sync/DOCUMENTATION.md` and the nearest owning module documentation before editing. Context gathering is complete when every changed state has an identified owner, authority, scope, and lifecycle.
|
||||
|
||||
## Sources Of Truth
|
||||
|
||||
@@ -22,6 +22,10 @@ Classify every input before deriving state:
|
||||
|
||||
Prefer deterministic authoritative records over heuristics. Derive live behavior from live channels, not historical anomalies.
|
||||
|
||||
Give each state and its invariants one owner. Callers request domain transitions from that owner; they do not inspect one field, mutate another collection, and repair status externally. Split ownership only when the states have genuinely independent lifecycles.
|
||||
|
||||
Represent mutually exclusive lifecycle states with discriminated unions or equally precise contracts. Avoid boolean/nullable field combinations that permit impossible states. Reject invalid transitions at the owning boundary so downstream reducers and effects receive trusted state.
|
||||
|
||||
## Failure Is Not Empty
|
||||
|
||||
Any authoritative loader whose result can replace, delete, or clear state must distinguish failure from successful empty data.
|
||||
@@ -53,6 +57,7 @@ Inferring destructive cleanup from disappearance between snapshots requires an e
|
||||
|
||||
## Event Reducers
|
||||
|
||||
- Make the valid transition path explicit and flat. Return early for irrelevant entities and semantic no-ops; assert or reject transitions that violate an established invariant.
|
||||
- Clone only fields the event mutates; preserve every unrelated reference.
|
||||
- Return no change for semantically identical events.
|
||||
- Gate scans behind cheap event/entity checks.
|
||||
@@ -76,6 +81,7 @@ For streaming-frequency work, also load `performance-engineering`.
|
||||
|
||||
## Optimistic Updates
|
||||
|
||||
- Keep optimistic promotion, reconciliation, and rollback behavior behind the store/module that owns both visible and shadow state; do not expose collections for callers to mutate independently.
|
||||
- Insert optimistic data into the visible store and a separate shadow tracker.
|
||||
- Use client-generated IDs accepted and echoed by the server to reconcile in place.
|
||||
- Remove optimistic data from both visible and shadow state on failure.
|
||||
@@ -133,7 +139,7 @@ When state exists in memory and one or more persistent stores, define an explici
|
||||
|
||||
## Verification
|
||||
|
||||
Cover the relevant lifecycle, not only static state:
|
||||
Cover every applicable lifecycle branch, not only static state. Verification is complete when failure cannot masquerade as empty success, stale or partial data cannot cause destructive replacement, and each transition remains with its owner:
|
||||
|
||||
- fresh bootstrap and successful empty result;
|
||||
- fetch failure preserving prior state;
|
||||
@@ -147,17 +153,3 @@ Cover the relevant lifecycle, not only static state:
|
||||
- identity-preserving moves/category changes and runtime/scope changes resetting cleanup baselines;
|
||||
- create, update, move, archive, and delete mutations surviving responses started before those mutations;
|
||||
- missing versus empty persistence, malformed payloads, out-of-order writes, hydration races, and lifecycle durability behavior.
|
||||
|
||||
## Red Flags
|
||||
|
||||
- Fetch helper catches and returns `[]`.
|
||||
- Historical message/session data drives a live spinner.
|
||||
- One failed entity blocks or clears all entities.
|
||||
- Light polling overwrites fields it did not fetch.
|
||||
- Queue reads current model/agent at send time.
|
||||
- New session lookup assumes SSE already indexed it.
|
||||
- Optimistic data has no shadow entry or rollback.
|
||||
- Snapshot-difference cleanup treats its first startup snapshot as a disappearance event.
|
||||
- Eviction runs on the acquisition path, or a cache limit is raised in response to a request loop.
|
||||
- Missing or malformed persistence becomes authoritative empty state.
|
||||
- Debounced writes are canceled on owner/lifecycle change without completing against the captured owner or an explicit durability/data-loss contract.
|
||||
|
||||
@@ -10,7 +10,7 @@ description: Use when creating or modifying OpenChamber UI components, styling,
|
||||
- Use semantic OpenChamber theme tokens; never hardcode hex colors or generic Tailwind palette colors.
|
||||
- Use shared UI primitives before introducing feature-local controls.
|
||||
- Use the shared `Button`; do not create button wrappers such as `ButtonSmall` or `ButtonLarge`.
|
||||
- Every dropdown-style value-picker trigger (shows current value, opens a picker) takes its chrome from `dropdownTriggerVariants` in `packages/ui/src/components/ui/dropdown-trigger.ts` (sizes: `sm` dense h-6, `default` forms h-8; native `SelectTrigger` consumes it). Call sites add layout classes only (width/truncation) — never re-declare border/radius/bg/hover. Deliberately chrome-less pickers (chat composer, headers) are the only exception.
|
||||
- Every dropdown-style value-picker trigger takes its chrome from `dropdownTriggerVariants` in `packages/ui/src/components/ui/dropdown-trigger.ts`; call sites add layout classes only. Deliberately chrome-less pickers in composers or headers are the exception.
|
||||
- Use the sprite-based `Icon`; never import icons directly from `@remixicon/react`.
|
||||
- Apply hover tokens only to interactive elements.
|
||||
- Use status colors only for actual status/feedback.
|
||||
@@ -24,7 +24,7 @@ description: Use when creating or modifying OpenChamber UI components, styling,
|
||||
| Adding, converting, storing, or generating icons | `references/icons.md` |
|
||||
| Adding built-in or custom themes | `references/adding-themes.md` |
|
||||
|
||||
Load every matching reference before editing. Settings work must also load `settings-ui-patterns`; user-facing or accessible text must load `locale-ui-patterns`.
|
||||
Load every matching reference before editing. User-facing or accessible text must load `locale-ui-patterns`. Settings composition is owned by `settings-ui-patterns`, which declares `theme-system` as its one-way companion.
|
||||
|
||||
## Token Decision
|
||||
|
||||
@@ -73,30 +73,11 @@ Use `IconName` for icon values stored in arrays, objects, state, or config. `Ico
|
||||
|
||||
## Animation Contract
|
||||
|
||||
Animate only `transform` and `opacity`. The compositor drives those; every other
|
||||
property recalculates style on each frame for as long as the animation runs, and
|
||||
geometry properties add layout on top. Measured on this repository's fixture,
|
||||
identical at any element count from 1 to 32:
|
||||
Animate only `transform` and `opacity`. Use `transform: rotate(...)`, not the individual `rotate` property. Non-composited properties recalculate style continuously; geometry also triggers layout, and wrappers, `will-change`, `contain`, or stepped timing do not remove that cost. Animate only while conveying live information.
|
||||
|
||||
| Animated property | Style recalculations/sec | Layouts/sec |
|
||||
|---|---|---|
|
||||
| `transform`, `opacity`, `filter` | 0 | 0 |
|
||||
| `rotate` (the individual property) | 60 | 0 |
|
||||
| `background-position`, `border-color`, `box-shadow` | 60 | 0 |
|
||||
| `width` and other geometry | 60 | 60 |
|
||||
For any other technique, load `performance-engineering` and `scripts/perf/DOCUMENTATION.md`, measure it with `bun run profile:animation`, and add a fixture variant when needed. This skill owns animation styling; `performance-engineering` owns performance evidence.
|
||||
|
||||
- `rotate: 360deg` is not a cheap synonym for `transform: rotate(360deg)`.
|
||||
Prefer the `transform` form.
|
||||
- Cost applies for the entire time an animation runs, so an indicator tied to a
|
||||
long-running operation pays it continuously. An indicator that is not
|
||||
conveying anything should not be animating.
|
||||
- `will-change`, wrapper elements, `contain`, and `steps()` timing do not make a
|
||||
non-composited property cheap. Only changing the property does.
|
||||
- Verify with `bun run profile:animation` rather than reasoning about it; add a
|
||||
variant to `scripts/perf/animation-fixture.html` for a technique not covered.
|
||||
See `scripts/perf/DOCUMENTATION.md`.
|
||||
|
||||
## Verification
|
||||
## Completion Criteria
|
||||
|
||||
- Animations are limited to `transform` and `opacity`, or their cost was measured and accepted.
|
||||
- No hardcoded/palette colors were introduced.
|
||||
@@ -104,4 +85,4 @@ identical at any element count from 1 to 32:
|
||||
- Icons use `Icon`/`IconName`, and generated sprite changes are intentional.
|
||||
- Hover, selection, primary, and status semantics are distinct.
|
||||
- Light/dark/high-contrast and long-text states remain legible.
|
||||
- Relevant type-check, visual/runtime validation, and generated-asset checks ran.
|
||||
- Every applicable contract and loaded task reference was verified with relevant type-check, visual/runtime validation, and generated-asset checks.
|
||||
|
||||
@@ -43,6 +43,15 @@ export const presetThemes: Theme[] = [
|
||||
bun run type-check && bun run lint && bun run build
|
||||
```
|
||||
|
||||
## Authoring Tools
|
||||
|
||||
Both do the mechanical work of steps 1–2 and are run by hand:
|
||||
|
||||
- `node scripts/convert-vscode-theme.cjs <vscode-theme.json>` converts a VS Code
|
||||
theme into this format and registers it in `presets.ts`.
|
||||
- `node scripts/harmonize-theme.mjs <theme.json> [--write]` aligns accent roles
|
||||
to one chroma/lightness target in OKLCH so borrowed colors read as one family.
|
||||
|
||||
## Key Files
|
||||
|
||||
- Theme types: `packages/ui/src/types/theme.ts`
|
||||
|
||||
@@ -11,6 +11,7 @@ description: Use when creating or modifying OpenChamber shared UI data access, O
|
||||
- OpenChamber-owned HTTP capabilities use `RuntimeAPIs` where runtime-specific behavior exists, otherwise explicit OpenChamber routes through `runtimeFetch`.
|
||||
- Browser/realtime consumers use shared runtime URL/socket helpers.
|
||||
- Shared UI never hardcodes localhost, ports, API origins, credentials, or one runtime's transport assumptions.
|
||||
- Treat runtime adapters as the imperative shell: they own transport, auth, serialization, and platform mechanics. Shared feature code receives trusted contracts and owns domain decisions.
|
||||
|
||||
## Classify First
|
||||
|
||||
@@ -27,7 +28,7 @@ description: Use when creating or modifying OpenChamber shared UI data access, O
|
||||
|
||||
| Task | Required reference |
|
||||
|---|---|
|
||||
| Iframes, downloads, raw images, object URLs, URL tokens, preview proxy/subresources | `references/browser-assets-and-auth.md` |
|
||||
| Iframes, downloads, raw images, object URLs, URL tokens | `references/browser-assets-and-auth.md` |
|
||||
| Adding runtime capabilities, VS Code behavior, Electron privilege/security, unsupported runtime behavior | `references/runtime-parity.md` |
|
||||
| Locating implementations, route registration, runtime switching, or focused tests | `references/implementation-map.md` |
|
||||
|
||||
@@ -45,6 +46,9 @@ Load every matching reference before editing.
|
||||
8. **Authoritative fetches must signal failure.** Do not convert failure into a valid empty value that callers use to clear state.
|
||||
9. **Keep privileges at the native/runtime boundary.** UI visibility and prompts are not authorization.
|
||||
10. **Confirm trust-boundary mutations.** Host imports, credential writes, privileged deep links, and runtime switching require explicit user intent.
|
||||
11. **Parse at the boundary.** Treat external, persisted, bridge, IPC, and network payloads as unknown until a schema, parser, or narrow constructor produces the trusted type consumed by shared code. Do not validate fields and then continue passing the raw payload.
|
||||
12. **Model the real contract.** Prefer precise result/state unions and required dependencies over loose strings, boolean combinations, optional callback bags, `any`, or repeated casts. Make unsupported runtime behavior and failure distinct from valid empty success.
|
||||
13. **Keep adapters deep and bridges thin.** Hide meaningful protocol or platform mechanics behind an intention-revealing runtime operation; do not add pass-through layers that only rename SDK, fetch, or bridge calls.
|
||||
|
||||
## HTTP Decision Rules
|
||||
|
||||
@@ -59,7 +63,7 @@ await runtimeFetch('/api/fs/raw', { query: { path } });
|
||||
Do not immediately fetch a URL produced by `getRuntimeUrlResolver()`. Use the resolver only when the browser/realtime API itself consumes the URL:
|
||||
|
||||
```ts
|
||||
const iframeSrc = getRuntimeUrlResolver().authenticatedAsset('/api/preview/frame');
|
||||
const imageSrc = getRuntimeUrlResolver().authenticatedAsset('/api/fs/raw?path=diagram.png');
|
||||
const eventUrl = getRuntimeUrlResolver().sse('/api/event');
|
||||
```
|
||||
|
||||
@@ -69,6 +73,8 @@ Plain `fetch` is reserved for intentional external origins that are not the acti
|
||||
|
||||
Review runtime base URL, auth, SDK clients, terminal/realtime transports, stores, session memory, and caches. Key caches by runtime identity where IDs, paths, or URLs can collide. Reset or reconnect affected state through the established runtime-switch flow.
|
||||
|
||||
Re-parse values obtained after a switch at their owning boundary. A type established for one runtime response does not make cached raw data from another runtime trustworthy.
|
||||
|
||||
## Common Anti-Patterns
|
||||
|
||||
| Avoid | Use |
|
||||
@@ -80,6 +86,8 @@ Review runtime base URL, auth, SDK clients, terminal/realtime transports, stores
|
||||
| Web-only shared route | Explicit VS Code/mobile decision |
|
||||
| Returning `[]` after authoritative fetch failure | Throw or distinct failure result |
|
||||
| Rebuilding SDK `Request` from URL only | Preserve original request body/headers/signal |
|
||||
| Component validates unknown JSON then passes it onward | Adapter parses once and returns a trusted contract |
|
||||
| Boolean/nullable combinations for exclusive outcomes | Discriminated result or state union |
|
||||
|
||||
## Verification
|
||||
|
||||
|
||||
@@ -28,12 +28,20 @@ Browser-owned URLs cannot attach the normal `Authorization` header. Use short-li
|
||||
- Add browser-readable GET or realtime paths to the narrow allowlist in `packages/web/server/lib/ui-auth/ui-auth.js`.
|
||||
- Add allowlist tests; never allow arbitrary `/api/*` URL-token access.
|
||||
|
||||
## Preview Iframes And Rewritten Resources
|
||||
## Showing Somebody Else's Page
|
||||
|
||||
- Use preview proxy helpers so preview and URL tokens propagate to rewritten resources and redirects.
|
||||
- Strip legacy client-token query parameters before forwarding upstream.
|
||||
- Do not use `postMessage('*')`; target the known preview origin.
|
||||
- Preserve CSP where possible. If injecting a bridge, prefer a per-response nonce and remove only directives that block framing or the bridge.
|
||||
OpenChamber does not rewrite third-party HTML to display it. Rewriting a page to
|
||||
serve it under our origin and a path prefix breaks every absolute URL on it, and
|
||||
recovering from that means encoding knowledge of each framework's dev-server
|
||||
internals — which ages badly and fails silently.
|
||||
|
||||
- The in-app browser renders a real Chromium `<webview>` (`packages/ui/src/components/browser/`).
|
||||
- A dev server on a remote OpenChamber host is reached by binding a local port
|
||||
and tunnelling raw bytes (`packages/web/server/lib/dev-tunnel/`), so the page
|
||||
keeps its own origin at the root of its own host.
|
||||
- Runtimes without a Chromium host fall back to a plain iframe that can display
|
||||
a page but cannot inspect one. State that limit; do not emulate around it.
|
||||
- Do not use `postMessage('*')`; target a known origin.
|
||||
- Re-resolve browser URLs after runtime switches; do not retain URLs minted for an old runtime.
|
||||
|
||||
## Security Tests
|
||||
@@ -43,4 +51,4 @@ Prefer focused coverage in:
|
||||
- `packages/ui/src/lib/runtime-url.test.ts`
|
||||
- `packages/ui/src/lib/runtime-auth.test.ts`
|
||||
- `packages/web/server/lib/ui-auth/ui-auth.test.js`
|
||||
- `packages/web/server/lib/preview/proxy-runtime.test.js`
|
||||
- `packages/web/server/lib/dev-tunnel/tunnel.test.js`
|
||||
|
||||
@@ -42,7 +42,7 @@ Review every cache keyed only by session ID, directory, URL, or entity ID. Add r
|
||||
- URL/auth: `packages/ui/src/lib/runtime-url.test.ts`, `runtime-auth.test.ts`
|
||||
- Server auth: `packages/web/server/lib/ui-auth/ui-auth.test.js`
|
||||
- Generic proxy: `packages/web/server/opencode-proxy.test.js`
|
||||
- Preview proxy: `packages/web/server/lib/preview/proxy-runtime.test.js`
|
||||
- Dev-server tunnel: `packages/web/server/lib/dev-tunnel/tunnel.test.js`
|
||||
- VS Code bridge: `packages/vscode/webview/api/bridge.test.ts`
|
||||
- VS Code proxy: `packages/vscode/src/bridge-proxy-runtime.test.js`
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
name: writing-for-agents
|
||||
description: Writing documents for agents. Use when creating or editing skills or modifying AGENTS.md.
|
||||
author: Matt Pocock
|
||||
---
|
||||
|
||||
Reference for writing any document an agent consumes — a skill, an `AGENTS.md`, a doc reached by a pointer. The packaging differs; the writing does not: the same levers make each one predictable — the agent taking the same _process_ every run, not producing the same output.
|
||||
|
||||
## Context pointers
|
||||
|
||||
A **context pointer** is a reference held in the agent's context that names some out-of-context material and encodes the condition for reaching it. A skill's description is one; a line in `AGENTS.md` naming a doc is the same object. The pointer's _wording_, not its target, decides when the agent reaches the material — and how reliably. A must-have target behind a weakly worded pointer is a variance bug: sharpen the wording first, and inline the material only if sharpening fails.
|
||||
|
||||
A pointer does two jobs — state what the material is, and list the **branches** that should trigger reaching it (a branch is a distinct case the document handles, so different runs take different paths through it). Every word of an always-loaded pointer costs on every turn, so it earns even harder pruning than the body:
|
||||
|
||||
- **Front-load the leading word** — the pointer is where it does its triggering work.
|
||||
- **One trigger per branch.** Synonyms that rename a single branch are one branch written twice; collapse them and keep only genuinely distinct branches.
|
||||
- **Cut identity the body already carries.**
|
||||
|
||||
## The two loads
|
||||
|
||||
Every document and pointer you add spends one of two budgets:
|
||||
|
||||
- **Context load** — the cost of always-loaded material on the agent's window: an `AGENTS.md` line, a skill description, anything sitting in context every turn, spending tokens and attention whether or not it fires.
|
||||
- **Cognitive load** — the cost on the human: which documents exist and when to reach for each. The human is the index. Not a cost to minimise — it is the price of human agency; spend it where human judgement matters, remove it where it does not.
|
||||
|
||||
Material reached only through a pointer escapes context load at the price of the pointer's own line; material with no pointer at all rides entirely on cognitive load.
|
||||
|
||||
## Information hierarchy
|
||||
|
||||
A document is built from two content types — **steps** (the ordered actions the agent performs) and **reference** (definitions, rules, facts consulted on demand) — that mix freely: all steps (a recipe), all reference (a review's rules, this skill), or both. The core decision is where each piece sits on the **information hierarchy**, a ladder ranked by how immediately the agent needs the material:
|
||||
|
||||
1. **In-file step** — the primary tier: what the agent does, in order.
|
||||
2. **In-file reference** — consulted on demand. Often a legitimately flat peer-set (every rule of a review on one rung) — a fine arrangement, not a smell.
|
||||
3. **Disclosed reference** — pushed out into a separate file, reached by a context pointer, loaded only when the pointer fires. Spans a sibling file in the same folder through fully external reference that lives anywhere and any document can point at.
|
||||
|
||||
Push too little down and the top bloats; push too much and you hide material the agent actually needs. That tension is the whole decision.
|
||||
|
||||
**Progressive disclosure** is the move down the ladder — out of the main file and behind a pointer — so the top stays legible. Not primarily a token optimisation: it is how the hierarchy is protected. Branching is the cleanest disclosure test: inline what every branch needs, and push behind a pointer what only some branches reach. When a document has steps, in-file reference that should be disclosed buries them and turns attending to them into a coin-flip — a variance lever, not just a legibility one.
|
||||
|
||||
**Co-location** is the within-file companion: where the ladder decides _how far down_ a piece sits, co-location decides _what sits beside it_ once there. Keep a concept's definition, rules, and caveats under one heading rather than scattered, so reading one part brings its neighbours with it. The test: the document should read like documentation written for the agent — grouped material reads that way; scattered material does not. (Distinct from duplication: that repeats one meaning in two places; scattering fragments one meaning across many.)
|
||||
|
||||
**Sprawl** is the failure mode here: a document simply too long, even when every line is live and unique. Attention thins across the excess, and every extra line is one more to keep relevant. The cure is the ladder: disclose reference behind pointers, and split by branch or sequence so each path carries only what it needs.
|
||||
|
||||
## Steps and completion criteria
|
||||
|
||||
Every step ends on a **completion criterion** — the condition that tells the agent the work is done. Two properties make it a lever:
|
||||
|
||||
- **Clarity** — can the agent tell done from not-done? A vague bound ("understanding reached") invites **premature completion**: ending the step before it is genuinely done, attention slipping to _being done_. The visible steps still ahead — the **post-completion steps** — supply the pull; the criterion's clarity is the resistance. Defend in order: **sharpen the bound first** (local and cheap); only if it is irreducibly fuzzy _and_ you observe the rush, hide the later steps by splitting the sequence — and hiding only works across a real context boundary (a hand-off or a subagent dispatch; an inline call leaves the later steps in context and clears nothing).
|
||||
- **Demand** — how much it requires. "Every modified model accounted for" forces thorough work where "produce a change list" does not. Demand drives **legwork** — the digging the agent does within the work, latent in the wording rather than written as its own step — and it is not step-bound: "every rule applied" binds a body of flat reference just as "every step done" binds a sequence, which is how an all-reference document still carries an exhaustiveness bar.
|
||||
|
||||
The strongest criteria are both checkable and exhaustive.
|
||||
|
||||
## When to split
|
||||
|
||||
Splitting one document into two spends one of the two loads, so split only when the cut earns it:
|
||||
|
||||
- **By sequence** — split a run of steps where the post-completion steps tempt the agent to rush the one in front of it. Keeping them out of view drives more legwork on the current task. Beware the reverse: merging sequences exposes each step's later steps to what follows, inviting premature completion.
|
||||
|
||||
## Leading words
|
||||
|
||||
A **leading word** is a compact concept already living in the model's pretraining that the agent thinks with while running the document (_lesson_, _fog of war_, _tracer bullets_). Repeated as a token, never as a sentence, it accumulates a distributed definition and anchors a whole region of behaviour in the fewest tokens, by recruiting priors the model already holds. Coining your own works if you define it clearly, but a made-up word recruits no priors — you pay in definition tokens what a pretrained word gives free; reach for an existing word first.
|
||||
|
||||
It anchors twice. In the body, _execution_: the agent reaches for the same behaviour every time the word appears, and inside flat reference it focuses attention on a class of thing to look for. In a pointer, _invocation_: when the same word lives in your prompts, your docs, and your codebase, the agent links that shared language to the material and reaches it more reliably.
|
||||
|
||||
Hunt for opportunities to refactor with leading words. A triad spelled out at three sites, a pointer spending a sentence to gesture at one idea — each is a passage begging to collapse into a single token:
|
||||
|
||||
- "fast, deterministic, low-overhead" → _tight_ (a _tight_ loop).
|
||||
- "a loop you believe in" → _red_ — a fuzzy gate becomes a binary observable state (the loop goes _red_ on the bug, or it doesn't).
|
||||
|
||||
You win twice: fewer tokens, and a sharper hook for the agent to hang its thinking on. Assume every document is carrying restatements that leading words retire — go find them.
|
||||
|
||||
**Negation** is the failure mode beside this lever: steering by prohibition drags the forbidden behaviour into context and makes it _more_ available, not less. _Don't think of an elephant_, and the elephant is all there is; the negation is a weak modifier the strongly-activated concept overruns, so the ban half-reads as an instruction to do the thing. Prompt the **positive** — state the target behaviour ("write one-line comments") so the banned one is never spoken. A prohibition earns its place only as a hard guardrail you cannot phrase positively; even then, pair it with the positive target so attention lands on what to do.
|
||||
|
||||
## Pruning
|
||||
|
||||
- Keep each meaning in a **single source of truth**: one authoritative place, so changing the behaviour is a one-place edit. **Duplication** — the same meaning in more than one place — costs maintenance and tokens, and inflates a meaning's prominence on the ladder past its real rank. (The accidental inverse of a leading word, which repeats a token on purpose, never the meaning.)
|
||||
- For cross-document guidance, name one canonical owner. Other documents point to it and state only their local consequence; they do not restate the shared rule.
|
||||
- The **environment** is a source of truth too — `package.json` scripts, config files, the directory layout, `--help` output — and a document that restates it is a **cache**: a copy of a lookup, earning its load only when the lookup is expensive. Cache what the agent cannot find by looking: the unwritten convention, the reason behind a choice, the gotcha no config confesses. Leave the one-file, one-command lookups to the environment, where they cannot go stale.
|
||||
- Check every line for **relevance**: does it still bear on what the document does? A line loses relevance by never bearing on the task (mere exposition, or a branch that should be disclosed) or by going stale as the behaviour or world it describes changes. Shorter documents are easier to keep relevant. Without a pruning discipline the default fate is **sediment**: stale layers that settle because adding feels safe and removing feels risky, until you must core down through them to find what is still live.
|
||||
- Hunt **no-ops** sentence by sentence: an instruction the model already obeys by default pays load to say nothing. The test — does it change behaviour versus the default? — is model-relative, not reader-relative: two people disagreeing about a no-op disagree about the default, and settle it by running the document, not by debate. When a sentence fails, delete the whole sentence rather than trim words from it. The test also grades leading words: a word too weak to beat the default (_be thorough_ when the agent is already thorough-ish) is a no-op, and the fix is a stronger word (_relentless_), not a different technique.
|
||||
@@ -32,6 +32,9 @@ jobs:
|
||||
- name: Lint
|
||||
run: bun run lint
|
||||
|
||||
- name: Tests
|
||||
run: bun run test
|
||||
|
||||
- name: Electron Linux packaging unit tests
|
||||
working-directory: packages/electron
|
||||
run: |
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
name: pr-review
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
# PR conversation comments arrive as `issue_comment` events, so their PR number
|
||||
|
||||
@@ -24,13 +24,13 @@ jobs:
|
||||
- uses: actions/stale@eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899 # v10.3.0
|
||||
with:
|
||||
repo-token: ${{ steps.app-token.outputs.token }}
|
||||
days-before-stale: 60
|
||||
days-before-stale: 28
|
||||
days-before-close: 7
|
||||
stale-issue-label: stale
|
||||
stale-pr-label: stale
|
||||
stale-issue-message: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
any activity in the last 60 days. It will be closed in 7 days if no
|
||||
any activity in the last 28 days. It will be closed in 7 days if no
|
||||
further activity occurs.
|
||||
close-issue-message: >
|
||||
This issue has been automatically closed because it has been stale for
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
reopen the issue.
|
||||
stale-pr-message: >
|
||||
This pull request has been automatically marked as stale because it has
|
||||
not had any activity in the last 60 days. It will be closed in 7 days
|
||||
not had any activity in the last 28 days. It will be closed in 7 days
|
||||
if no further activity occurs.
|
||||
close-pr-message: >
|
||||
This pull request has been automatically closed because it has been
|
||||
|
||||
+4
-1
@@ -24,6 +24,7 @@ changelog-*.png
|
||||
/openchamber@*
|
||||
local-dev*
|
||||
.tmp/
|
||||
/tmp/
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
@@ -67,6 +68,8 @@ data/
|
||||
workspaces/
|
||||
*.pid
|
||||
.worktrees/
|
||||
|
||||
# Marks a disposable clone dedicated to unattended maintenance tasks.
|
||||
.maintenance-clone
|
||||
test-results/
|
||||
artifacts/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
mode: primary
|
||||
hidden: true
|
||||
model: opencode-go/deepseek-v4-flash
|
||||
model: opencode-go/mimo-v2.5
|
||||
color: "#c0392b"
|
||||
permission:
|
||||
edit: allow
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
mode: primary
|
||||
hidden: true
|
||||
model: opencode-go/deepseek-v4-flash
|
||||
model: opencode-go/mimo-v2.5
|
||||
color: "#4f8f8f"
|
||||
permission:
|
||||
edit: deny
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
mode: primary
|
||||
hidden: true
|
||||
model: opencode-go/deepseek-v4-flash
|
||||
model: opencode-go/mimo-v2.5
|
||||
color: "#c4920a"
|
||||
permission:
|
||||
edit: deny
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
---
|
||||
description: Create an anti-slop lint cleanup PR from the next generated batch
|
||||
agent: build
|
||||
---
|
||||
|
||||
You are working in the OpenChamber repository.
|
||||
|
||||
Goal: reduce anti-slop Oxlint findings in a small, reviewable maintenance PR.
|
||||
|
||||
This task can run unattended on a schedule, so it must be safe to start at any moment and must stop cleanly when there is nothing to do.
|
||||
|
||||
First, verify the worktree is safe to use:
|
||||
|
||||
`git status --porcelain`
|
||||
|
||||
If the output is not empty, decide which of two situations you are in.
|
||||
|
||||
If the repository root contains a `.maintenance-clone` marker file, this working copy is a disposable clone dedicated to unattended maintenance. Nothing in it is human work in progress, so leftover changes are debris from an earlier task that failed to clean up after itself. Recover the clone rather than stopping:
|
||||
|
||||
```
|
||||
git checkout -- .
|
||||
git clean -fd
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
|
||||
Report exactly which files you discarded, then continue with the task. A failed predecessor must not be able to jam the pipeline for every later run.
|
||||
|
||||
If the marker file is absent, this is a working copy a person uses. Stop immediately and report that the worktree has uncommitted changes. Do not stash, reset, discard, commit, or switch branches.
|
||||
|
||||
Then run:
|
||||
|
||||
`bun run deslop -- next-batch --min-issues 60 --max-issues 120`
|
||||
|
||||
Use the command output as the source of truth for this task scope.
|
||||
|
||||
If the output contains `NO BATCH AVAILABLE`, stop immediately and report the printed reason. Do not create a branch, do not create a pull request, and do not look for other work. Concurrency is already handled: the command excludes files claimed by other active batches and refuses to exceed the active-batch limit.
|
||||
|
||||
Background: anti-slop is a vendored Oxlint plugin at `tools/oxlint/anti-slop/`, configured in `oxlint.config.ts`. It rejects low-evidence typing: unjustified type assertions, `unknown`/`object`/`Record<string, unknown>` contracts, ad hoc `typeof` narrowing, conditional `{}` spreads, and module mocking. Fixing a finding means giving the code real type evidence, never hiding the symptom.
|
||||
|
||||
Workflow:
|
||||
- Before generating the batch, switch to `main` and pull the latest remote changes.
|
||||
- Read the `next-batch` output carefully.
|
||||
- Use the exact `Run ID`, `Batch name`, `Branch name`, and `PR title` printed by the command.
|
||||
- Create the branch using the printed `Branch name`.
|
||||
- Work only on the selected files listed in the batch output.
|
||||
- Treat the selected files as complete-file scope. Do not cherry-pick only the first N findings.
|
||||
- Read each selected file fully before editing it. These findings sit on type contracts, so a local edit can change behavior at a distant call site.
|
||||
- Fix as many findings as practical in the selected files. Your default should be to fix selected findings, not to skip them.
|
||||
|
||||
## What a good fix looks like
|
||||
|
||||
Every finding is the same underlying complaint: the code claims less about a value than it actually knows. A good fix restores the missing knowledge. A bad fix hides the complaint while the knowledge stays missing. The rule cannot tell the difference, so you must.
|
||||
|
||||
Before editing, answer one question for the value in question: where does it actually come from? There are only three answers, and each has one correct fix.
|
||||
|
||||
1. It comes from code in this repository. The real type already exists somewhere upstream. Find it and use it. No parsing, no assertion.
|
||||
2. It crosses an I/O boundary: HTTP response, `postMessage`, file contents, `localStorage`, a child process, the OpenCode SDK edge. Parse it once at that boundary, then let the parsed type flow onward untouched.
|
||||
|
||||
On parsing style, follow local precedent and do not introduce a new one. `zod` is declared as a dependency but is not currently used in the source, so a maintenance PR is the wrong place to start spreading it. Unless the file or package you are editing already parses with a schema library, write a small local parse function that takes the raw input, returns the domain type or `undefined`, and lives next to the boundary it guards. If you believe a schema library is genuinely warranted, skip the finding and say so in the PR body instead of introducing the pattern yourself.
|
||||
3. It is genuinely dynamic, such as a plugin registry keyed by arbitrary strings. Then keep the open key but make the value type precise, and say so in the contract's name.
|
||||
|
||||
### `no-unsafe-dictionary-type`
|
||||
|
||||
Bad, and the most common lazy fix. The shape is known; the annotation throws it away.
|
||||
|
||||
```ts
|
||||
type QuotaSnapshot = Record<string, unknown>;
|
||||
|
||||
function readLimit(snapshot: QuotaSnapshot) {
|
||||
return snapshot.limit;
|
||||
}
|
||||
```
|
||||
|
||||
Good. Name the contract and state the fields the code actually reads.
|
||||
|
||||
```ts
|
||||
type QuotaSnapshot = {
|
||||
limit: number;
|
||||
used: number;
|
||||
resetsAt: string;
|
||||
};
|
||||
|
||||
function readLimit(snapshot: QuotaSnapshot) {
|
||||
return snapshot.limit;
|
||||
}
|
||||
```
|
||||
|
||||
Also good, when keys really are open but values are not.
|
||||
|
||||
```ts
|
||||
type ProviderQuotas = Record<string, QuotaSnapshot>;
|
||||
```
|
||||
|
||||
Still bad, and does not count as a fix:
|
||||
|
||||
```ts
|
||||
type QuotaSnapshot = Record<string, any>;
|
||||
type QuotaSnapshot = { [key: string]: object };
|
||||
type QuotaSnapshot = Record<string, string | number | boolean | null>;
|
||||
```
|
||||
|
||||
The third one is the sneaky one. Widening to a union of primitives satisfies the rule without describing anything. If you cannot name the fields, that is a signal the value is unparsed I/O; go to the boundary and parse it.
|
||||
|
||||
### `no-unknown-parameters`, `no-unknown-returns`, `no-unknown-type-aliases`
|
||||
|
||||
Bad. The function accepts anything and immediately guesses.
|
||||
|
||||
```ts
|
||||
function applyThemeMessage(message: unknown) {
|
||||
const theme = message as { themeId: string };
|
||||
setTheme(theme.themeId);
|
||||
}
|
||||
```
|
||||
|
||||
Good. Parse at the boundary; the domain function receives a real type.
|
||||
|
||||
```ts
|
||||
type ThemeMessage = { themeId: string };
|
||||
|
||||
function parseThemeMessage(data: MessageEvent["data"]): ThemeMessage | undefined {
|
||||
if (data === null || typeof data !== "object") return undefined;
|
||||
const themeId = Reflect.get(data, "themeId");
|
||||
return typeof themeId === "string" ? { themeId } : undefined;
|
||||
}
|
||||
|
||||
function applyThemeMessage(message: ThemeMessage) {
|
||||
setTheme(message.themeId);
|
||||
}
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
const message = parseThemeMessage(event.data);
|
||||
if (message === undefined) return;
|
||||
applyThemeMessage(message);
|
||||
});
|
||||
```
|
||||
|
||||
The parse function itself will still report `no-runtime-typeof` and `no-reflect-get`, because it is doing exactly what those rules describe. That is expected and acceptable: the checks are now concentrated in one named boundary function instead of scattered through domain logic, and the domain function above is genuinely typed. Report these remaining findings in the PR body rather than hiding them. Do not silence them with inline suppressions.
|
||||
|
||||
Note what changed at runtime: a malformed message is now ignored instead of silently producing `undefined` deeper in the call stack. That is a deliberate behavior decision and it belongs in the PR body. Never introduce a throw on a path that previously degraded quietly.
|
||||
|
||||
The `cause` convention is the single allowed exception: `unknown` is correct for an error cause.
|
||||
|
||||
### `no-known-value-widening`
|
||||
|
||||
Bad. The annotation erases the known keys, so callers lose autocomplete and typo safety.
|
||||
|
||||
```ts
|
||||
const settingsBySlug: Record<string, SettingsSection> = {
|
||||
appearance: appearanceSection,
|
||||
keybindings: keybindingsSection,
|
||||
};
|
||||
```
|
||||
|
||||
Good. Keep inference and validate the shape.
|
||||
|
||||
```ts
|
||||
const settingsBySlug = {
|
||||
appearance: appearanceSection,
|
||||
keybindings: keybindingsSection,
|
||||
} satisfies Record<string, SettingsSection>;
|
||||
```
|
||||
|
||||
`satisfies` checks every value against the contract while preserving the literal keys. Reach for it before anything else here.
|
||||
|
||||
### `no-chained-type-assertions` and `no-widen-then-assert`
|
||||
|
||||
Bad. The precise type existed and was thrown away, then guessed back.
|
||||
|
||||
```ts
|
||||
const raw = loadSession() as unknown as SessionSnapshot;
|
||||
```
|
||||
|
||||
Good. Fix the upstream contract so the round trip is unnecessary.
|
||||
|
||||
```ts
|
||||
const snapshot = loadSession();
|
||||
```
|
||||
|
||||
If `loadSession` genuinely returns something imprecise, that function is the real defect. Fix it there when it is inside the batch scope; if it is outside, make the minimal supporting change and say so in the PR body.
|
||||
|
||||
### `require-safety-comment-for-type-assertion`
|
||||
|
||||
The first move is always to delete the assertion, not to document it. Only a small minority of these findings deserve a comment.
|
||||
|
||||
Bad, and an automatic rejection at review:
|
||||
|
||||
```ts
|
||||
// SAFETY: this is safe.
|
||||
const session = value as Session;
|
||||
|
||||
// SAFETY: value is a Session.
|
||||
const session = value as Session;
|
||||
|
||||
// SAFETY: required by TypeScript.
|
||||
const session = value as Session;
|
||||
```
|
||||
|
||||
These say nothing. A valid comment names the check that already ran and the line or function that ran it, so a reviewer can verify the claim without trusting you.
|
||||
|
||||
Good:
|
||||
|
||||
```ts
|
||||
const parsed = sessionSchema.safeParse(payload);
|
||||
if (!parsed.success) return undefined;
|
||||
// SAFETY: sessionSchema.safeParse above confirmed every field of Session.
|
||||
const session = parsed.data as Session;
|
||||
```
|
||||
|
||||
If you cannot write such a sentence truthfully, you do not have an assertion problem, you have a missing check. Add the check.
|
||||
|
||||
### `no-conditional-empty-object-spread`
|
||||
|
||||
This one changes behavior more often than it looks, so read the consumer before editing.
|
||||
|
||||
Bad:
|
||||
|
||||
```ts
|
||||
const body = {
|
||||
sessionId,
|
||||
...(title !== undefined ? { title } : {}),
|
||||
};
|
||||
```
|
||||
|
||||
Good, when the consumer distinguishes a missing key from an explicit `undefined`, which is true for anything serialized to JSON or merged over defaults:
|
||||
|
||||
```ts
|
||||
const body: CreateSessionBody = { sessionId };
|
||||
if (title !== undefined) body.title = title;
|
||||
```
|
||||
|
||||
Good, when the consumer treats both the same:
|
||||
|
||||
```ts
|
||||
const body = { sessionId, title };
|
||||
```
|
||||
|
||||
Choosing wrongly here sends `"title": null` or drops a field on a real API call. If you cannot determine which behavior the consumer needs by reading it, skip the finding and say why.
|
||||
|
||||
### `no-runtime-typeof`
|
||||
|
||||
Bad. An ad hoc check in the middle of domain logic.
|
||||
|
||||
```ts
|
||||
function resolveHost(stored: unknown) {
|
||||
if (typeof stored === "string") return stored;
|
||||
return DEFAULT_HOST;
|
||||
}
|
||||
```
|
||||
|
||||
Good. Read and validate where the value enters the program, then branch on real domain values.
|
||||
|
||||
```ts
|
||||
function readStoredHost(): string {
|
||||
const stored = localStorage.getItem(STORED_HOST_KEY);
|
||||
return stored !== null && stored.length > 0 ? stored : DEFAULT_HOST;
|
||||
}
|
||||
```
|
||||
|
||||
Here the fix removed the check entirely, because `localStorage.getItem` already has a precise contract: `string | null`. The original `unknown` was self-inflicted. Look for this case first; it is more common than it seems.
|
||||
|
||||
When a real check is unavoidable, keep it inside one named boundary function as shown above, and accept that the boundary function keeps its finding. What is not acceptable is spreading the same check across domain code, or renaming it into a type predicate so it reads as intentional while nothing was actually established.
|
||||
|
||||
### `no-module-mocking`
|
||||
|
||||
Bad. The test mocks a module and therefore tests the mock.
|
||||
|
||||
```ts
|
||||
mock.module("../lib/runtimeFetch", () => ({ runtimeFetch: async () => ({ ok: true }) }));
|
||||
```
|
||||
|
||||
Good. Pass the dependency in, and let the test supply a real function.
|
||||
|
||||
```ts
|
||||
async function loadStatus(fetchStatus: () => Promise<StatusResponse>) {
|
||||
return fetchStatus();
|
||||
}
|
||||
|
||||
test("returns the fetched status", async () => {
|
||||
const status = await loadStatus(async () => ({ ok: true }));
|
||||
expect(status.ok).toBe(true);
|
||||
});
|
||||
```
|
||||
|
||||
If introducing the seam would restructure production code well beyond the batch, skip the finding and say so. Do not fake a seam you do not believe in.
|
||||
|
||||
## How to know your fix is real
|
||||
|
||||
Before moving to the next finding, check all four:
|
||||
|
||||
- The code now knows something it did not know before. If you only rearranged syntax, it is not a fix.
|
||||
- No new `any`, no new assertion, no new broad union invented to satisfy the checker.
|
||||
- If you added parsing, you decided explicitly what happens on invalid input, and that decision is written in the PR body.
|
||||
- If you changed a type used elsewhere, you searched for its call sites and updated them, rather than casting at the call site.
|
||||
|
||||
Handle findings deliberately instead of skipping them: for parsing work, add the smallest schema that covers the fields actually used; for contract changes, follow call sites with search and update them; for tests, prefer real seams over widened fixtures.
|
||||
|
||||
## Finish the file
|
||||
|
||||
A selected file is finished when it has zero anti-slop findings for the enabled rules, or when every remaining finding has an individual, specific reason to stay.
|
||||
|
||||
This matters beyond tidiness. A file left half-fixed will be selected again by a later batch, producing a second pull request over the same file, with its own template, its own review, and its own merge. Every finding you defer costs the repository owner a future review cycle. Treat "I fixed the easy half" as an incomplete task, not a delivery.
|
||||
|
||||
So, before you consider a selected file done:
|
||||
|
||||
- Re-run `bun run deslop -- file <path>` and read what is left.
|
||||
- If findings remain, they must be the genuinely hard ones, and you must be able to explain each one specifically. "Requires a broader refactor" is only acceptable when you name the refactor, the module boundary it crosses, and why doing it here would make the change unreviewable.
|
||||
- A group of findings sharing one root cause counts as one reason, and that root cause is usually worth fixing. If eleven findings in a file all come from one untyped parser, fixing that parser is the point of the batch, not a reason to skip.
|
||||
- Leaving more than roughly a quarter of a file's findings behind means you have not finished. Either finish them or explain, per group, why the file was a bad selection in the first place.
|
||||
|
||||
Skip a finding when the fix would require unclear behavior changes, when the change would be so large that the pull request stops being reviewable, or when the only way you can see to close it is one of the forbidden patterns. That last case is not a loophole, it is the required outcome: an honest skip is always better than a laundered fix, and choosing the forbidden pattern to satisfy "finish the file" is the worse failure of the two. Ordinary difficulty, on its own, is still not a reason. If skipped, give the specific reason in the PR body under `## Non-goals`.
|
||||
|
||||
### When the whole file is an external-data boundary
|
||||
|
||||
Some files exist to receive data from outside the program: provider APIs, quota endpoints, extension host messages, configuration on disk. In such a file, most or all findings can share one root cause, and the honest fix is a real parsed boundary with named contracts, which is a substantial piece of work rather than a lint cleanup.
|
||||
|
||||
Recognize this early, before editing. Read the file first and ask whether closing its findings means designing a data contract that does not exist yet. If it does, choose one of two outcomes, and never a third:
|
||||
|
||||
- Do the work properly for a coherent part of the file: define the contract for one provider, one endpoint, or one message, parse it at its boundary, and leave the rest with a clear explanation of the remaining root cause. A correct partial fix with a named boundary is a good pull request.
|
||||
- Conclude that the file is a poor batch selection, abort per "Aborting cleanly", and say in your report that the file needs a deliberate data-contract change rather than an unattended cleanup.
|
||||
|
||||
What you must not do is invent a generic JSON contract to make the findings disappear. Generic record types, primitive unions, and `unknown`-based aliases over external data are exactly the patterns these rules exist to reject, and reintroducing them under time pressure defeats the purpose of the whole task.
|
||||
|
||||
Hard prohibitions. Each of these makes the lint output greener while making the code worse, and each is grounds for rejecting the whole PR:
|
||||
- Do not disable, downgrade, or ignore anti-slop rules, in configuration or with inline comments.
|
||||
- Do not add `any`, widen a type, or add an assertion in order to satisfy a rule.
|
||||
- Do not write a generic or placeholder `// SAFETY:` comment. A comment that does not name a real, already-performed check is worse than the original finding.
|
||||
- Do not invent a union of primitives to escape a dictionary rule.
|
||||
- Do not move a rejected `typeof` check into a hand-written type predicate to get it out of the linter's way.
|
||||
- Do not delete code, tests, or fields to make a finding disappear.
|
||||
- Do not rename a symbol solely to dodge `no-shape-in-symbol-names`; rename it to what it actually is.
|
||||
- Do not introduce a throw where the previous code degraded quietly. A parse failure on a path that used to fall back must keep falling back.
|
||||
- Do not introduce a schema library, a new utility module, or a new architectural pattern as part of a lint cleanup.
|
||||
- Do not edit `oxlint.config.ts` or `tools/oxlint/anti-slop/`.
|
||||
- Do not edit `CHANGELOG.md`, package versions, or release metadata. This is internal maintenance with no user-facing change.
|
||||
- Do not fix findings outside the selected files.
|
||||
|
||||
## Aborting cleanly
|
||||
|
||||
You may reach a point where the batch cannot be completed correctly: validation keeps failing, or the only remaining way to close the findings is a pattern this task forbids. Stopping there is the right decision. Stopping there and walking away from a modified working copy is not.
|
||||
|
||||
Whatever edits exist in the working copy at that moment are your own, made minutes ago in this session. They are not human work in progress, and nothing is lost by removing them. Leaving them behind jams every scheduled run that follows, because those runs correctly refuse to operate on a dirty worktree.
|
||||
|
||||
So when you abort, in this order:
|
||||
|
||||
1. Revert every file you modified: `git checkout -- <paths>`, plus `git clean -fd` for files you created. Verify with `git status --porcelain` that the result is empty.
|
||||
2. Release the claim so the files return to the pool: ``bun run deslop -- release --run <run-id>``.
|
||||
3. Return to `main`.
|
||||
4. Report what you attempted, precisely why you stopped, and confirm that both the worktree is clean and the claim is released.
|
||||
|
||||
Never leave a partially fixed working copy as a message to the next run. If a file resists a correct fix, that belongs in your report, not on disk.
|
||||
|
||||
After edits, run:
|
||||
|
||||
`bun run deslop -- check-batch --run <run-id>`
|
||||
|
||||
Then validate the packages you actually touched, not the whole workspace. For each affected package run its own checks, for example:
|
||||
|
||||
`bun run --cwd packages/ui type-check`
|
||||
|
||||
`bun run --cwd packages/ui lint`
|
||||
|
||||
`bun run --cwd packages/ui test`
|
||||
|
||||
Workspace-wide `bun run type-check` and `bun run lint` are CI's job. Run them locally only when a change crosses package boundaries or touches shared contracts.
|
||||
|
||||
For files that TypeScript does not cover, such as server or CLI JavaScript, run the focused tests for that surface instead, for example `bun run --cwd packages/web test`.
|
||||
|
||||
Validation and delivery:
|
||||
- Confirm selected files have fewer findings than before.
|
||||
- Confirm `Findings outside selected files delta` is not positive. If it is, you introduced new findings elsewhere; fix them before continuing.
|
||||
- If validation fails, fix failures only if the fixes stay within the task scope. Otherwise stop and report the blocker.
|
||||
- Commit the changes with a concise message.
|
||||
- Push the branch.
|
||||
- Create exactly one PR with `gh pr create` using the exact printed `PR title`.
|
||||
- After the PR is created, switch back to `main` and pull the latest remote changes again.
|
||||
|
||||
PR requirements. The repository has a mandatory pull request template at `.github/PULL_REQUEST_TEMPLATE.md`, and `AGENTS.md` requires it to be completed with concrete evidence for the final PR HEAD. Read the template and `CONTRIBUTING.md` before writing the description. Use every template heading, in the template's order, and do not invent replacement headings. Fill each section as follows.
|
||||
|
||||
- Use the exact printed `PR title`.
|
||||
- `## Intent`: state that this is an unattended maintenance batch, name the `Run ID`, `Batch name`, and `Branch name`, and say what behavior changes. When nothing observable changes, say so explicitly rather than leaving it implied.
|
||||
- `## Non-goals`: the findings left unfixed in the selected files, findings elsewhere in the repository, and any refactor you deliberately did not start. Give the reason for each, not just the count.
|
||||
- `## Affected surfaces`: the packages, runtimes, user-visible states, and persisted or external contracts the diff reaches. Name every runtime the changed code runs in, and explain why an apparently applicable runtime is unaffected.
|
||||
- `## Repository guidance`: fill the table. List the `AGENTS.md` rules you followed, every project skill that matched the change, required skill references you read, and the nearest `README.md` or `DOCUMENTATION.md` for the touched modules. For each row explain why it applies and how the change complies. Do not list filenames without explanation.
|
||||
- `## Validation`: fill the table with the exact commands you ran and their results, including `check-batch` and every package-scoped type-check, lint, and test command, naming the packages. Record failures honestly, including pre-existing failures unrelated to this PR, and say which checks you did not run. Do not claim runtime behavior from type-check or lint alone.
|
||||
- `## Visual evidence`: these PRs usually have no visible change, so explain concretely why the diff cannot affect rendered behavior. If anything user-visible did change, attach before/after evidence for the affected states.
|
||||
- `## Risks and failure behavior`: cover what breaks if a change is wrong, how to roll it back, and any compatibility, data, performance, or cross-runtime concern. This is where every behavior-affecting decision belongs: each parsing decision you introduced and what now happens on invalid input, each `// SAFETY:` comment you added with the invariant it documents, and any change to whether an object key is present. State "None identified" only with a concrete reason.
|
||||
|
||||
Add a `## Manual testing recommendations` section after the template sections, with focused checks for the changed behavior, based on the selected files and actual edits. Type-contract changes can alter runtime behavior at call sites, so name the affected surfaces concretely.
|
||||
|
||||
Also state, inside `## Intent`, the selected files and how many findings `check-batch` reports as fixed and remaining.
|
||||
|
||||
Constraints:
|
||||
- Keep the PR small and reviewable.
|
||||
- Do not auto-merge.
|
||||
- Do not modify unrelated files except minimal supporting changes required by selected-file fixes.
|
||||
- Do not run broad formatting.
|
||||
- Leave the batch's run directory intact after creating the PR. `next-batch` prints its location. That directory is both the handoff for the review follow-up task and the claim that stops another batch, including the React Doctor pipeline, from touching the same files. Deleting it early lets a parallel batch collide with this PR. Never delete it by hand; use `bun run deslop -- release --run <run-id>`.
|
||||
- If you stop before creating a PR for any reason, release the claim with `bun run deslop -- release --run <run-id>` so the files return to the pool.
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
description: Follow up on an anti-slop PR by addressing review feedback
|
||||
agent: build
|
||||
---
|
||||
|
||||
You are working in the OpenChamber repository.
|
||||
|
||||
Goal: follow up on an existing anti-slop maintenance PR, address Greptile/review bot feedback, and clean up the local batch handoff files when done.
|
||||
|
||||
This task can run unattended on a schedule, so it must be safe to start at any moment and must stop cleanly when there is nothing to do.
|
||||
|
||||
First, verify the worktree is safe to use:
|
||||
|
||||
`git status --porcelain`
|
||||
|
||||
If the output is not empty, decide which of two situations you are in.
|
||||
|
||||
If the repository root contains a `.maintenance-clone` marker file, this working copy is a disposable clone dedicated to unattended maintenance. Nothing in it is human work in progress, so leftover changes are debris from an earlier task that failed to clean up after itself. Recover the clone rather than stopping:
|
||||
|
||||
```
|
||||
git checkout -- .
|
||||
git clean -fd
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
|
||||
Report exactly which files you discarded, then continue with the task. A failed predecessor must not be able to jam the pipeline for every later run.
|
||||
|
||||
If the marker file is absent, this is a working copy a person uses. Stop immediately and report that the worktree has uncommitted changes. Do not stash, reset, discard, commit, or switch branches.
|
||||
|
||||
List the active batches:
|
||||
|
||||
`bun run deslop -- active`
|
||||
|
||||
The listing may include batches owned by the React Doctor pipeline; those are shown as `[pipeline rd]`. Never touch them.
|
||||
|
||||
Workflow:
|
||||
- If there are no active batches, stop and report that there is nothing to follow up.
|
||||
- Each active batch corresponds to one open PR. Read its `batch.json` for `runId`, `branchName`, `batchName`, `prTitle`, and selected files.
|
||||
- Use `gh` to find the open PR for each batch branch.
|
||||
- Work on the oldest batch that has an open PR with unaddressed feedback. If several qualify, handle exactly one and leave the rest.
|
||||
- If a batch's PR was already merged or closed, do not treat it as follow-up work. Release its claim with `bun run deslop -- release --run <run-id>` so its files return to the pool, then continue looking.
|
||||
- If no batch has an open PR with actionable feedback, stop and report that.
|
||||
- Switch to the batch branch using the exact `branchName`.
|
||||
- Pull or update the branch from remote if needed.
|
||||
- Use `gh` to inspect PR review comments, PR issue comments, review threads if available, and check run summaries if relevant.
|
||||
- Focus specifically on Greptile/review bot feedback and actionable reviewer comments.
|
||||
- Pay particular attention to comments questioning whether a type contract is now wrong, whether a `// SAFETY:` comment is accurate, or whether a call site was missed. These are the likely real defects in this kind of PR.
|
||||
- Address actionable comments with minimal follow-up fixes.
|
||||
- Keep changes within the original selected files whenever possible.
|
||||
- If a review comment requires changes outside the selected files, make only the minimal required supporting change.
|
||||
- Do not perform unrelated cleanup.
|
||||
- Do not rewrite the original PR.
|
||||
- Do not force-push.
|
||||
- Do not disable, downgrade, or ignore anti-slop rules, and do not add `any`, widen a type, or add an assertion to satisfy a reviewer comment.
|
||||
- Follow the same fix standards as the original batch task, described in `.opencode/commands/as-fixes.md` under "What a good fix looks like" and "Hard prohibitions". Read that section before editing. Review pressure is exactly when a laundered fix is most tempting.
|
||||
|
||||
After fixes, run:
|
||||
|
||||
`bun run deslop -- check-batch --run <run-id>`
|
||||
|
||||
Then re-run the package-scoped checks for the packages you touched, for example `bun run --cwd packages/ui type-check`, `bun run --cwd packages/ui lint`, and `bun run --cwd packages/ui test`. Workspace-wide checks are CI's job.
|
||||
|
||||
Delivery:
|
||||
- Commit follow-up fixes with a concise message.
|
||||
- Push the branch.
|
||||
- Reply to addressed review comments using `gh`.
|
||||
- For each specific review comment you addressed, reply with what was changed and the follow-up commit hash.
|
||||
- If the feedback was a general PR comment, add one general PR comment summarizing what was addressed, commit hashes, and validation results.
|
||||
- Update the PR description so it stays true for the final HEAD: refresh `## Validation` with the checks you re-ran, and move any new behavior change into `## Risks and failure behavior`. Keep every heading of `.github/PULL_REQUEST_TEMPLATE.md` intact, and preserve content the repository owner added by hand, including screenshots. Read the live description before editing and merge into it rather than overwriting.
|
||||
- If a comment is intentionally not addressed, reply with a concise reason.
|
||||
- Do not release the batch while its PR is still open and awaiting review. The claim is what keeps parallel batches off these files.
|
||||
- Release the batch only once its PR has been merged or closed: `bun run deslop -- release --run <run-id>`.
|
||||
- After the follow-up is complete, switch back to `main` and pull the latest remote changes.
|
||||
|
||||
Constraints:
|
||||
- Work on exactly one anti-slop batch PR.
|
||||
- Prefer the oldest batch with an open PR.
|
||||
- Do not auto-merge.
|
||||
- Do not close the PR.
|
||||
- Do not edit `CHANGELOG.md`, package versions, or release metadata.
|
||||
- Do not release or delete handoff directories for batches you did not handle.
|
||||
- If validation fails and cannot be fixed safely within scope, leave the batch claimed and report the blocker.
|
||||
@@ -1,58 +0,0 @@
|
||||
---
|
||||
description: Draft user-facing CHANGELOG.md entries for [Unreleased]
|
||||
agent: build
|
||||
---
|
||||
|
||||
You are updating @CHANGELOG.md and @packages/vscode/CHANGELOG.md.
|
||||
|
||||
Goal: write user-facing bullet points for the `## [Unreleased]` section that summarize the changes since the latest git tag up to `HEAD`.
|
||||
|
||||
Style rules:
|
||||
- Match the writing style of the existing changelog (tone + level of detail).
|
||||
- Write like release notes for actual users, not a marketing summary. Be concrete and plain-spoken.
|
||||
- Avoid generic payoff clauses like "making X faster", "improving reliability", "for a smoother workflow", or "so you can..." unless the diff clearly proves that exact user-visible outcome.
|
||||
- Prefer short direct bullets: what changed, where users see it, and only one consequence if it is obvious.
|
||||
- Avoid internal implementation details, but do not replace them with vague benefits. If a technical change has no clear user-visible effect, omit it or group it under a plain reliability bullet.
|
||||
- Avoid internal component names unless users see them (ex: "VS Code extension", "Desktop app", "Web app").
|
||||
- For @packages/vscode/CHANGELOG.md: Craft entries specifically for behavior that is present in the VS Code extension. Exclude Desktop app, Web app, Mobile/PWA, and main-app-only UI. Do not copy shared/main changelog bullets into this file unless changed files or code paths show the feature exists in the extension. Focus on core UI improvements and VS Code integration. Do NOT use "VSCode:" or "VS Code:" prefixes in this file.
|
||||
- Prefer grouping by platform only if it reads better.
|
||||
- No new release header; only update the `[Unreleased]` bullets.
|
||||
- Don't include implementation notes, commit hashes, or file paths in the changelog text.
|
||||
- Use area prefixes when helpful for grouping in the main @CHANGELOG.md (e.g., "Chat:", "VSCode:", "Settings:", "Git:", "Terminal:", "Mobile:", "UI:").
|
||||
- Credit contributors inline using "(thanks to @username)" at the end of the bullet. Find contributor usernames from commit authors (not email, but a github username) or PR metadata when available. Skip if contributor is btriapitsyn, since this is a repo owner.
|
||||
|
||||
Highlights and ordering:
|
||||
- Review several recent release sections before drafting. Match how they reserve bold area prefixes for release highlights and order the remaining bullets by user importance.
|
||||
- Sort bullets by user impact, not commit order. Put breaking changes first, then the most significant new capabilities or broad user-visible improvements, followed by smaller features, fixes, and visual polish.
|
||||
- Mark only the strongest release highlights with a bold area prefix, such as `- **Chat attachments:** ...`. Usually this is the first 1-3 bullets, but use fewer when the release does not contain enough substantial changes and more only when clearly justified.
|
||||
- Treat a change as a highlight when it introduces a substantial user-facing capability, materially changes a common workflow, or fixes a severe/widespread user-facing problem. Do not bold a bullet merely because it is first, has a large diff, or was difficult to implement.
|
||||
- Keep related platform bullets together only when that does not push a more important change too far down the list.
|
||||
- Rank highlights independently in the main and VS Code changelogs. A main-app highlight is not automatically a VS Code highlight, and the extension may have different top changes.
|
||||
|
||||
Quality checks before editing:
|
||||
- For every bullet, ask: "Could a user point to this in the UI or behavior?" If not, rewrite it or drop it.
|
||||
- For every VS Code bullet, verify the change applies to the extension, not just shared web UI or server code. When unsure, leave it out of @packages/vscode/CHANGELOG.md.
|
||||
- For every bold bullet, ask: "Would a user reasonably describe this as one of the release's headline changes?" If not, remove the bold styling or move it lower.
|
||||
- Read the finished list top to bottom and confirm that each bullet is no more important than the bullets above it, except where keeping closely related platform bullets together improves readability.
|
||||
- Do not mention low-level mechanics such as "local refs first", "source of truth", "route", "store", "cache", "payload", or "ref resolution". Translate only when there is a clear user-facing symptom.
|
||||
- Do not bundle unrelated changes just to reduce bullet count. It is better to omit minor internal fixes than to create a vague catch-all sentence.
|
||||
- Avoid LinkedIn-style language. Bad: "commit review is faster and branch history is more reliable." Better: "commit history can now show file diffs inline." Bad: "installed-state accuracy is improved." Better: "the skills list now matches OpenCode's installed skills more closely."
|
||||
|
||||
Determine the base version:
|
||||
- Use the latest tag (ex: `v1.3.2`) as the base.
|
||||
- Inspect all commits after the base up to `HEAD`.
|
||||
|
||||
Repo context for style:
|
||||
!`head -140 CHANGELOG.md`
|
||||
|
||||
Git context (base tag, commits, changed files):
|
||||
!`BASE=$(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD); echo "Base: $BASE"; echo "Commits since base: $(git rev-list --count "$BASE"..HEAD)"; echo "Diff stats: $(git diff --shortstat "$BASE"..HEAD)"; echo; echo "=== Top 30 commits ==="; git log --oneline -30 "$BASE"..HEAD; echo; echo "=== Changed files ==="; git diff --stat "$BASE"..HEAD`
|
||||
|
||||
Additional hints (optional, use only if needed):
|
||||
- If there are breaking changes or user-visible behavior changes, call them out first.
|
||||
- If changes are mostly internal refactors, mention them only when there is a concrete user-visible fix. Otherwise do not add a changelog bullet for them.
|
||||
|
||||
Now:
|
||||
1) Propose the new `[Unreleased]` bullet list for the main @CHANGELOG.md.
|
||||
2) Propose the VS Code-specific `[Unreleased]` list for @packages/vscode/CHANGELOG.md.
|
||||
3) Edit both files to update their respective `[Unreleased]` sections.
|
||||
@@ -0,0 +1,135 @@
|
||||
---
|
||||
description: Deeply review every open maintenance PR and fix it to completion, not by commenting
|
||||
agent: build
|
||||
---
|
||||
|
||||
You are working in the OpenChamber repository.
|
||||
|
||||
Goal: take every open automated maintenance pull request and bring it to a state where a human reviewer would merge it without a single objection. You are the intelligence layer between unattended batch tasks and the repository owner. The batch tasks optimize for a metric; you optimize for the code being right.
|
||||
|
||||
You do not leave review comments. You do the work. A finding you notice and do not fix is a failure of this task.
|
||||
|
||||
## Scope of the run
|
||||
|
||||
In scope: every open pull request whose head branch starts with `anti-slop/` or `react-doctor/`.
|
||||
|
||||
Find them:
|
||||
|
||||
`gh pr list --state open --search "head:anti-slop/" --json number,title,headRefName,url`
|
||||
|
||||
`gh pr list --state open --search "head:react-doctor/" --json number,title,headRefName,url`
|
||||
|
||||
Work through them one at a time, oldest first. Finish a PR completely before starting the next. Do not interleave.
|
||||
|
||||
This task ends only when every PR in the list has been reviewed, fixed, validated, pushed, and its description updated. Do not stop at the first one. Do not stop because a PR looks acceptable at a glance; that judgement comes after reading the diff, not before.
|
||||
|
||||
## Before you start
|
||||
|
||||
Verify the worktree is clean:
|
||||
|
||||
`git status --porcelain`
|
||||
|
||||
If the output is not empty and the repository root contains a `.maintenance-clone` marker file, this is a disposable maintenance clone and the changes are debris from an earlier failed task. Recover it with `git checkout -- .`, `git clean -fd`, `git checkout main`, `git pull`, report exactly which files you discarded, and continue.
|
||||
|
||||
If the marker file is absent, stop immediately and report it. Do not stash, reset, or discard anything.
|
||||
|
||||
Read `AGENTS.md`, and read `.opencode/commands/as-fixes.md` in full, including the sections "What a good fix looks like" and "Hard prohibitions". Those describe the standard the anti-slop PRs were supposed to meet. Your job includes verifying they actually met it.
|
||||
|
||||
Load every project skill matching the code you end up touching, exactly as `AGENTS.md` requires. These PRs reach into sync, stores, UI, runtime, and CLI code, and the applicable skill is determined by what you change, not by the fact that this is maintenance work.
|
||||
|
||||
## Working on one PR
|
||||
|
||||
Check out the branch and bring it up to date with `main`:
|
||||
|
||||
`gh pr checkout <number>`
|
||||
|
||||
`git merge origin/main`
|
||||
|
||||
If the merge conflicts, resolve it correctly by reading both sides. Never resolve a conflict by taking one side wholesale to save time.
|
||||
|
||||
Then read the entire diff against `main`, not just the changed lines:
|
||||
|
||||
`git diff origin/main...HEAD`
|
||||
|
||||
For every file in the diff, open the file itself and read the surrounding code. These PRs change type contracts and component structure, so a line that looks correct in isolation is frequently wrong in context.
|
||||
|
||||
## What you are looking for
|
||||
|
||||
Treat the PR body's claims as unverified. Re-run the checks yourself; do not trust reported results.
|
||||
|
||||
Correctness of the change itself:
|
||||
- Did the change alter runtime behavior? Effect cleanup, hook dependencies, component extraction, conditional object spreads, and added parsing all can. Decide whether the new behavior is right, not merely whether it is different.
|
||||
- Does a removed or reordered object key change what gets serialized to an API, persisted to disk, or merged over defaults? A key that used to be absent and is now present as `undefined` is a real change.
|
||||
- Was dead code removed that is actually referenced somewhere the batch task did not search, including dynamic imports, string-keyed lookups, generated assets, and other packages?
|
||||
- Did a type contract change without every call site being updated? Search for each changed symbol across the workspace.
|
||||
- Did an extracted component lose state, memoization, ref forwarding, or a stable identity that the original had?
|
||||
|
||||
Honesty of the change:
|
||||
- Is any `// SAFETY:` comment vague, generic, or untrue? A comment must name the check that already ran. If it does not, either delete the assertion by fixing the contract, or write the truthful comment.
|
||||
- Was a type laundered rather than fixed? Look for invented primitive unions, `any`, new assertions, hand-written type predicates that merely relocate a rejected `typeof` check, or deleted fields and tests.
|
||||
- Was a lint rule disabled, downgraded, ignored, or suppressed inline anywhere in the diff? Revert that and fix the underlying code.
|
||||
- Was a new dependency, schema library, utility module, or architectural pattern introduced under the cover of cleanup? Remove it and solve the problem within existing precedent.
|
||||
|
||||
Quality of the result:
|
||||
- Does the new code read like the code around it, in naming, structure, and comment density?
|
||||
- Are the new names accurate, or do they describe the refactor instead of the domain?
|
||||
- Is the change complete, or did the batch task fix eight of eleven findings in a file and leave three arbitrary ones behind?
|
||||
|
||||
## Fixing
|
||||
|
||||
Fix everything you find, on the PR branch, as additional commits. You are explicitly permitted to go beyond the batch's original file scope when correctness requires it: update call sites, correct an upstream contract, add a missing test, or finish an incomplete refactor.
|
||||
|
||||
Two boundaries on that freedom:
|
||||
|
||||
1. Do not touch files that another open maintenance PR modifies. Check with `gh pr diff <other-number> --name-only` for the other open PRs in this run. If a correct fix genuinely requires such a file, make the change in whichever PR already owns that file, and note the cross-PR dependency in both descriptions.
|
||||
2. Do not turn a maintenance PR into a feature or a redesign. If you conclude the batch's approach was wrong at the root, revert that part of the diff rather than building on it, and explain the revert in the PR body. A smaller correct PR beats a larger clever one.
|
||||
|
||||
Do not disable, downgrade, or ignore lint rules. Do not add `any`, widen a type, or add an assertion to make a check pass. Do not edit `oxlint.config.ts`, `tools/oxlint/anti-slop/`, `CHANGELOG.md`, package versions, or release metadata.
|
||||
|
||||
If a batch left findings unfixed and the PR body called them skipped, evaluate each one yourself. Fix the ones that are fixable within a correct, reviewable change. Keep a skip only when you can articulate why fixing it would be wrong here, not merely hard.
|
||||
|
||||
## Validating each PR
|
||||
|
||||
Re-run the pipeline's own check for the batch, using the run id from the PR body when it is present:
|
||||
|
||||
`bun run deslop -- check-batch --run <run-id>` for anti-slop PRs
|
||||
|
||||
`bun run doctor -- check-batch --run <run-id>` for React Doctor PRs
|
||||
|
||||
If the run directory no longer exists, skip that command and say so; it is a convenience, not the source of truth.
|
||||
|
||||
Then, for every package the final diff touches, run its own checks:
|
||||
|
||||
`bun run --cwd packages/<name> type-check`
|
||||
|
||||
`bun run --cwd packages/<name> lint`
|
||||
|
||||
`bun run --cwd packages/<name> test`
|
||||
|
||||
Run `bunx oxlint <changed-paths>` on the files in the diff and confirm you have not increased anti-slop findings anywhere.
|
||||
|
||||
For surfaces TypeScript does not cover, such as server JavaScript, CLI JavaScript, or Electron main-process helpers, run the focused tests for that surface. Static checks do not prove those correct.
|
||||
|
||||
If a check fails for a reason unrelated to this PR, verify that claim by checking the same command on `main` before dismissing it, and report the result either way.
|
||||
|
||||
## Delivering each PR
|
||||
|
||||
- Commit your fixes with concise messages describing what was actually wrong.
|
||||
- Push to the PR branch. Never force-push.
|
||||
- Update the PR description so it describes the final state, using every heading of `.github/PULL_REQUEST_TEMPLATE.md` in the template's order. `## Intent` covers what the batch did and what you corrected; `## Non-goals` covers what you deliberately left alone; `## Affected surfaces` must reflect the final diff, including files you added beyond the batch scope; `## Repository guidance` must list the rules, skills, and module documentation that applied to your own edits, not only the batch's; `## Validation` must contain the exact commands you re-ran and their results; `## Risks and failure behavior` must carry every behavior change you accepted or introduced. A description that still describes only the batch's original work is incomplete.
|
||||
- Preserve any content the repository owner added to the description by hand, including screenshots. Read the live description before editing it and merge your changes into it rather than overwriting.
|
||||
- Add one PR comment summarizing your review pass, so the history shows what was examined and what was changed.
|
||||
- Do not merge, do not close, do not approve, and do not request review.
|
||||
- Do not release the batch claim. The batch stays claimed until its PR is merged or closed.
|
||||
|
||||
Then move to the next PR.
|
||||
|
||||
## Finishing the run
|
||||
|
||||
When every PR has been handled, return to `main` and pull:
|
||||
|
||||
`git checkout main && git pull`
|
||||
|
||||
Report, per PR: number, title, what was wrong, what you fixed, what you deliberately left alone and why, validation results, and your assessment of whether it is now ready to merge. State plainly if any PR is not ready and what blocks it.
|
||||
|
||||
If you found nothing wrong in a PR, say that explicitly and describe what you checked to reach that conclusion. That is a valid outcome, but only after real inspection.
|
||||
@@ -7,12 +7,35 @@ You are working in the OpenChamber repository.
|
||||
|
||||
Goal: reduce React Doctor diagnostics in a small, reviewable maintenance PR.
|
||||
|
||||
Start by running:
|
||||
This task can run unattended on a schedule, so it must be safe to start at any moment and must stop cleanly when there is nothing to do.
|
||||
|
||||
First, verify the worktree is safe to use:
|
||||
|
||||
`git status --porcelain`
|
||||
|
||||
If the output is not empty, decide which of two situations you are in.
|
||||
|
||||
If the repository root contains a `.maintenance-clone` marker file, this working copy is a disposable clone dedicated to unattended maintenance. Nothing in it is human work in progress, so leftover changes are debris from an earlier task that failed to clean up after itself. Recover the clone rather than stopping:
|
||||
|
||||
```
|
||||
git checkout -- .
|
||||
git clean -fd
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
|
||||
Report exactly which files you discarded, then continue with the task. A failed predecessor must not be able to jam the pipeline for every later run.
|
||||
|
||||
If the marker file is absent, this is a working copy a person uses. Stop immediately and report that the worktree has uncommitted changes. Do not stash, reset, discard, commit, or switch branches.
|
||||
|
||||
Then run:
|
||||
|
||||
`bun run doctor -- next-batch --min-issues 75 --max-issues 120`
|
||||
|
||||
Use the command output as the source of truth for this task scope.
|
||||
|
||||
If the output contains `NO BATCH AVAILABLE`, stop immediately and report the printed reason. Do not create a branch, do not create a pull request, and do not look for other work. Concurrency is already handled: the command excludes files claimed by other active batches and refuses to exceed the active-batch limit.
|
||||
|
||||
Workflow:
|
||||
- Before generating the batch, switch to `main` and pull the latest remote changes.
|
||||
- Read the `next-batch` output carefully.
|
||||
@@ -23,19 +46,42 @@ Workflow:
|
||||
- Fix as many diagnostics as practical in the selected files. Your default should be to fix selected diagnostics, not to skip them.
|
||||
- Prefer direct, behavior-preserving fixes: missing effect cleanup, mutable effect dependencies, accessibility issues with semantic fixes, local performance improvements, Tailwind shorthand replacements, component extraction when the boundary is clear, dead-code removal after verifying no references, and reducer or derived-state cleanup when the state relationship is local and clear.
|
||||
- Handle larger diagnostics deliberately instead of skipping them: for component splits, extract the smallest coherent subcomponent that reduces the diagnostic while preserving props/state flow; for dead code, verify references with search before deleting exports, types, or files; for state architecture issues, prefer the smallest local reducer or derived-state simplification that preserves behavior; for render-function extraction, extract only stable render helpers that do not depend on large implicit closure state, or pass explicit props; for behavior-sensitive diagnostics, read the surrounding code first and preserve existing runtime behavior.
|
||||
- Skip a diagnostic only when the fix would require broad architectural changes, unclear behavior changes, or changes outside the selected batch scope. If skipped, mention it in the PR body.
|
||||
- Finish each selected file. A file is finished when it has zero React Doctor diagnostics, or when every remaining diagnostic has an individual, specific reason to stay. A half-fixed file will be selected again later and cost a second pull request, a second review, and a second merge over the same code.
|
||||
- Before considering a file done, re-run `bun run doctor -- file <path>` and read what is left. Leaving more than roughly a quarter of a file's diagnostics behind means you have not finished.
|
||||
- A group of diagnostics sharing one root cause counts as one reason, and that root cause is usually worth fixing rather than deferring.
|
||||
- Skip a diagnostic when the fix would require unclear behavior changes, when the change would be so large that the pull request stops being reviewable, or when the only way you can see to close it is a change you would not defend in review. An honest skip is always better than a forced fix. Ordinary difficulty, on its own, is still not a reason. If skipped, give the specific reason in the PR body under `## Non-goals`.
|
||||
- If a whole selected file turns out to need a deliberate architectural change rather than a cleanup, abort per "Aborting cleanly" and report that the file was a poor batch selection.
|
||||
- Do not suppress React Doctor diagnostics unless there is a clear false positive.
|
||||
- If a listed diagnostic requires changes outside the selected files, make only the minimal required supporting change. Do not expand the cleanup scope.
|
||||
|
||||
## Aborting cleanly
|
||||
|
||||
You may reach a point where the batch cannot be completed correctly: validation keeps failing, or the only remaining way to close the findings is a pattern this task forbids. Stopping there is the right decision. Stopping there and walking away from a modified working copy is not.
|
||||
|
||||
Whatever edits exist in the working copy at that moment are your own, made minutes ago in this session. They are not human work in progress, and nothing is lost by removing them. Leaving them behind jams every scheduled run that follows, because those runs correctly refuse to operate on a dirty worktree.
|
||||
|
||||
So when you abort, in this order:
|
||||
|
||||
1. Revert every file you modified: `git checkout -- <paths>`, plus `git clean -fd` for files you created. Verify with `git status --porcelain` that the result is empty.
|
||||
2. Release the claim so the files return to the pool: ``bun run doctor -- release --run <run-id>``.
|
||||
3. Return to `main`.
|
||||
4. Report what you attempted, precisely why you stopped, and confirm that both the worktree is clean and the claim is released.
|
||||
|
||||
Never leave a partially fixed working copy as a message to the next run. If a file resists a correct fix, that belongs in your report, not on disk.
|
||||
|
||||
After edits, run:
|
||||
|
||||
`bun run doctor -- check-batch --run <run-id>`
|
||||
|
||||
Then run:
|
||||
Then validate the packages you actually touched, not the whole workspace. For each affected package run its own checks, for example:
|
||||
|
||||
`bun run type-check`
|
||||
`bun run --cwd packages/ui type-check`
|
||||
|
||||
`bun run lint`
|
||||
`bun run --cwd packages/ui lint`
|
||||
|
||||
`bun run --cwd packages/ui test`
|
||||
|
||||
Workspace-wide `bun run type-check` and `bun run lint` are CI's job. Run them locally only when a change crosses package boundaries or touches shared contracts. For files that TypeScript does not cover, such as server or CLI JavaScript, run the focused tests for that surface instead.
|
||||
|
||||
Validation and delivery:
|
||||
- Confirm selected files have fewer diagnostics than before.
|
||||
@@ -45,15 +91,20 @@ Validation and delivery:
|
||||
- Create exactly one PR with `gh pr create` using the exact printed `PR title`.
|
||||
- After the PR is created, switch back to `main` and pull the latest remote changes again.
|
||||
|
||||
PR requirements:
|
||||
PR requirements. The repository has a mandatory pull request template at `.github/PULL_REQUEST_TEMPLATE.md`, and `AGENTS.md` requires it to be completed with concrete evidence for the final PR HEAD. Read the template and `CONTRIBUTING.md` before writing the description. Use every template heading, in the template's order, and do not invent replacement headings. Fill each section as follows.
|
||||
|
||||
- Use the exact printed `PR title`.
|
||||
- Include the `Run ID`, `Batch name`, and `Branch name`.
|
||||
- Include selected files.
|
||||
- Include diagnostics fixed according to `check-batch`.
|
||||
- Include remaining diagnostics in selected files.
|
||||
- Include validation results for `bun run type-check` and `bun run lint`.
|
||||
- Include a `Manual testing recommendations` section with focused checks for the changed behavior. Base it on the selected files and actual edits, for example checking affected dropdowns, keyboard navigation, model/agent selection, settings controls, or mobile/desktop variants.
|
||||
- Include any skipped diagnostics and why.
|
||||
- `## Intent`: state that this is an unattended maintenance batch, name the `Run ID`, `Batch name`, and `Branch name`, and say what behavior changes. When nothing observable changes, say so explicitly rather than leaving it implied.
|
||||
- `## Non-goals`: the diagnostics left unfixed in the selected files, diagnostics elsewhere in the repository, and any refactor you deliberately did not start. Give the reason for each, not just the count.
|
||||
- `## Affected surfaces`: the packages, runtimes, user-visible states, and persisted or external contracts the diff reaches. Name every runtime the changed code runs in, and explain why an apparently applicable runtime is unaffected.
|
||||
- `## Repository guidance`: fill the table. List the `AGENTS.md` rules you followed, every project skill that matched the change, required skill references you read, and the nearest `README.md` or `DOCUMENTATION.md` for the touched modules. For each row explain why it applies and how the change complies. Do not list filenames without explanation.
|
||||
- `## Validation`: fill the table with the exact commands you ran and their results, including `check-batch` and every package-scoped type-check, lint, and test command, naming the packages. Record failures honestly, including pre-existing failures unrelated to this PR, and say which checks you did not run. Do not claim runtime behavior from type-check or lint alone.
|
||||
- `## Visual evidence`: these PRs usually have no visible change, so explain concretely why the diff cannot affect rendered behavior. If anything user-visible did change, attach before/after evidence for the affected states.
|
||||
- `## Risks and failure behavior`: cover what breaks if a change is wrong, how to roll it back, and any compatibility, data, performance, or cross-runtime concern. State "None identified" only with a concrete reason.
|
||||
|
||||
Add a `## Manual testing recommendations` section after the template sections, with focused checks for the changed behavior. Base it on the selected files and actual edits, for example checking affected dropdowns, keyboard navigation, model or agent selection, settings controls, and mobile or desktop variants.
|
||||
|
||||
Also state, inside `## Intent`, the selected files and how many diagnostics `check-batch` reports as fixed and remaining.
|
||||
|
||||
Constraints:
|
||||
- Keep the PR small and reviewable.
|
||||
@@ -61,4 +112,6 @@ Constraints:
|
||||
- Do not modify unrelated files except minimal supporting changes required by selected-file fixes.
|
||||
- Do not run broad formatting.
|
||||
- Do not fix diagnostics outside the selected files.
|
||||
- Leave `.tmp/react-doctor/runs/<run-id>/` intact after creating the PR. These files are the handoff for the review follow-up task.
|
||||
- Do not edit `CHANGELOG.md`, package versions, or release metadata. This is internal maintenance with no user-facing change.
|
||||
- Leave the batch's run directory intact after creating the PR. `next-batch` prints its location. That directory is both the handoff for the review follow-up task and the claim that stops another batch, including the anti-slop pipeline, from touching the same files. Deleting it early lets a parallel batch collide with this PR. Never delete it by hand; use `bun run doctor -- release --run <run-id>`.
|
||||
- If you stop before creating a PR for any reason, release the claim with `bun run doctor -- release --run <run-id>` so the files return to the pool.
|
||||
|
||||
@@ -7,16 +7,40 @@ You are working in the OpenChamber repository.
|
||||
|
||||
Goal: follow up on an existing React Doctor maintenance PR, address Greptile/review bot feedback, and clean up the local batch handoff files when done.
|
||||
|
||||
Inspect local React Doctor batch handoff files:
|
||||
This task can run unattended on a schedule, so it must be safe to start at any moment and must stop cleanly when there is nothing to do.
|
||||
|
||||
`find .tmp/react-doctor/runs -maxdepth 2 -name batch.json -print 2>/dev/null || true`
|
||||
First, verify the worktree is safe to use:
|
||||
|
||||
`git status --porcelain`
|
||||
|
||||
If the output is not empty, decide which of two situations you are in.
|
||||
|
||||
If the repository root contains a `.maintenance-clone` marker file, this working copy is a disposable clone dedicated to unattended maintenance. Nothing in it is human work in progress, so leftover changes are debris from an earlier task that failed to clean up after itself. Recover the clone rather than stopping:
|
||||
|
||||
```
|
||||
git checkout -- .
|
||||
git clean -fd
|
||||
git checkout main
|
||||
git pull
|
||||
```
|
||||
|
||||
Report exactly which files you discarded, then continue with the task. A failed predecessor must not be able to jam the pipeline for every later run.
|
||||
|
||||
If the marker file is absent, this is a working copy a person uses. Stop immediately and report that the worktree has uncommitted changes. Do not stash, reset, discard, commit, or switch branches.
|
||||
|
||||
List the active batches:
|
||||
|
||||
`bun run doctor -- active`
|
||||
|
||||
The listing may include batches owned by the anti-slop pipeline; those are shown as `[pipeline as]`. Never touch them.
|
||||
|
||||
Workflow:
|
||||
- Read the available `.tmp/react-doctor/runs/*/batch.json` files.
|
||||
- Find the most recent batch that has `branchName`, `batchName`, and `prTitle`.
|
||||
- Read its `Run ID`, `Batch name`, `Branch name`, `PR title`, and selected files.
|
||||
- Use `gh` to find the open PR for that branch or title.
|
||||
- If no open PR exists for the batch, stop and report that there is no PR to follow up.
|
||||
- If there are no active batches, stop and report that there is nothing to follow up.
|
||||
- Each active batch corresponds to one open PR. Read its `batch.json` for `runId`, `branchName`, `batchName`, `prTitle`, and selected files.
|
||||
- Use `gh` to find the open PR for each batch branch.
|
||||
- Work on the oldest batch that has an open PR with unaddressed feedback. If several qualify, handle exactly one and leave the rest.
|
||||
- If a batch's PR was already merged or closed, do not treat it as follow-up work. Release its claim with `bun run doctor -- release --run <run-id>` so its files return to the pool, then continue looking.
|
||||
- If no batch has an open PR with actionable feedback, stop and report that.
|
||||
- Switch to the batch branch using the exact `branchName`.
|
||||
- Pull or update the branch from remote if needed.
|
||||
- Use `gh` to inspect PR review comments, PR issue comments, review threads if available, and check run summaries if relevant.
|
||||
@@ -32,9 +56,7 @@ After fixes, run:
|
||||
|
||||
`bun run doctor -- check-batch --run <run-id>`
|
||||
|
||||
`bun run type-check`
|
||||
|
||||
`bun run lint`
|
||||
Then re-run the package-scoped checks for the packages you touched, for example `bun run --cwd packages/ui type-check`, `bun run --cwd packages/ui lint`, and `bun run --cwd packages/ui test`. Workspace-wide checks are CI's job.
|
||||
|
||||
Delivery:
|
||||
- Commit follow-up fixes with a concise message.
|
||||
@@ -42,15 +64,17 @@ Delivery:
|
||||
- Reply to addressed review comments using `gh`.
|
||||
- For each specific review comment you addressed, reply with what was changed and the follow-up commit hash.
|
||||
- If the feedback was a general PR comment, add one general PR comment summarizing what was addressed, commit hashes, and validation results.
|
||||
- Update the PR description so it stays true for the final HEAD: refresh `## Validation` with the checks you re-ran, and move any new behavior change into `## Risks and failure behavior`. Keep every heading of `.github/PULL_REQUEST_TEMPLATE.md` intact, and preserve content the repository owner added by hand, including screenshots. Read the live description before editing and merge into it rather than overwriting.
|
||||
- If a comment is intentionally not addressed, reply with a concise reason.
|
||||
- After successful push and replies, delete only the completed batch handoff directory: `.tmp/react-doctor/runs/<run-id>/`.
|
||||
- Do not release the batch while its PR is still open and awaiting review. The claim is what keeps parallel batches off these files.
|
||||
- Release the batch only once its PR has been merged or closed: `bun run doctor -- release --run <run-id>`.
|
||||
- After the follow-up is complete, switch back to `main` and pull the latest remote changes.
|
||||
|
||||
Constraints:
|
||||
- Work on exactly one React Doctor batch PR.
|
||||
- Prefer the most recent batch with an open PR.
|
||||
- Prefer the oldest batch with an open PR.
|
||||
- Do not auto-merge.
|
||||
- Do not close the PR.
|
||||
- Do not delete handoff files until comments are addressed, validation passes, and follow-up commits are pushed.
|
||||
- Do not delete unrelated `.tmp/react-doctor/runs/*` directories.
|
||||
- If validation fails and cannot be fixed safely within scope, do not delete the handoff directory.
|
||||
- Do not edit `CHANGELOG.md`, package versions, or release metadata.
|
||||
- Do not release or delete handoff directories for batches you did not handle.
|
||||
- If validation fails and cannot be fixed safely within scope, leave the batch claimed and report the blocker.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 77 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 89 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -79,29 +79,55 @@ task-required reference named by those skills. Skills are canonical for their
|
||||
detailed workflows and checklists. Treating this table as optional advice is a
|
||||
process violation.
|
||||
|
||||
**Always load `.agents/skills/communication-style/SKILL.md` at the start of
|
||||
every task, before any analysis, tool call, or response. Apply its guidance to
|
||||
all messages and written output, not only to user-facing copy or documentation.**
|
||||
|
||||
| Trigger | Required skill |
|
||||
|---|---|
|
||||
| Any source, dependency, export, build-config, generated-asset, package-contract, or module-ownership change | `openchamber-change-discipline` |
|
||||
| Source/dependency changes, exports or package contracts, build/generated assets, or module ownership | `openchamber-change-discipline` |
|
||||
| CLI commands, prompts, terminal output, non-TTY, `--quiet`, or `--json` behavior | `clack-cli-patterns` |
|
||||
| Shared UI data access, OpenCode SDK, `RuntimeAPIs`, runtime fetch/auth/URLs, bridges/proxies, runtime switching, or server API routes | `ui-api-decoupling` |
|
||||
| Shared UI data access, OpenCode SDK or server routes, `RuntimeAPIs`, runtime auth/URLs, bridges, or runtime switching | `ui-api-decoupling` |
|
||||
| Electron main/preload, IPC, native UI, updater, deep links, SSH/tunnels, packaging, or child processes | `desktop-shell` |
|
||||
| Session sync, bootstrap/reconnect, reducers, polling, optimistic state, queues, live status, reconciliation, or directory-scoped caches | `sync-state-invariants` |
|
||||
| Render/store/event hot paths, large lists, caching/indexing, high CPU/memory, lag, jank, freezes, or performance regressions | `performance-engineering` |
|
||||
| Render/store/event hot paths, large lists, caches/indexes, or reported lag, freezes, CPU/memory, startup, or performance regressions | `performance-engineering` |
|
||||
| WebSocket, SSE, streaming transport, runtime transport internals, or private relay | `relay-transport` |
|
||||
| UI components, styling, colors, buttons, or icons | `theme-system` |
|
||||
| User-facing or accessible UI text, labels, aria, toasts, dialogs, or navigation copy | `locale-ui-patterns` |
|
||||
| Settings UI, settings dialogs, configuration surfaces, or settings search | `settings-ui-patterns` |
|
||||
| Sortable or drag-to-reorder behavior, especially `@dnd-kit` and touch/wrapping layouts | `drag-to-reorder` |
|
||||
| iOS Simulator build, launch, preview, gestures, or `serve-sim` control | `serve-sim` |
|
||||
| Drafting or updating user-facing CHANGELOG entries for the `[Unreleased]` section (main app or VS Code extension) | `changelog-authoring` |
|
||||
| Creating or editing skills, `AGENTS.md`, or docs reached through agent instructions/context pointers | `writing-for-agents` |
|
||||
|
||||
Pure code-reading or explanation does not require implementation skills unless needed to interpret a specialized subsystem.
|
||||
|
||||
### Skill Ownership
|
||||
|
||||
Keep each cross-cutting rule with one canonical owner; companion skills add only domain-specific consequences and a pointer to that owner.
|
||||
|
||||
| Concern | Canonical skill |
|
||||
|---|---|
|
||||
| Change scope, abstraction discipline, and validation risk | `openchamber-change-discipline` |
|
||||
| State authority, reconciliation, optimistic state, and lifecycle correctness | `sync-state-invariants` |
|
||||
| Measurement, hot-path cost, caching performance, and optimization evidence | `performance-engineering` |
|
||||
| Shared UI API and runtime boundaries | `ui-api-decoupling` |
|
||||
| WebSocket/SSE and private relay mechanics | `relay-transport` |
|
||||
| Electron native ownership and privilege boundary | `desktop-shell` |
|
||||
| UI tokens, primitives, icons, and animation styling | `theme-system` |
|
||||
| Settings composition and search behavior | `settings-ui-patterns` |
|
||||
| User-facing text and localization | `locale-ui-patterns` |
|
||||
| Agent-facing document structure and context pointers | `writing-for-agents` |
|
||||
|
||||
Before adding guidance to a skill, identify its canonical owner. If another skill owns the rule, add a precise companion pointer and only the local consequence; do not copy the rule.
|
||||
|
||||
## Validation
|
||||
|
||||
- Use `package.json` scripts as the command source of truth.
|
||||
- Prefer focused tests and package-scoped type-check/lint for executable source changes.
|
||||
- Use workspace-wide checks for cross-workspace contracts, root tooling, dependencies, or shared generated assets.
|
||||
- Run `bun run dead-code` when source files are added/deleted/renamed or exports, types, entrypoints, or import shape change; inspect its report because it is non-blocking.
|
||||
- Run `bunx oxlint <changed-paths>` on TypeScript/JavaScript files you created or substantially rewrote. This runs the vendored `anti-slop` plugin, which rejects low-evidence typing: unjustified type assertions, `unknown`/`object`/`Record<string, unknown>` contracts, ad hoc `typeof` narrowing, and module mocking. Fix findings in code you authored. Pre-existing findings elsewhere are a known backlog: do not mass-fix them, and never silence a rule, weaken severity, or launder types to make the check pass.
|
||||
- Do not assume TypeScript/lint covers server JS, CLI JS, Electron helpers, or native behavior; run focused tests, syntax checks, builds, or runtime validation for the touched surface.
|
||||
- For docs-only or isolated config changes, run the narrowest relevant validation.
|
||||
- Report exactly what was and was not validated. Static checks alone do not prove runtime, relay, performance, or platform correctness.
|
||||
|
||||
+149
@@ -4,6 +4,155 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- **Chat context attachments:** everything you attach to a message — diff/file/plan comments, terminal selections, browser annotations, PR comments and failed checks, linked issues and PRs — now shows up in the conversation as a compact context card: a header naming the source, the captured content behind an expander, and your comment below it. Previously most of these arrived as a wall of raw text inside your message.
|
||||
- **Chat: comment on a reply.** Select text in a chat message and choose Comment to attach that quote with your note to the next message. The selection stays highlighted while you type, and the selection menu itself was restyled — Add to chat is now Add to input.
|
||||
- **Diff: comment like a review.** Hovering a line shows a + button in the gutter; clicking it, clicking a line, or dragging across lines opens the comment editor for that line or range. The comment editor and saved-comment cards now match the chat's comment style.
|
||||
- Files: in a rendered markdown preview, select text and choose Comment to attach exactly that fragment (with a source line range when it can be located) plus your note to the next message.
|
||||
- Composer: hovering or tapping a context chip above the input opens a stacked preview of everything attached, where a comment can be edited in place or an item removed before sending.
|
||||
- Mobile: the chat comment input overlays the composer exactly and rides the keyboard; Enter makes a new line there, with attach on the button.
|
||||
- **Terminal:** terminals no longer vanish or die behind your back. Opening the app in another browser tab, on another device, or after a reload now shows the terminals already running on the server instead of an empty list, and terminals sitting in background tabs are no longer closed by the server's idle cleanup while the app is open.
|
||||
- Chat: @ file mentions now rank files and directories together by how well they match, so the file you typed is at the top instead of below unrelated directories. Multi-word queries match in any order, and long paths keep the folder next to the file name visible so identical-looking index.md rows are distinguishable.
|
||||
- Search: Ctrl/Cmd+P now matches the whole file path, not just the file name — searching a folder name like "solo-is-a" finds the file inside it.
|
||||
- **Session tabs (opt-in):** the web/desktop header can show your open sessions as browser-style tabs — turn them on in Settings → General → Navigation → Session tabs. Every session you open joins the strip, clicking a tab switches the whole workspace (chat, project, panels), and closing one (its × button, middle-click, or Alt+W — rebindable in Shortcuts) never touches the session itself. Tabs reorder by drag, scroll behind the header buttons when there are many and carry the sidebar's running/unread dot. Each tab has the full session menu — on the "..." button or right-click — plus Close other tabs; renaming works right in the tab.
|
||||
- Files: the editor toolbar is now always docked under the file tabs; the floating hover toolbar and its setting were removed.
|
||||
- **Search in dropdowns:** every searchable picker — branches, projects, agents, models, providers, stashes, SSH hosts, skills, archived sessions — now uses one matcher: best matches come first, multi-word queries match in any order, and punctuation doesn't matter (so "gpt4o" finds "gpt-4o"). The git branch and gitmoji pickers also stopped silently dropping rows that a second, built-in filter didn't like. Sidebar session search and the Todos/Memory/Plans/Notes filters match the same way now.
|
||||
- Terminal: mobile keyboards no longer capitalize the first letter of every command on iOS and Android.
|
||||
- Mobile: narrowing a browser window past phone size now switches into the mobile app layout (and back when widened) instead of squeezing the desktop layout. The old/new mobile layout setting is gone — phones always get the mobile layout.
|
||||
- Desktop: a freshly installed or updated build no longer keeps loading the previous version's interface from cache.
|
||||
- Chat: OpenCode notices now share one style.
|
||||
- UI: draft target menus stay inside the chat area instead of overlapping the header.
|
||||
- UI: Linear and Cloudflare tools now show their own icons.
|
||||
- UI: sidebar item tooltips no longer appear instantly on passing hover.
|
||||
- Sessions: headers now find archived sessions too, so an archived session's title no longer goes missing.
|
||||
- UI: the timeline dialog now fits small screens instead of squeezing the message list to a couple of rows (thanks to @gaojunran).
|
||||
- UI: the btw panel's shadow is lighter, matching the composer.
|
||||
- Devices: re-pairing a phone (or logging in again) keeps the device's existing name in Connected Devices instead of resetting it to "OpenChamber Mobile".
|
||||
- Relay: paired devices no longer get logged out when the app restarts (for example during an update) while another local OpenChamber process is running — the restarted app keeps serving them instead of a bystander process taking over.
|
||||
|
||||
## [1.20.0] - 2026-08-23
|
||||
|
||||
- **Session: /btw side questions.** Type `/btw` followed by your question to ask something off-topic in a temporary session forked from the current conversation, so it inherits the full context but leaves the chat itself untouched. The answer streams into a panel above the composer, which talks to that session while the panel is open; you can collapse it to a slim header bar, keep it as a full session, or discard it. The temporary session stays out of the sidebar and session lists until you keep it (thanks to @jaygupta17).
|
||||
- **Chat sessions:** start chats without choosing a project. They live in their own Chats section, rather than inheriting a project's repository and worktree context.
|
||||
- **Desktop/Remote instances:** adding an SSH connection now starts from the hosts in your SSH config instead of a blank command field. Ports, install method and passwords moved behind Advanced settings, and each connection shows Connected, Connecting, or Needs attention with the failure text and a button that resolves it.
|
||||
- Desktop/Remote instances: connecting to a remote machine now works when bun, OpenChamber or the opencode CLI live in your home directory rather than on the system path. Installing no longer fails with a permission error, and a missing opencode CLI is now reported before the connection starts instead of as a stack trace.
|
||||
- Desktop/Remote instances: a managed remote server can now also be published to the remote machine's own network, so other devices there reach it without the SSH tunnel. It requires a UI password, and stays private to the tunnel otherwise.
|
||||
- Desktop/Remote instances: disconnecting from a connection set to not keep the server running now actually stops that remote server.
|
||||
- Skills catalog: browse curated GitHub skill collections in a card-based catalog with cross-source search, skill counts, stars, recent updates, and links back to each skill's repository.
|
||||
- Diff: the context-panel diff can now show every change on the current branch against its base branch. OpenChamber detects the base when Git knows it, or lets you choose one once when it does not.
|
||||
- Dictation: speech is now transcribed after you stop recording. The composer shows a live waveform and timer, and long recordings split at pauses instead of cutting words.
|
||||
- Settings: the project selector on Providers, Agents, MCP, Commands and Skills now only changes what those pages show. It used to switch the whole app, so opening another project's configuration moved your chat, session list and file tree with it.
|
||||
- Settings/Projects: a project can now pin a thinking level next to its model, for models that offer levels. Both sit in one Defaults for new chats group, laid out like the Sessions defaults.
|
||||
- Settings/General: changing the default model, variant or agent no longer repoints an open chat that already carries a model you picked for it. Chats following the default still switch immediately.
|
||||
- Settings/Providers: the provider you select no longer jumps to a different one on its own. Changing the chat's model or agent, and background provider refreshes, used to move the settings selection with them.
|
||||
- Settings/Integrations: the experimental page now only lists integrations that can be installed; unavailable and Coming soon entries were removed.
|
||||
- Chat: file paths in messages now open from the session's project, even if you last browsed files in another project (thanks to @tomzx).
|
||||
- Chat: app links such as `spotify://` now ask for confirmation before opening another app. You can trust an app link type on one device and manage trusted links in Settings.
|
||||
- Files/Desktop: files opened from outside the workspace remain readable after their temporary access expires instead of failing until you reopen them (thanks to @pascalandr).
|
||||
- Diff: creating an inline comment now opens the chat and focuses the composer for your follow-up.
|
||||
- Chat: in the expanded composer, Enter now starts a new line and Cmd/Ctrl+Enter sends, so a long prompt is harder to send by accident.
|
||||
- Providers: expanded support for custom providers.
|
||||
- Small Model: summaries, goal audits, commit messages, and walkthroughs now support more providers.
|
||||
- Git: generated commit messages now match the repository's recent commit style and language.
|
||||
- Git: generating a pull request description now picks up the repository's own PR template when it has one, so the draft comes back in your project's sections and checklists instead of the built-in Summary/Why/Testing layout.
|
||||
- Sidebar: switch between the full project list and a focused view of one project. Sessions created outside OpenChamber now also appear in the sidebar and Recent list without a page refresh (thanks to @tomzx).
|
||||
- Chat: if OpenCode restarts while a response is still running, the chat now stops with an interrupted state and a notification to continue instead of hanging silently (thanks to @sum117).
|
||||
- Chat: while a reply streams, the model status line under the last message now turns into the finished message's info row in place, instead of jumping when the reply completes.
|
||||
- Chat: newly sent messages and syntax-highlighted code blocks no longer briefly flicker. Bash output can also grow with its content instead of being cut off.
|
||||
- Chat: long user messages can be expanded even when their final layout finishes after they first appear.
|
||||
- Chat: in a chat without a project, the work status card again steps aside when the context panel is open, instead of sitting next to it.
|
||||
- Usage: Z.ai credit limits now appear alongside its other quota windows.
|
||||
- Git: pull-request checks in Work status stay current as their status changes.
|
||||
- UI: the default dialog close button is easier to click or tap (thanks to @rockinrimmer).
|
||||
- Desktop/Windows: the close button now aligns correctly with the rest of the window chrome.
|
||||
|
||||
## [1.19.0] - 2026-08-19
|
||||
|
||||
- **Settings/Integrations:** a new Integrations settings page lists Claude Code, Command Code, and Cursor plugins with install, update, setup, and remove actions, plus Discord and Telegram Coming soon placeholders.
|
||||
- **Project knowledge:** the Project notes panel is now Project knowledge, with notes, todos, plans and their search in a resizable sidebar. Notes are cards you expand by clicking anywhere on them, plans open and edit in the panel itself instead of a separate tab, and notes and plans can be pinned as context.
|
||||
- **Files:** drag files onto the Files sidebar to upload them into the project or a specific folder; existing files require confirmation before replacement, and open previews refresh after an upload (thanks to @makeittech, @alanzchen).
|
||||
- Settings: OpenChamber no longer replaces a full OpenCode config with an empty `$schema`-only stub when the file uses JSON5-style unquoted keys; Settings changes now fail instead of wiping plugins, MCP servers, and providers (thanks to @makeittech).
|
||||
- Chat: an open conversation no longer keeps re-coloring the same code blocks in the background, so browsing files with a chat open stops pinning a CPU core and spinning up the fans (thanks to @makeittech).
|
||||
- Stability/Proxy: the local server now reuses its connection to OpenCode instead of opening a new one for every API request. Under sustained traffic the old behavior could use up every outgoing network port on the machine, at which point nothing on the computer could open a new connection until the traffic stopped and the ports were released (thanks to @alohaninja).
|
||||
- Usage/Claude: Claude plan limits now work when you are signed in through Claude Code, without also signing into Anthropic in OpenCode; the account is read from Claude Code's own login on macOS, Linux, and WSL. The page shows your session and weekly limits again, adds per-model weekly limits and extra usage spending, and names your plan. Limits are kept on screen instead of disappearing when Anthropic temporarily blocks refreshes.
|
||||
- Usage/Command Code: Command Code plan limits now appear in the Usage page and work status panel.
|
||||
- Git: the pull request panel now follows the branch's current open PR, and an open PR always wins over an older merged or closed one. After a PR is merged or closed the panel keeps showing it as the branch's last PR and offers creating the next one right below it (thanks to @makeittech).
|
||||
- Git/Worktrees: creating a worktree from a pull request now falls back to GitHub's pull-request reference when the source fork was deleted or cannot be reached, instead of failing before creating the worktree (thanks to @makeittech).
|
||||
- Chat: new chats no longer start against a deleted last worktree directory; they fall back to the active project instead of saving the first message and never starting.
|
||||
- Chat: typing with Chinese, Japanese, or Korean input methods no longer interrupts composition or jumps the cursor to the end of the composer (thanks to @makeittech).
|
||||
- Chat: opening a busy subagent in the context panel now shows its history instead of only the working-status line (thanks to @makeittech).
|
||||
- Chat: saved chats in the context panel open again instead of staying blank.
|
||||
- Chat: the context meter no longer climbs over 100% (330% readouts) after turns with many tool calls and no longer jumps when reopening an older session; it now shows what the window actually holds, everywhere the value appears — header, context sidebar, work status panel, mini chat, and mobile (thanks to @pocharlies).
|
||||
- Chat/Attachments: extracted Office and OpenDocument content is now capped and presented more compactly, preventing large documents and their images from overwhelming the message context.
|
||||
- Projects: project names now match the folder name exactly, so `.ssh` and `opencode-claude` are no longer shown as `.Ssh` and `Opencode Claude` in the sidebar, window title, settings and notifications; names you renamed yourself are kept.
|
||||
- Files: files reached through a symlink inside the workspace now open correctly instead of being rejected as outside the workspace.
|
||||
- Settings: the session retention action you pick is now saved instead of being dropped (thanks to @Gautam0507).
|
||||
- Mobile: connecting through an ngrok address now bypasses ngrok's browser warning page instead of failing the server check.
|
||||
- Mobile/iOS: text selection in the chat composer now uses native CodeMirror selection handles.
|
||||
- Desktop: browser pages served from a self-signed loopback HTTPS address now load instead of being blocked by the certificate warning.
|
||||
- Browser: typing a comment on a page no longer triggers app shortcuts.
|
||||
- Skills Catalog: the source is now named ClawHub instead of "ClawdHub" (thanks to @makeittech).
|
||||
|
||||
## [1.18.4] - 2026-08-14
|
||||
|
||||
- **Chat:** new messages now remain at the end of the conversation instead of jumping before older messages after the message ID sequence rolls over; history loading, revert, and redo follow the same chronological order.
|
||||
- **Stability:** a single internal error no longer shuts down the local server, which made the instance unreachable until it was restarted; the error is logged and the server keeps running.
|
||||
- Mobile: connecting to a server that has authentication disabled now survives closing and reopening the app — auto-reconnect and the return-to-app check no longer treat the missing password token as a lost connection and kick back to the connect screen.
|
||||
- Browser: restoring or opening a dev server preview while connected to an instance over a relay or other non-standard address no longer crashes the app; the preview reports the tunnel as unavailable instead.
|
||||
|
||||
## [1.18.3] - 2026-08-14
|
||||
|
||||
- **Browser panel:** the preview and browser panels are now one panel, backed by a real browser view on the desktop app. Pages that previously refused to load because they were being rewritten now open normally, logins persist, and developer tools are available. Point at an element or drag a region, write a comment, and it goes to chat with a screenshot of what you marked.
|
||||
- **Agent browser control:** agents can now open a page and work with it — read what is on screen, click, type, scroll, look at how an element renders, switch between mobile, tablet and desktop layouts, and save a screenshot into the project — so they can check their own work instead of describing what they expect. It is a separate OpenChamber Web tool, turned on or off in the new Settings → General → OpenChamber Tools section.
|
||||
- **Chat images:** completed assistant replies now collect Markdown images into a compact gallery with thumbnails and full-screen previews, including workspace-local images and a horizontally scrollable mobile layout (thanks to @ChangeHow).
|
||||
- Sessions: switching projects now selects a session owned by the new project, and a message already being prepared stays with the session where it was submitted instead of being rerouted by a later project switch (thanks to @makeittech).
|
||||
- Browser: dev servers are listed from what is actually listening, so one is offered no matter how it was started, and a server that is still starting is waited for instead of showing an error to retry by hand. The panel holds several pages at once, shows each page's own icon, suggests addresses already visited in this project, and adds a hard reload, page zoom, device sizes, a light/dark switch for the page, and clearing cookies or cached data for the panel alone.
|
||||
- Browser: when OpenChamber runs on another machine, the desktop app opens its dev servers through a local port, so pages load with working hot reload and developer tools; links and redirects to another local port stay on that machine. In a web browser tab, only dev servers on your own machine can be opened.
|
||||
- Remote access: pairing QR codes created while the app is open through a public domain (for example behind a reverse proxy) now include that domain as a connection address, so paired phones can reach the server over it instead of relying only on the local network address or the relay.
|
||||
- Remote access: messages sent through the private relay no longer fail with a 400 error when request-body frames are lost during a connection drop; incomplete requests are retried instead (thanks to @claymor333).
|
||||
- Mobile: a brief network hiccup when opening or returning to the app no longer bounces a working connection to the connect screen — the app retries in the background and reconnects on its own, while an unreachable server shows the connect screen within a few seconds.
|
||||
- Mobile: long-pressing the logo on the connect screen (or the instances list) opens a connection log with a copy button, for reporting connection problems.
|
||||
- Usage: quota limits enabled for display now refresh every three minutes on desktop, mobile, and VS Code, with a manual refresh action available at any time.
|
||||
- Usage: OpenCode Go quota tracking now uses the existing OpenCode API key instead of requiring separate browser cookies and a workspace ID.
|
||||
- Scheduled Tasks: when two OpenChamber servers use the same project configuration, a scheduled occurrence now runs only once instead of both servers starting duplicate sessions (thanks to @makeittech).
|
||||
- Desktop/Windows/Linux: minimizing the window now always keeps it in the taskbar; the tray background setting, renamed "Close to the system tray", applies when you close the window.
|
||||
- Performance: closed context panels no longer keep embedded chats running, and an open panel mounts only its active chat instead of every saved chat tab (thanks to @karimodm).
|
||||
- Chat: opening subagent and code-review sessions in the context panel no longer steals focus from the main composer; subagent prompting is available immediately when enabled, and code-review sessions are no longer mistaken for read-only subagent sessions.
|
||||
- Chat: typing `!` to enter shell mode no longer inserts the trigger into the command or moves the caret to the wrong side of it (thanks to @RyderAsKing).
|
||||
- Chat: line numbers with three or more digits no longer wrap in code blocks (thanks to @ChangeHow).
|
||||
- Work status: new-session drafts now show project, MCP, and usage details before a session exists, long subagent lists stay within the panel, and hiding every section leaves controls available to restore them (thanks to @alohaninja).
|
||||
- Desktop/Linux: frameless main and Mini Chat windows now use native rounded corners (thanks to @kydorn).
|
||||
|
||||
## [1.18.2] - 2026-08-10
|
||||
|
||||
- **Observability panel:** a new panel near to the chat brings the active goal, tasks, subagents, pinned context, MCP servers, and context usage into one live view. The session list also shows how long an agent has been working.
|
||||
- **Scheduled Tasks:** projects can now define recurring tasks as Markdown files in `.agents/loops`; opening the task list discovers file changes without a restart, and loop tasks can be edited, enabled, disabled, deleted, or run from the app (thanks to @makeittech).
|
||||
- **Settings:** OpenCode configuration changes now accumulate behind a single Apply & Restart action instead of restarting OpenCode after every edit; the confirmation warns when active chats will be stopped (thanks to @makeittech).
|
||||
- Remote access: paired devices that use the private relay no longer lose relay access when no browser client is currently connected or device-state loading temporarily fails.
|
||||
- Performance: the initial web download is about 58% smaller and startup memory use is about 22% lower; heavy Settings and syntax-highlighting code now loads only when opened (thanks to @makeittech).
|
||||
- Git/Worktrees: prompts now wait for a new worktree to finish checkout before sending, and sessions resolve to the worktree that owns them instead of occasionally opening or sending against the parent repository (thanks to @ftzi).
|
||||
- Git/Worktrees: setup now runs the repository's `post-checkout` hook after creating a worktree, and deeply nested worktrees no longer fail with “Filename too long” on Windows (thanks to @ftzi, @makeittech).
|
||||
- Projects: new project directories can now be created outside the current workspace, and adding, creating, or cloning a project opens a new-session draft targeted at that project instead of leaving the previous session context active.
|
||||
- Chat: messages submitted before switching sessions stay with the session and workspace they were sent from, and are cancelled rather than crossing into a different instance (thanks to @Wsyjq).
|
||||
- Chat: queued messages no longer send into a response that is still streaming, and tool cards left running by an interrupted response settle instead of remaining stuck (thanks to @makeittech).
|
||||
- Chat: shell command output is expanded by default, and adding a message to context returns focus to the composer (thanks to @pascalandr, @makeittech).
|
||||
- Chat: fresh messages no longer replay their entry animation after they have already been shown, and iOS users can insert a newline with Shift+Enter again (thanks to @makeittech).
|
||||
- Chat: the composer caret is now easier to see.
|
||||
- MCP: authorization now handles browser callbacks more reliably, settings distinguish available and unavailable servers more clearly, and failed connections expose a retry action.
|
||||
- Usage: added xAI quota reporting (thanks to @iamhenry).
|
||||
- Terminal: default tab names remain unique after tabs are closed, Escape reaches terminal applications instead of closing the context panel, and background connections send fewer keepalives (thanks to @makeittech).
|
||||
- Desktop/macOS: choosing a folder after denying filesystem access now recovers correctly instead of leaving the app unable to open the directory (thanks to @deatheros).
|
||||
- Desktop/Windows: minimizing from the taskbar now remains a native minimize while the app's own minimize action can still hide to the tray (thanks to @pascalandr).
|
||||
- Desktop: overlay scrollbars auto-hide again after scrolling instead of remaining permanently visible.
|
||||
- Mobile/Android: pairing QR codes now work in older WebViews that misread `openchamber://` links (thanks to @CMBill).
|
||||
- Mobile: pending agent questions now reappear after a cold start instead of leaving the session waiting without an answer prompt.
|
||||
- Files: removing an attached Office or OpenDocument file also removes the images extracted from that document, and Linux reveal failures now surface as an error instead of escaping in the background (thanks to @chiamsun, @pascalandr).
|
||||
- VSCode: notebook links now open in the notebook editor when a compatible extension is installed (thanks to @TTTPOB).
|
||||
- Settings: rapid edits to notification templates no longer overwrite one another, and the collapsed-user-message preference now persists correctly (thanks to @AmanTahiliani, @pascalandr).
|
||||
- Walkthrough: branch comparisons now use the repository's actual remote default branch instead of assuming its name (thanks to @RyderAsKing).
|
||||
- Server: foreground installs managed by a user systemd service now update through a separate transient service instead of being interrupted by the server restart (thanks to @SYU8384).
|
||||
- Security: updated archive extraction to address GHSA-xcpc-8h2w-3j85 (thanks to @mel0nyrame).
|
||||
- UI: dialogs, dropdowns, popovers, and tooltips now use consistent glass styling; the macOS vibrancy option was removed to reduce rendering overhead.
|
||||
|
||||
## [1.18.1] - 2026-08-04
|
||||
|
||||
- **Providers:** signing in to an OAuth-only provider now actually completes — the browser login is stored and the provider list updates instead of remaining signed out. OAuth-only providers show a Connect flow instead of an API key form, and their models stay hidden until you are signed in.
|
||||
|
||||
+18
-1
@@ -113,9 +113,16 @@ The final AppImage verifier checks desktop identity and the architecture of Elec
|
||||
```bash
|
||||
bun run type-check # Must pass
|
||||
bun run lint # Must pass
|
||||
bun run test # Must pass
|
||||
bun run build # Must succeed
|
||||
```
|
||||
|
||||
`bun run test` runs every suite in the repository: shared UI, VS Code, Electron,
|
||||
web/server, and the root scripts. The UI, VS Code, and Electron suites keep
|
||||
module-level singletons, so `scripts/run-isolated-tests.mjs` gives each test file
|
||||
its own process instead of letting load order decide the result. Run a single
|
||||
file directly while iterating (`bun test <file>`).
|
||||
|
||||
For docs-only changes, validation may be enough:
|
||||
|
||||
```bash
|
||||
@@ -197,7 +204,7 @@ state why it remains valid. If there is genuinely no user-visible change, say
|
||||
so and provide a concrete reason; deleting the evidence section is not an
|
||||
exemption.
|
||||
|
||||
### Review Enforcement
|
||||
### Review enforcement
|
||||
|
||||
The automated reviewer performs one unified review of correctness, repository
|
||||
guidance compliance, pull request quality, and evidence. It independently
|
||||
@@ -231,6 +238,16 @@ verify a trustworthy result, in which case it applies `review:automation-failed`
|
||||
Each completed review creates a new comment tied to its reviewed HEAD so the
|
||||
conversation remains chronological. Previous review comments are not rewritten.
|
||||
|
||||
### Keeping PRs active
|
||||
|
||||
Stale PRs add review load and make it hard to tell what's still being worked on, so the stale bot keeps the open list current. A PR with no activity for 28 days is automatically labeled `stale`, and closed 7 days later if it stays inactive. To keep a PR open:
|
||||
|
||||
- Push updates or respond to review feedback
|
||||
- Leave a comment if you're waiting on a reviewer
|
||||
- Add the `pinned`, `security`, or `help wanted` label to exempt a long-running PR from the stale bot
|
||||
|
||||
Reopening a closed PR is fine if it becomes relevant again.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
|
||||
@@ -6,31 +6,31 @@
|
||||
"name": "openchamber-monorepo",
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.4.0",
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
"@codemirror/commands": "^6.10.1",
|
||||
"@codemirror/autocomplete": "^6.20.3",
|
||||
"@codemirror/commands": "^6.11.0",
|
||||
"@codemirror/lang-cpp": "^6.0.3",
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-html": "^6.4.11",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-html": "^6.4.12",
|
||||
"@codemirror/lang-javascript": "^6.2.5",
|
||||
"@codemirror/lang-json": "^6.0.2",
|
||||
"@codemirror/lang-markdown": "^6.5.0",
|
||||
"@codemirror/lang-markdown": "^6.5.2",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.2",
|
||||
"@codemirror/lang-sql": "^6.10.0",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/lint": "^6.9.2",
|
||||
"@codemirror/search": "^6.6.0",
|
||||
"@codemirror/state": "^6.5.4",
|
||||
"@codemirror/view": "6.39.13",
|
||||
"@codemirror/lang-yaml": "^6.1.3",
|
||||
"@codemirror/language": "6.12.4",
|
||||
"@codemirror/lint": "^6.9.7",
|
||||
"@codemirror/search": "^6.7.1",
|
||||
"@codemirror/state": "^6.7.1",
|
||||
"@codemirror/view": "6.43.9",
|
||||
"@heroui/scroll-shadow": "^2.3.18",
|
||||
"@heroui/system": "^2.4.23",
|
||||
"@heroui/theme": "^2.4.23",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@octokit/rest": "^22.0.1",
|
||||
"@opencode-ai/sdk": "1.18.12",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||
@@ -65,6 +65,7 @@
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "^1.1.0",
|
||||
"@eslint/js": "^9.33.0",
|
||||
"@oxlint/plugins": "1.78.0",
|
||||
"@remixicon/react": "^4.7.0",
|
||||
"@tailwindcss/postcss": "^4.0.0",
|
||||
"@types/dom-speech-recognition": "^0.0.12",
|
||||
@@ -83,6 +84,7 @@
|
||||
"globals": "^16.3.0",
|
||||
"node-addon-api": "7.1.1",
|
||||
"nodemon": "^3.1.7",
|
||||
"oxlint": "1.78.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"sharp": "^0.35.0",
|
||||
"tailwindcss": "^4.0.0",
|
||||
@@ -95,7 +97,7 @@
|
||||
},
|
||||
"packages/electron": {
|
||||
"name": "@openchamber/electron",
|
||||
"version": "1.18.0",
|
||||
"version": "1.20.0",
|
||||
"dependencies": {
|
||||
"@openchamber/web": "workspace:*",
|
||||
"electron-context-menu": "^4.1.2",
|
||||
@@ -103,9 +105,10 @@
|
||||
"electron-updater": "^6.8.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron/rebuild": "^3.7.0",
|
||||
"electron": "^41.2.1",
|
||||
"@electron/rebuild": "^4.2.0",
|
||||
"electron": "^43.3.0",
|
||||
"electron-builder": "^26.0.0",
|
||||
"node-abi": "^4.33.0",
|
||||
},
|
||||
},
|
||||
"packages/mobile": {
|
||||
@@ -131,7 +134,7 @@
|
||||
},
|
||||
"packages/ui": {
|
||||
"name": "@openchamber/ui",
|
||||
"version": "1.18.0",
|
||||
"version": "1.20.0",
|
||||
"dependencies": {
|
||||
"@aparajita/capacitor-secure-storage": "^8.0.0",
|
||||
"@base-ui/react": "^1.4.0",
|
||||
@@ -140,38 +143,37 @@
|
||||
"@capacitor/keyboard": "^8.0.0",
|
||||
"@capacitor/push-notifications": "^8.1.1",
|
||||
"@capacitor/status-bar": "^8.0.0",
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
"@codemirror/commands": "^6.10.1",
|
||||
"@codemirror/autocomplete": "^6.20.3",
|
||||
"@codemirror/commands": "^6.11.0",
|
||||
"@codemirror/lang-cpp": "^6.0.3",
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-html": "^6.4.11",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-html": "^6.4.12",
|
||||
"@codemirror/lang-javascript": "^6.2.5",
|
||||
"@codemirror/lang-json": "^6.0.2",
|
||||
"@codemirror/lang-markdown": "^6.5.0",
|
||||
"@codemirror/lang-markdown": "^6.5.2",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.2",
|
||||
"@codemirror/lang-sql": "^6.10.0",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/lang-yaml": "^6.1.3",
|
||||
"@codemirror/language": "6.12.4",
|
||||
"@codemirror/language-data": "^6.5.2",
|
||||
"@codemirror/legacy-modes": "^6.5.2",
|
||||
"@codemirror/lint": "^6.9.2",
|
||||
"@codemirror/search": "^6.6.0",
|
||||
"@codemirror/state": "^6.5.4",
|
||||
"@codemirror/view": "6.39.13",
|
||||
"@codemirror/legacy-modes": "^6.5.3",
|
||||
"@codemirror/lint": "^6.9.7",
|
||||
"@codemirror/search": "^6.7.1",
|
||||
"@codemirror/state": "^6.7.1",
|
||||
"@codemirror/view": "6.43.9",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@opencode-ai/sdk": "1.18.12",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
"@pierre/diffs": "1.3.0-beta.6",
|
||||
"@replit/codemirror-vim": "^6.3.0",
|
||||
"@replit/codemirror-vim": "^6.4.0",
|
||||
"@simplewebauthn/browser": "13.3.0",
|
||||
"@tanstack/react-virtual": "3.14.5",
|
||||
"@xenova/transformers": "^2.17.2",
|
||||
"@zumer/snapdom": "^2.12.0",
|
||||
"beautiful-mermaid": "^1.1.3",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -236,10 +238,10 @@
|
||||
},
|
||||
"packages/vscode": {
|
||||
"name": "openchamber",
|
||||
"version": "1.18.0",
|
||||
"version": "1.20.0",
|
||||
"dependencies": {
|
||||
"@openchamber/ui": "workspace:*",
|
||||
"@opencode-ai/sdk": "1.18.12",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
"adm-zip": "^0.6.0",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"react": "^19.1.1",
|
||||
@@ -259,16 +261,15 @@
|
||||
},
|
||||
"packages/web": {
|
||||
"name": "@openchamber/web",
|
||||
"version": "1.18.0",
|
||||
"version": "1.20.0",
|
||||
"bin": {
|
||||
"openchamber": "./bin/cli.js",
|
||||
},
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.1.0",
|
||||
"@octokit/rest": "^22.0.1",
|
||||
"@opencode-ai/sdk": "1.18.12",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
"@simplewebauthn/server": "13.3.1",
|
||||
"adm-zip": "^0.6.0",
|
||||
"bun-pty": "^0.4.5",
|
||||
"compression": "^1.8.1",
|
||||
"cron-parser": "^4.9.0",
|
||||
@@ -304,7 +305,6 @@
|
||||
"@remixicon/react": "^4.7.0",
|
||||
"@simplewebauthn/browser": "13.3.0",
|
||||
"@tailwindcss/postcss": "^4.0.0",
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/node": "^24.3.1",
|
||||
"@types/react": "^19.1.10",
|
||||
"@types/react-dom": "^19.1.7",
|
||||
@@ -353,8 +353,18 @@
|
||||
"bun-pty@0.4.8": "bun-patches/bun-pty@0.4.8.patch",
|
||||
},
|
||||
"overrides": {
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/view": "6.39.13",
|
||||
"@codemirror/autocomplete": "6.20.3",
|
||||
"@codemirror/commands": "6.11.0",
|
||||
"@codemirror/lang-html": "6.4.12",
|
||||
"@codemirror/lang-javascript": "6.2.5",
|
||||
"@codemirror/lang-markdown": "6.5.2",
|
||||
"@codemirror/lang-yaml": "6.1.3",
|
||||
"@codemirror/language": "6.12.4",
|
||||
"@codemirror/legacy-modes": "6.5.3",
|
||||
"@codemirror/lint": "6.9.7",
|
||||
"@codemirror/search": "6.7.1",
|
||||
"@codemirror/state": "6.7.1",
|
||||
"@codemirror/view": "6.43.9",
|
||||
},
|
||||
"packages": {
|
||||
"7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="],
|
||||
@@ -601,9 +611,9 @@
|
||||
|
||||
"@clack/prompts": ["@clack/prompts@1.1.0", "", { "dependencies": { "@clack/core": "1.1.0", "sisteransi": "^1.0.5" } }, "sha512-pkqbPGtohJAvm4Dphs2M8xE29ggupihHdy1x84HNojZuMtFsHiUlRvqD24tM2+XmI+61LlfNceM3Wr7U5QES5g=="],
|
||||
|
||||
"@codemirror/autocomplete": ["@codemirror/autocomplete@6.20.0", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg=="],
|
||||
"@codemirror/autocomplete": ["@codemirror/autocomplete@6.20.3", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g=="],
|
||||
|
||||
"@codemirror/commands": ["@codemirror/commands@6.10.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ=="],
|
||||
"@codemirror/commands": ["@codemirror/commands@6.11.0", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.7.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-/K4Rl5BN0OtTiPWmJCdqODu38XnDMsDxKY5rgrPnCkutPTJf2wVbkoixLfealF5Kwse/s8P8M5jAiURiwSwnFA=="],
|
||||
|
||||
"@codemirror/lang-angular": ["@codemirror/lang-angular@0.1.4", "", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-javascript": "^6.1.2", "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.3" } }, "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g=="],
|
||||
|
||||
@@ -613,11 +623,11 @@
|
||||
|
||||
"@codemirror/lang-go": ["@codemirror/lang-go@6.0.1", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/go": "^1.0.0" } }, "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg=="],
|
||||
|
||||
"@codemirror/lang-html": ["@codemirror/lang-html@6.4.11", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/css": "^1.1.0", "@lezer/html": "^1.3.12" } }, "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw=="],
|
||||
"@codemirror/lang-html": ["@codemirror/lang-html@6.4.12", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/css": "^1.1.0", "@lezer/html": "^1.3.12" } }, "sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w=="],
|
||||
|
||||
"@codemirror/lang-java": ["@codemirror/lang-java@6.0.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@lezer/java": "^1.0.0" } }, "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ=="],
|
||||
|
||||
"@codemirror/lang-javascript": ["@codemirror/lang-javascript@6.2.4", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/lint": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/javascript": "^1.0.0" } }, "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA=="],
|
||||
"@codemirror/lang-javascript": ["@codemirror/lang-javascript@6.2.5", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/lint": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/javascript": "^1.0.0" } }, "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A=="],
|
||||
|
||||
"@codemirror/lang-jinja": ["@codemirror/lang-jinja@6.0.0", "", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.4.0" } }, "sha512-47MFmRcR8UAxd8DReVgj7WJN1WSAMT7OJnewwugZM4XiHWkOjgJQqvEM1NpMj9ALMPyxmlziEI1opH9IaEvmaw=="],
|
||||
|
||||
@@ -627,7 +637,7 @@
|
||||
|
||||
"@codemirror/lang-liquid": ["@codemirror/lang-liquid@6.3.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.1" } }, "sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw=="],
|
||||
|
||||
"@codemirror/lang-markdown": ["@codemirror/lang-markdown@6.5.0", "", { "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.3.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/markdown": "^1.0.0" } }, "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw=="],
|
||||
"@codemirror/lang-markdown": ["@codemirror/lang-markdown@6.5.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.3.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/markdown": "^1.0.0" } }, "sha512-AwBOdkWYuA//WcM0xO5PfHPUcmz/O2i5o0Nsg1U69SII/loCJlFI1Romd9xp2HYb1kYJRGZotyqRghuHH5n8Kw=="],
|
||||
|
||||
"@codemirror/lang-php": ["@codemirror/lang-php@6.0.2", "", { "dependencies": { "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/php": "^1.0.0" } }, "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA=="],
|
||||
|
||||
@@ -645,21 +655,21 @@
|
||||
|
||||
"@codemirror/lang-xml": ["@codemirror/lang-xml@6.1.0", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.0.0", "@lezer/xml": "^1.0.0" } }, "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg=="],
|
||||
|
||||
"@codemirror/lang-yaml": ["@codemirror/lang-yaml@6.1.2", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.0.0", "@lezer/yaml": "^1.0.0" } }, "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw=="],
|
||||
"@codemirror/lang-yaml": ["@codemirror/lang-yaml@6.1.3", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.2.0", "@lezer/lr": "^1.0.0", "@lezer/yaml": "^1.0.0" } }, "sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ=="],
|
||||
|
||||
"@codemirror/language": ["@codemirror/language@6.12.2", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg=="],
|
||||
"@codemirror/language": ["@codemirror/language@6.12.4", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A=="],
|
||||
|
||||
"@codemirror/language-data": ["@codemirror/language-data@6.5.2", "", { "dependencies": { "@codemirror/lang-angular": "^0.1.0", "@codemirror/lang-cpp": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-go": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-java": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/lang-jinja": "^6.0.0", "@codemirror/lang-json": "^6.0.0", "@codemirror/lang-less": "^6.0.0", "@codemirror/lang-liquid": "^6.0.0", "@codemirror/lang-markdown": "^6.0.0", "@codemirror/lang-php": "^6.0.0", "@codemirror/lang-python": "^6.0.0", "@codemirror/lang-rust": "^6.0.0", "@codemirror/lang-sass": "^6.0.0", "@codemirror/lang-sql": "^6.0.0", "@codemirror/lang-vue": "^0.1.1", "@codemirror/lang-wast": "^6.0.0", "@codemirror/lang-xml": "^6.0.0", "@codemirror/lang-yaml": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/legacy-modes": "^6.4.0" } }, "sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg=="],
|
||||
|
||||
"@codemirror/legacy-modes": ["@codemirror/legacy-modes@6.5.2", "", { "dependencies": { "@codemirror/language": "^6.0.0" } }, "sha512-/jJbwSTazlQEDOQw2FJ8LEEKVS72pU0lx6oM54kGpL8t/NJ2Jda3CZ4pcltiKTdqYSRk3ug1B3pil1gsjA6+8Q=="],
|
||||
"@codemirror/legacy-modes": ["@codemirror/legacy-modes@6.5.3", "", { "dependencies": { "@codemirror/language": "^6.0.0" } }, "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg=="],
|
||||
|
||||
"@codemirror/lint": ["@codemirror/lint@6.9.4", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw=="],
|
||||
"@codemirror/lint": ["@codemirror/lint@6.9.7", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.42.0", "crelt": "^1.0.5" } }, "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg=="],
|
||||
|
||||
"@codemirror/search": ["@codemirror/search@6.6.0", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw=="],
|
||||
"@codemirror/search": ["@codemirror/search@6.7.1", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "sha512-uMe5UO6PamJtSHrXhhHOzSX3ReWtiJrva6GnPMwSOrZtiExb5X5eExhr2OUZQVvdxPsKpY3Ro2mFbQadpPWmHA=="],
|
||||
|
||||
"@codemirror/state": ["@codemirror/state@6.5.4", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw=="],
|
||||
"@codemirror/state": ["@codemirror/state@6.7.1", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A=="],
|
||||
|
||||
"@codemirror/view": ["@codemirror/view@6.39.13", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-QBO8ZsgJLCbI28KdY0/oDy5NQLqOQVZCozBknxc2/7L98V+TVYFHnfaCsnGh1U+alpd2LOkStVwYY7nW2R1xbw=="],
|
||||
"@codemirror/view": ["@codemirror/view@6.43.9", "", { "dependencies": { "@codemirror/state": "^6.7.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-sTuUzTpPMFebRhg6dawChoKKgndIwfjmJgKVxBefPElcU2NwQ6AFroupk0SFqEerQyZOGRfDNnSN8Dw/lMAsXw=="],
|
||||
|
||||
"@date-fns/tz": ["@date-fns/tz@1.4.1", "", {}, "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="],
|
||||
|
||||
@@ -673,19 +683,19 @@
|
||||
|
||||
"@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="],
|
||||
|
||||
"@electron-internal/extract-zip": ["@electron-internal/extract-zip@1.0.5", "", {}, "sha512-+bqFCP98pLI0Tt0XQo1TmlXtwjWchISndDOxCkEcIuUgXWpBnLyRI+2DU+mesvnMMX6L1XDqYNA0lXNDHd/yiA=="],
|
||||
|
||||
"@electron/asar": ["@electron/asar@3.4.1", "", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="],
|
||||
|
||||
"@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="],
|
||||
|
||||
"@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],
|
||||
|
||||
"@electron/node-gyp": ["@electron/node-gyp@github:electron/node-gyp#06b29aa", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^8.1.0", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.2.1", "nopt": "^6.0.0", "proc-log": "^2.0.1", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^2.0.2" }, "bin": "./bin/node-gyp.js" }, "electron-node-gyp-06b29aa", "sha512-UJwi6aXMAiUaOvqPHVlMtCOLRa1QAU2SqYD9H07KHpN+I2mBoFuxP1HnUOkt86+j+/o/XyHpM7D33JFFQi/jfA=="],
|
||||
"@electron/get": ["@electron/get@5.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^3.0.0", "graceful-fs": "^4.2.11", "progress": "^2.0.3", "semver": "^7.6.3", "sumchecker": "^3.0.1" }, "optionalDependencies": { "undici": "^7.24.4" } }, "sha512-3kSBtG8ObcTVfXanm5vVJ6UnBLEVmVsRk1M+vGqCuMBV+XLCbJYuWQful+yIy0GQDsSlK0kHEriEHn7SPk4EnA=="],
|
||||
|
||||
"@electron/notarize": ["@electron/notarize@2.5.0", "", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", "promise-retry": "^2.0.1" } }, "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A=="],
|
||||
|
||||
"@electron/osx-sign": ["@electron/osx-sign@1.3.3", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg=="],
|
||||
|
||||
"@electron/rebuild": ["@electron/rebuild@3.7.2", "", { "dependencies": { "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", "fs-extra": "^10.0.0", "got": "^11.7.0", "node-abi": "^3.45.0", "node-api-version": "^0.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", "tar": "^6.0.5", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg=="],
|
||||
"@electron/rebuild": ["@electron/rebuild@4.2.0", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.1.1", "node-abi": "^4.2.0", "node-api-version": "^0.2.1", "node-gyp": "^12.2.0", "read-binary-file-arch": "^1.0.6" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-RKL/O+jGoXJMxrx/5771y1n0xTKmFuOYGO3gMmwypBM6rsH0kou0mswwdXA2JrhIkE4xyC7v9vGk0n6NPzgOxQ=="],
|
||||
|
||||
"@electron/universal": ["@electron/universal@2.0.3", "", { "dependencies": { "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g=="],
|
||||
|
||||
@@ -781,8 +791,6 @@
|
||||
|
||||
"@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.6.2", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA=="],
|
||||
|
||||
"@gar/promisify": ["@gar/promisify@1.1.3", "", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="],
|
||||
|
||||
"@heroui/react-rsc-utils": ["@heroui/react-rsc-utils@2.1.9", "", { "peerDependencies": { "react": ">=18 || >=19.0.0-rc.0" } }, "sha512-e77OEjNCmQxE9/pnLDDb93qWkX58/CcgIqdNAczT/zUP+a48NxGq2A2WRimvc1uviwaNL2StriE2DmyZPyYW7Q=="],
|
||||
|
||||
"@heroui/react-utils": ["@heroui/react-utils@2.1.14", "", { "dependencies": { "@heroui/react-rsc-utils": "2.1.9", "@heroui/shared-utils": "2.1.12" }, "peerDependencies": { "react": ">=18 || >=19.0.0-rc.0" } }, "sha512-hhKklYKy9sRH52C9A8P0jWQ79W4MkIvOnKBIuxEMHhigjfracy0o0lMnAUdEsJni4oZKVJYqNGdQl+UVgcmeDA=="],
|
||||
@@ -961,9 +969,7 @@
|
||||
|
||||
"@npmcli/agent": ["@npmcli/agent@3.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^10.0.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q=="],
|
||||
|
||||
"@npmcli/fs": ["@npmcli/fs@2.1.2", "", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="],
|
||||
|
||||
"@npmcli/move-file": ["@npmcli/move-file@2.0.1", "", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="],
|
||||
"@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="],
|
||||
|
||||
"@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="],
|
||||
|
||||
@@ -997,7 +1003,47 @@
|
||||
|
||||
"@openchamber/web": ["@openchamber/web@workspace:packages/web"],
|
||||
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.12", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-Skjm0uRWqIiL9BQliZSrvnBflT99q1aGhT2pATNwli2WU8XSKm4lhZJFay7dIzjrA5C9SfgK+YSeoES2PbFugA=="],
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.21", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-k6iHQ5C8wOPglk+LgFyYnst168cGMQYumgpbVoeXJ+iC1AtvwD5zmjuF8CxMze/y9G1K2bOeO6p9yRvA7eHZLA=="],
|
||||
|
||||
"@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.78.0", "", { "os": "android", "cpu": "arm" }, "sha512-Bu819lmAfZMUHErrpe0cEWj3iaefuUODHSU8+UbXy67V/r7/7f4K3FL0NmbD85E+wiFLDYuhP8Zlv0XnVeXshw=="],
|
||||
|
||||
"@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.78.0", "", { "os": "android", "cpu": "arm64" }, "sha512-CDfxZgB61B7buRdY2FJoAYYPPXCZ1EoC1LKscnC5dg3kjobdxiconvAvvN1BmHyW4PyFT3jRLDag/BY/roSNBQ=="],
|
||||
|
||||
"@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.78.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-2Y2U9Ahrz+OO0Ej88f9SJYq51/jUBp1Mc7iZu0ukrbeeZ3gpRGfzIFnoqfHDY96xr0GEfNrPUBFEy0nN5aD7HA=="],
|
||||
|
||||
"@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.78.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-rpych6eJq6m9jDRypTEaPD1xysaEW5h9+xuxhGK/QhOg+/xaqPZrCrTNoIl/f3nEjuJeCEmstNDlrE9rJi/3/g=="],
|
||||
|
||||
"@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.78.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IcMGrQT3QizkOESUJd5et+rOhVqSkNDfNik1cvrKDqIbzqx9KMtRswpFgkCuNTSwylCFLKhGUu8KmqY1ZnC0Dg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.78.0", "", { "os": "linux", "cpu": "arm" }, "sha512-/uLdoJ0IXE6vo/0f0LKjinQAp+re+VMaCWaNT8ENIv2EOCkSsc8SGaflXAuW0Jua2dq5+GLVWm1NQK7P3UFSNQ=="],
|
||||
|
||||
"@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.78.0", "", { "os": "linux", "cpu": "arm" }, "sha512-7xi4Wb/O8NRJhLoUXmDJMUVpNYvB5kefdhFU1Jb8rtae4QoXlTiLwI14X4YvAXVZLNZChP8m5qO9SQAlWQTbkQ=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.78.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-4hFW0+fVXa3OIh1Y4A5SPkmvI4wuuBSrCVKzOyE7PTjhc7yEqZ1pmvEEeS5Lj/MaqvegFxXyF33N+6jkehxdyg=="],
|
||||
|
||||
"@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.78.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-oC0mvsgBJjlMijSDEhx9KuvR9zYeHXceA9MjbuXB1F8NSR78Yj2unOBrstEvTVaq+pko+kuue6DajC00eqvTdg=="],
|
||||
|
||||
"@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.78.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-XAllT5SUZS+ohjuZ3/5S0cwe0r7eboiuigeStCZ5DXRYx/2KVM2UvQXvAfyzXEimtQjAB7cDQ2YxDe2Zl2WNQQ=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.78.0", "", { "os": "linux", "cpu": "none" }, "sha512-trucMER/0QtecoXvc1y/UVqE3kwJipDwrx4oHfj+nNm3dq2zjP44WT0CfHNDPM3G1DXIkx/gY6lAD21NSCZVhA=="],
|
||||
|
||||
"@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.78.0", "", { "os": "linux", "cpu": "none" }, "sha512-cm3O4F/HQbdzOUX5mKHqG5KDL6E5w0pnlZ+fbBy2rmLryPOowkuLagFHTopQsEIpjcaZoPOrL+BmmAytAG9HFg=="],
|
||||
|
||||
"@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.78.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-33wRf6HqGNsybJ3qX4cGaQN2ODPxNmc1rMa0mrTmx3eFq1VzOnvQooi9bIGVYakW8a/wmqVx1mgsUm8R2xfTiw=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.78.0", "", { "os": "linux", "cpu": "x64" }, "sha512-rRdISSYegj6VganMZ9tjRjijowfHJ09IZU01i0toBAqr6n5LEtwHq2IeS4FjW2RoskOHlb6efB26H5izYb3GEQ=="],
|
||||
|
||||
"@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.78.0", "", { "os": "linux", "cpu": "x64" }, "sha512-GmsP4rW0xTL6u5CVdcDsaN5Fbc7hBc382Wmar1kttbnwSEviM+rSINKOMQ+UQ6iH+AGwC+8gaAiwu134Tgh6Lg=="],
|
||||
|
||||
"@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.78.0", "", { "os": "none", "cpu": "arm64" }, "sha512-sy9yeYuADc8a+n4TLBayzMCZiHPW78DcIFVpOXTmdKHWQeM9xe5uzkqIIZmi326D5hY9XVwacipEB1p7tQjPAg=="],
|
||||
|
||||
"@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.78.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-rjc2hF1KfMi8fZj1X/m3AmnHbdsF3rL0v6KQg0Uc880Yb2khjz+3U14sfdZ7jWTpRnN1m1NQa/TT7uU9lJWPrA=="],
|
||||
|
||||
"@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.78.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-zcuXFVrEFHIafRfkCQT8w/Xe41o07ozl/vwHq7p94vB29xVzsB0sZGYORU1jhcYKv3Lr0J3HbJ2T4fHH5rWmvA=="],
|
||||
|
||||
"@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.78.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Sb5ocmLSuYeOuXd+CFOToGKp/gjXUEWDnvIGwhnh8aq8wY4TMmEnKnvbogSW7RdMZv77JSARduS7/gv+khYEjA=="],
|
||||
|
||||
"@oxlint/plugins": ["@oxlint/plugins@1.78.0", "", {}, "sha512-Ypt8KeRYw+4jUtlPirfcHWMrn5ms12VrrFPD+Mds477/7tJxG1Kcz2Yrg2nVcTQEUx/GdlhS+BUg1kmxNm04Ug=="],
|
||||
|
||||
"@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.3.1", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw=="],
|
||||
|
||||
@@ -1153,7 +1199,9 @@
|
||||
|
||||
"@remixicon/react": ["@remixicon/react@4.9.0", "", { "peerDependencies": { "react": ">=18.2.0" } }, "sha512-5/jLDD4DtKxH2B4QVXTobvV1C2uL8ab9D5yAYNtFt+w80O0Ys1xFOrspqROL3fjrZi+7ElFUWE37hBfaAl6U+Q=="],
|
||||
|
||||
"@replit/codemirror-vim": ["@replit/codemirror-vim@6.3.0", "", { "peerDependencies": { "@codemirror/commands": "6.x.x", "@codemirror/language": "6.x.x", "@codemirror/search": "6.x.x", "@codemirror/state": "6.x.x", "@codemirror/view": "6.x.x" } }, "sha512-aTx931ULAMuJx6xLf7KQDOL7CxD+Sa05FktTDrtLaSy53uj01ll3Zf17JdKsriER248oS55GBzg0CfCTjEneAQ=="],
|
||||
"@replit/codemirror-vim": ["@replit/codemirror-vim@6.4.0", "", { "dependencies": { "@replit/codemirror-vim-core": "^0.1.0" }, "peerDependencies": { "@codemirror/commands": "6.x.x", "@codemirror/language": "6.x.x", "@codemirror/search": "6.x.x", "@codemirror/state": "6.x.x", "@codemirror/view": "6.x.x" } }, "sha512-t9UMDNhkmeAkl0uRbiJVotv97bGD6mf4GyJJoEbrjUqa/Pov0s9eL+4AaI0Xto3OGri17i9qwIpT0JbVlVXt8A=="],
|
||||
|
||||
"@replit/codemirror-vim-core": ["@replit/codemirror-vim-core@0.1.0", "", {}, "sha512-1i6EBKpcNfDKvTmTh6N6g9lL6udD5t+uFNh4JCqozRnVlvUGOps7h/QzS2ne4zcvPUjvApKpmcP7Grc3fNbZiQ=="],
|
||||
|
||||
"@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="],
|
||||
|
||||
@@ -1321,8 +1369,6 @@
|
||||
|
||||
"@textlint/types": ["@textlint/types@15.5.2", "", { "dependencies": { "@textlint/ast-node-types": "15.5.2" } }, "sha512-sJOrlVLLXp4/EZtiWKWq9y2fWyZlI8GP+24rnU5avtPWBIMm/1w97yzKrAqYF8czx2MqR391z5akhnfhj2f/AQ=="],
|
||||
|
||||
"@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="],
|
||||
|
||||
"@types/adm-zip": ["@types/adm-zip@0.5.7", "", { "dependencies": { "@types/node": "*" } }, "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw=="],
|
||||
|
||||
"@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
|
||||
@@ -1405,8 +1451,6 @@
|
||||
|
||||
"@types/vscode": ["@types/vscode@1.109.0", "", {}, "sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw=="],
|
||||
|
||||
"@types/yauzl": ["@types/yauzl@2.10.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.56.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/type-utils": "8.56.1", "@typescript-eslint/utils": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.56.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@8.56.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", "@typescript-eslint/typescript-estree": "8.56.1", "@typescript-eslint/visitor-keys": "8.56.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg=="],
|
||||
@@ -1477,7 +1521,7 @@
|
||||
|
||||
"@zumer/snapdom": ["@zumer/snapdom@2.12.8", "", {}, "sha512-dLX6ZMNjLveasn9yhcruOOfd8GBZBDp59F7iJoLlGf7BnGp0vfVsjxIZDIjN2UTZJN1KoJR/BXsxEnAyY7LuXA=="],
|
||||
|
||||
"abbrev": ["abbrev@1.1.1", "", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="],
|
||||
"abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
|
||||
|
||||
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
|
||||
|
||||
@@ -1493,8 +1537,6 @@
|
||||
|
||||
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
|
||||
|
||||
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
|
||||
|
||||
"ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
|
||||
|
||||
"ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="],
|
||||
@@ -1625,7 +1667,7 @@
|
||||
|
||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||
|
||||
"cacache": ["cacache@16.1.3", "", { "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" } }, "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ=="],
|
||||
"cacache": ["cacache@19.0.1", "", { "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", "tar": "^7.4.3", "unique-filename": "^4.0.0" } }, "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ=="],
|
||||
|
||||
"cacheable-lookup": ["cacheable-lookup@5.0.4", "", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="],
|
||||
|
||||
@@ -1663,7 +1705,7 @@
|
||||
|
||||
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
|
||||
|
||||
"chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="],
|
||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"chromium-pickle-js": ["chromium-pickle-js@0.2.0", "", {}, "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw=="],
|
||||
|
||||
@@ -1671,8 +1713,6 @@
|
||||
|
||||
"class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
|
||||
|
||||
"clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
|
||||
|
||||
"cli-cursor": ["cli-cursor@3.1.0", "", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="],
|
||||
|
||||
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
|
||||
@@ -1851,7 +1891,7 @@
|
||||
|
||||
"ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="],
|
||||
|
||||
"electron": ["electron@41.2.1", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-teeRThiYGTPKf/2yOW7zZA1bhb91KEQ4yLBPOg7GxpmnkLFLugKgQaAKOrCgdzwsXh/5mFIfmkm+4+wACJKwaA=="],
|
||||
"electron": ["electron@43.3.0", "", { "dependencies": { "@electron-internal/extract-zip": "^1.0.1", "@electron/get": "^5.0.0", "@types/node": "^24.9.0" }, "bin": { "electron": "cli.js", "install-electron": "install.js" } }, "sha512-nLlvu0WFjftWsSaTkV2B/c4NDuJBspTyXu8vKSQ6vLvFt8uG3NgN49LLKcXddwX0GqVvAQDhciWp+4xOdTdhew=="],
|
||||
|
||||
"electron-builder": ["electron-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "ci-info": "^4.2.0", "dmg-builder": "26.8.1", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { "electron-builder": "cli.js", "install-app-deps": "install-app-deps.js" } }, "sha512-uWhx1r74NGpCagG0ULs/P9Nqv2nsoo+7eo4fLUOB8L8MdWltq9odW/uuLXMFCDGnPafknYLZgjNX0ZIFRzOQAw=="],
|
||||
|
||||
@@ -1969,8 +2009,6 @@
|
||||
|
||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||
|
||||
"extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="],
|
||||
|
||||
"extsprintf": ["extsprintf@1.4.1", "", {}, "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="],
|
||||
|
||||
"fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="],
|
||||
@@ -2041,7 +2079,7 @@
|
||||
|
||||
"fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="],
|
||||
|
||||
"fs-minipass": ["fs-minipass@2.1.0", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="],
|
||||
"fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
|
||||
|
||||
"fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
|
||||
|
||||
@@ -2183,12 +2221,8 @@
|
||||
|
||||
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
|
||||
|
||||
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
||||
|
||||
"index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="],
|
||||
|
||||
"infer-owner": ["infer-owner@1.0.4", "", {}, "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="],
|
||||
|
||||
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
|
||||
|
||||
"inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
@@ -2251,8 +2285,6 @@
|
||||
|
||||
"is-interactive": ["is-interactive@1.0.0", "", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="],
|
||||
|
||||
"is-lambda": ["is-lambda@1.0.1", "", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="],
|
||||
|
||||
"is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
|
||||
|
||||
"is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="],
|
||||
@@ -2439,7 +2471,7 @@
|
||||
|
||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||
|
||||
"make-fetch-happen": ["make-fetch-happen@10.2.1", "", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="],
|
||||
"make-fetch-happen": ["make-fetch-happen@14.0.3", "", { "dependencies": { "@npmcli/agent": "^3.0.0", "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" } }, "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ=="],
|
||||
|
||||
"markdown-it": ["markdown-it@14.1.1", "", { "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", "linkify-it": "^5.0.0", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" }, "bin": { "markdown-it": "bin/markdown-it.mjs" } }, "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA=="],
|
||||
|
||||
@@ -2569,11 +2601,11 @@
|
||||
|
||||
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
||||
|
||||
"minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="],
|
||||
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"minipass-collect": ["minipass-collect@1.0.2", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="],
|
||||
"minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="],
|
||||
|
||||
"minipass-fetch": ["minipass-fetch@2.1.2", "", { "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA=="],
|
||||
"minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="],
|
||||
|
||||
"minipass-flush": ["minipass-flush@1.0.7", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA=="],
|
||||
|
||||
@@ -2581,9 +2613,9 @@
|
||||
|
||||
"minipass-sized": ["minipass-sized@1.0.3", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="],
|
||||
|
||||
"minizlib": ["minizlib@2.1.2", "", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="],
|
||||
"minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
|
||||
"mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="],
|
||||
|
||||
"mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
|
||||
|
||||
@@ -2611,7 +2643,7 @@
|
||||
|
||||
"next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="],
|
||||
|
||||
"node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="],
|
||||
"node-abi": ["node-abi@4.33.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-vLBWCKb+7LWsX+TbfzWOkw0W81m377tyx3hOweBTjO43CXZnRGS1/JPWs20fr0PgZyDXk6ROYrylsEycK8raDA=="],
|
||||
|
||||
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
|
||||
|
||||
@@ -2621,7 +2653,7 @@
|
||||
|
||||
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
|
||||
|
||||
"node-gyp": ["node-gyp@11.5.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ=="],
|
||||
"node-gyp": ["node-gyp@12.4.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw=="],
|
||||
|
||||
"node-pty": ["node-pty@1.2.0-beta.12", "", { "dependencies": { "node-addon-api": "^7.1.0" } }, "sha512-uExTCG/4VmSJa4+TjxFwPXv8BfacmfFEBL6JpxCMDghcwqzvD0yTcGmZ1fKOK6HY33tp0CelLblqTECJizc+Yw=="],
|
||||
|
||||
@@ -2631,7 +2663,7 @@
|
||||
|
||||
"nodemon": ["nodemon@3.1.14", "", { "dependencies": { "chokidar": "^3.5.2", "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^10.2.1", "pstree.remy": "^1.1.8", "semver": "^7.5.3", "simple-update-notifier": "^2.0.0", "supports-color": "^5.5.0", "touch": "^3.1.0", "undefsafe": "^2.0.5" }, "bin": { "nodemon": "bin/nodemon.js" } }, "sha512-jakjZi93UtB3jHMWsXL68FXSAosbLfY0In5gtKq3niLSkrWznrVBzXFNOEMJUfc9+Ke7SHWoAZsiMkNP3vq6Jw=="],
|
||||
|
||||
"nopt": ["nopt@6.0.0", "", { "dependencies": { "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g=="],
|
||||
"nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
|
||||
|
||||
"normalize-package-data": ["normalize-package-data@6.0.2", "", { "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g=="],
|
||||
|
||||
@@ -2683,6 +2715,8 @@
|
||||
|
||||
"own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
|
||||
|
||||
"oxlint": ["oxlint@1.78.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.78.0", "@oxlint/binding-android-arm64": "1.78.0", "@oxlint/binding-darwin-arm64": "1.78.0", "@oxlint/binding-darwin-x64": "1.78.0", "@oxlint/binding-freebsd-x64": "1.78.0", "@oxlint/binding-linux-arm-gnueabihf": "1.78.0", "@oxlint/binding-linux-arm-musleabihf": "1.78.0", "@oxlint/binding-linux-arm64-gnu": "1.78.0", "@oxlint/binding-linux-arm64-musl": "1.78.0", "@oxlint/binding-linux-ppc64-gnu": "1.78.0", "@oxlint/binding-linux-riscv64-gnu": "1.78.0", "@oxlint/binding-linux-riscv64-musl": "1.78.0", "@oxlint/binding-linux-s390x-gnu": "1.78.0", "@oxlint/binding-linux-x64-gnu": "1.78.0", "@oxlint/binding-linux-x64-musl": "1.78.0", "@oxlint/binding-openharmony-arm64": "1.78.0", "@oxlint/binding-win32-arm64-msvc": "1.78.0", "@oxlint/binding-win32-ia32-msvc": "1.78.0", "@oxlint/binding-win32-x64-msvc": "1.78.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-QgQePuxIqKOzo1KSjG2EnITEeWvWnKAm77eq8nrMtf6AGoA+zyGc4PFYtDNJSD25g/ibOwfQ851hZ4/SPkMVoA=="],
|
||||
|
||||
"p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
|
||||
|
||||
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
@@ -2759,12 +2793,10 @@
|
||||
|
||||
"pretty-bytes": ["pretty-bytes@6.1.1", "", {}, "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ=="],
|
||||
|
||||
"proc-log": ["proc-log@2.0.1", "", {}, "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw=="],
|
||||
"proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
|
||||
|
||||
"promise-inflight": ["promise-inflight@1.0.1", "", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="],
|
||||
|
||||
"promise-retry": ["promise-retry@2.0.1", "", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="],
|
||||
|
||||
"prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
|
||||
@@ -3015,7 +3047,7 @@
|
||||
|
||||
"socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
|
||||
|
||||
"socks-proxy-agent": ["socks-proxy-agent@7.0.0", "", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="],
|
||||
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
|
||||
|
||||
@@ -3045,7 +3077,7 @@
|
||||
|
||||
"sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="],
|
||||
|
||||
"ssri": ["ssri@9.0.1", "", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="],
|
||||
"ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
|
||||
|
||||
"stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
|
||||
|
||||
@@ -3115,7 +3147,7 @@
|
||||
|
||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||
|
||||
"tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="],
|
||||
"tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="],
|
||||
|
||||
"tar-fs": ["tar-fs@3.1.2", "", { "dependencies": { "pump": "^3.0.0", "tar-stream": "^3.1.5" }, "optionalDependencies": { "bare-fs": "^4.0.1", "bare-path": "^3.0.0" } }, "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw=="],
|
||||
|
||||
@@ -3217,7 +3249,7 @@
|
||||
|
||||
"underscore": ["underscore@1.13.8", "", {}, "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ=="],
|
||||
|
||||
"undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="],
|
||||
"undici": ["undici@6.28.0", "", {}, "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA=="],
|
||||
|
||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
||||
|
||||
@@ -3233,9 +3265,9 @@
|
||||
|
||||
"unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
|
||||
|
||||
"unique-filename": ["unique-filename@2.0.1", "", { "dependencies": { "unique-slug": "^3.0.0" } }, "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A=="],
|
||||
"unique-filename": ["unique-filename@4.0.0", "", { "dependencies": { "unique-slug": "^5.0.0" } }, "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ=="],
|
||||
|
||||
"unique-slug": ["unique-slug@3.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w=="],
|
||||
"unique-slug": ["unique-slug@5.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg=="],
|
||||
|
||||
"unique-string": ["unique-string@2.0.0", "", { "dependencies": { "crypto-random-string": "^2.0.0" } }, "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg=="],
|
||||
|
||||
@@ -3387,7 +3419,7 @@
|
||||
|
||||
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
|
||||
|
||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"yaml": ["yaml@2.8.2", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A=="],
|
||||
|
||||
@@ -3429,19 +3461,17 @@
|
||||
|
||||
"@capacitor/cli/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"@capacitor/cli/tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="],
|
||||
|
||||
"@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="],
|
||||
|
||||
"@electron/asar/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"@electron/fuses/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],
|
||||
|
||||
"@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
|
||||
"@electron/get/env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="],
|
||||
|
||||
"@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
"@electron/get/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"@electron/node-gyp/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="],
|
||||
"@electron/get/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||
|
||||
"@electron/notarize/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],
|
||||
|
||||
@@ -3467,16 +3497,10 @@
|
||||
|
||||
"@ionic/utils-terminal/slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
|
||||
|
||||
"@isaacs/fs-minipass/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="],
|
||||
|
||||
"@npmcli/agent/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"@npmcli/agent/socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"@npmcli/move-file/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
|
||||
"@openchamber/web/cron-parser": ["cron-parser@4.9.0", "", { "dependencies": { "luxon": "^3.2.1" } }, "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q=="],
|
||||
|
||||
"@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
|
||||
@@ -3553,24 +3577,18 @@
|
||||
|
||||
"app-builder-lib/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||
|
||||
"app-builder-lib/tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="],
|
||||
|
||||
"app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
|
||||
|
||||
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"cacache/glob": ["glob@8.1.0", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="],
|
||||
"cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"cacache/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
||||
|
||||
"cacache/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"cacache/p-map": ["p-map@4.0.0", "", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="],
|
||||
|
||||
"cacache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
|
||||
"cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
|
||||
"cheerio/undici": ["undici@7.22.0", "", {}, "sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg=="],
|
||||
|
||||
"chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||
|
||||
"cli-truncate/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
|
||||
@@ -3605,12 +3623,8 @@
|
||||
|
||||
"form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"fs-minipass/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||
|
||||
"glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"globby/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
|
||||
|
||||
"globby/slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="],
|
||||
@@ -3625,13 +3639,11 @@
|
||||
|
||||
"keytar/node-addon-api": ["node-addon-api@4.3.0", "", {}, "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="],
|
||||
|
||||
"make-fetch-happen/http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="],
|
||||
"lru-cache/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"make-fetch-happen/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="],
|
||||
"make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="],
|
||||
|
||||
"make-fetch-happen/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
"make-fetch-happen/proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="],
|
||||
|
||||
"markdown-it/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
@@ -3641,27 +3653,17 @@
|
||||
|
||||
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
|
||||
|
||||
"minipass-collect/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-fetch/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-sized/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minizlib/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
"node-abi/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"node-gyp/make-fetch-happen": ["make-fetch-happen@14.0.3", "", { "dependencies": { "@npmcli/agent": "^3.0.0", "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^5.0.0", "promise-retry": "^2.0.1", "ssri": "^12.0.0" } }, "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ=="],
|
||||
"node-gyp/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"node-gyp/nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="],
|
||||
|
||||
"node-gyp/proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="],
|
||||
|
||||
"node-gyp/tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="],
|
||||
|
||||
"node-gyp/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="],
|
||||
"node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"node-sarif-builder/fs-extra": ["fs-extra@11.3.3", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg=="],
|
||||
|
||||
@@ -3683,10 +3685,10 @@
|
||||
|
||||
"path-scurry/lru-cache": ["lru-cache@11.2.6", "", {}, "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ=="],
|
||||
|
||||
"path-scurry/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"postject/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="],
|
||||
|
||||
"prebuild-install/node-abi": ["node-abi@3.94.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g=="],
|
||||
|
||||
"prebuild-install/tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
|
||||
|
||||
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
|
||||
@@ -3715,16 +3717,12 @@
|
||||
|
||||
"slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="],
|
||||
|
||||
"socks-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"sort-keys/is-plain-obj": ["is-plain-obj@1.1.0", "", {}, "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg=="],
|
||||
|
||||
"source-map/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=="],
|
||||
|
||||
"source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||
|
||||
"ssri/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"superagent/mime": ["mime@2.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="],
|
||||
|
||||
"supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
|
||||
@@ -3733,8 +3731,6 @@
|
||||
|
||||
"table/slice-ansi": ["slice-ansi@4.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ=="],
|
||||
|
||||
"temp/mkdirp": ["mkdirp@0.5.6", "", { "dependencies": { "minimist": "^1.2.6" }, "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="],
|
||||
|
||||
"temp/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="],
|
||||
|
||||
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
|
||||
@@ -3773,24 +3769,8 @@
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||
|
||||
"@capacitor/cli/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"@capacitor/cli/tar/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"@capacitor/cli/tar/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"@capacitor/cli/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||
|
||||
"@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
||||
|
||||
"@electron/node-gyp/glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="],
|
||||
|
||||
"@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"@npmcli/move-file/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
|
||||
"@rollup/plugin-node-resolve/@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
|
||||
|
||||
"@secretlint/config-loader/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
@@ -3807,23 +3787,17 @@
|
||||
|
||||
"app-builder-lib/@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"app-builder-lib/@electron/rebuild/node-abi": ["node-abi@4.28.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-Qfp5XZL1cJDOabOT8H5gnqMTmM4NjvYzHp4I/Kt/Sl76OVkOBBHRFlPspGV0hYvMoqQsypFjT/Yp7Km0beXW9g=="],
|
||||
"app-builder-lib/@electron/rebuild/node-gyp": ["node-gyp@11.5.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^14.0.3", "nopt": "^8.0.0", "proc-log": "^5.0.0", "semver": "^7.3.5", "tar": "^7.4.3", "tinyglobby": "^0.2.12", "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-ra7Kvlhxn5V9Slyus0ygMa2h+UqExPqUIkfk7Pc8QTLT956JLSy51uWFwHtIYy0vI8cB4BDhc/S03+880My/LQ=="],
|
||||
|
||||
"app-builder-lib/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||
|
||||
"app-builder-lib/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"app-builder-lib/tar/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"app-builder-lib/tar/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"app-builder-lib/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"app-builder-lib/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
||||
|
||||
"cacache/glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="],
|
||||
"cacache/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"cacache/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
|
||||
"cacache/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"cacache/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"cli-truncate/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
|
||||
|
||||
@@ -3843,33 +3817,15 @@
|
||||
|
||||
"iconv-corefoundation/cli-truncate/slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="],
|
||||
|
||||
"make-fetch-happen/http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"make-fetch-happen/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="],
|
||||
|
||||
"micromark-extension-math/katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache": ["cacache@19.0.1", "", { "dependencies": { "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^12.0.0", "tar": "^7.4.3", "unique-filename": "^4.0.0" } }, "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ=="],
|
||||
"minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
"minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/minipass-fetch": ["minipass-fetch@4.0.1", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", "minizlib": "^3.0.1" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-j7U11C5HXigVuutxebFadoYBbd7VSdZWggSe64NVdvWNBqGAiXPL2QVCehjmw7lY1oF9gOllYbORh+hiNgfPgQ=="],
|
||||
"minipass-sized/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/ssri": ["ssri@12.0.0", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ=="],
|
||||
|
||||
"node-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="],
|
||||
|
||||
"node-gyp/tar/chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"node-gyp/tar/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"node-gyp/tar/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"node-gyp/tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"node-gyp/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="],
|
||||
"node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"nodemon/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||
|
||||
@@ -3879,6 +3835,8 @@
|
||||
|
||||
"openai/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
|
||||
"prebuild-install/node-abi/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"prebuild-install/tar-fs/chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
|
||||
|
||||
"prebuild-install/tar-fs/tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
|
||||
@@ -3895,8 +3853,6 @@
|
||||
|
||||
"rimraf/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
|
||||
|
||||
"rimraf/glob/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"source-map/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="],
|
||||
|
||||
"source-map/whatwg-url/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
|
||||
@@ -4011,36 +3967,26 @@
|
||||
|
||||
"workbox-build/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"@electron/node-gyp/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"app-builder-lib/@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
|
||||
|
||||
"app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
||||
|
||||
"app-builder-lib/@electron/rebuild/node-gyp/nopt": ["nopt@8.1.0", "", { "dependencies": { "abbrev": "^3.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A=="],
|
||||
|
||||
"app-builder-lib/@electron/rebuild/node-gyp/proc-log": ["proc-log@5.0.0", "", {}, "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ=="],
|
||||
|
||||
"app-builder-lib/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"cacache/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
|
||||
"cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/@npmcli/fs": ["@npmcli/fs@4.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/unique-filename": ["unique-filename@4.0.0", "", { "dependencies": { "unique-slug": "^5.0.0" } }, "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/minipass-fetch/minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"nodemon/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"qrcode/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
|
||||
@@ -4049,34 +3995,24 @@
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
"app-builder-lib/@electron/rebuild/node-gyp/nopt/abbrev": ["abbrev@3.0.1", "", {}, "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/unique-filename/unique-slug": ["unique-slug@5.0.0", "", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg=="],
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"qrcode/yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"qrcode/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
|
||||
|
||||
"node-gyp/make-fetch-happen/cacache/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,948 +0,0 @@
|
||||
# Pairing v2 Trusted-Device Issuance Backend Plan
|
||||
|
||||
## Scope
|
||||
|
||||
Implement the Pairing v2 mechanism without UI.
|
||||
|
||||
Included:
|
||||
|
||||
- Backend pairing session runtime.
|
||||
- Pairing create/redeem/cancel routes.
|
||||
- Trusted-device token issuance through the existing remote client auth runtime.
|
||||
- Backward-compatible remote client metadata extension.
|
||||
- Password/passkey issuance metadata alignment.
|
||||
- Shared v2 `openchamber://connect` payload helpers.
|
||||
|
||||
Not included:
|
||||
|
||||
- Settings page.
|
||||
- QR modal.
|
||||
- Pair Device button.
|
||||
- Device list UI.
|
||||
- Translations/copy.
|
||||
- Relay implementation.
|
||||
- LAN discovery.
|
||||
- End-user polished mobile/desktop screens.
|
||||
|
||||
## Naming
|
||||
|
||||
Use the existing `client-auth` domain.
|
||||
|
||||
New module:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/pairing.js
|
||||
```
|
||||
|
||||
Existing durable token module remains:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/remote-clients.js
|
||||
```
|
||||
|
||||
Conceptual names:
|
||||
|
||||
```text
|
||||
Remote client
|
||||
Trusted-device client token
|
||||
Pairing session
|
||||
Pairing secret
|
||||
Pairing redeem
|
||||
```
|
||||
|
||||
Deep link stays:
|
||||
|
||||
```text
|
||||
openchamber://connect
|
||||
```
|
||||
|
||||
Versions:
|
||||
|
||||
```text
|
||||
v=1 => legacy server + long-lived token import
|
||||
v=2 => one-time pairing handshake
|
||||
```
|
||||
|
||||
## New Files
|
||||
|
||||
### 1. `packages/web/server/lib/client-auth/pairing.js`
|
||||
|
||||
Create a new backend runtime module for short-lived pairing sessions.
|
||||
|
||||
Responsibilities:
|
||||
|
||||
```text
|
||||
createPairingSession
|
||||
getPairingSession
|
||||
cancelPairingSession
|
||||
redeemPairingSession
|
||||
sweepExpiredSessions
|
||||
```
|
||||
|
||||
Store file:
|
||||
|
||||
```text
|
||||
OPENCHAMBER_DATA_DIR/client-pairing-sessions.json
|
||||
```
|
||||
|
||||
Suggested store shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"sessions": [
|
||||
{
|
||||
"id": "pair_...",
|
||||
"secretHash": "...",
|
||||
"createdAt": "...",
|
||||
"expiresAt": "...",
|
||||
"usedAt": null,
|
||||
"cancelledAt": null,
|
||||
"clientId": null,
|
||||
"label": "Pair new device",
|
||||
"fingerprint": "ABCD-1234",
|
||||
"allowedClientKinds": ["mobile", "desktop"],
|
||||
"createdByClientId": null
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Security requirements:
|
||||
|
||||
```text
|
||||
Persist only secretHash.
|
||||
Return plaintext secret only from createPairingSession.
|
||||
Redeem is one-time.
|
||||
Redeem is expiry-aware.
|
||||
Redeem is cancellation-aware.
|
||||
Redeem must be mutation-serialized to avoid double issuance.
|
||||
No raw token/secret logging.
|
||||
```
|
||||
|
||||
Public methods should accept injected dependencies, following `remote-clients.js` style:
|
||||
|
||||
```js
|
||||
createClientPairingRuntime({
|
||||
fsPromises,
|
||||
path,
|
||||
crypto,
|
||||
storePath,
|
||||
remoteClientAuthRuntime,
|
||||
})
|
||||
```
|
||||
|
||||
## Existing Files To Update
|
||||
|
||||
### 2. `packages/web/server/lib/client-auth/remote-clients.js`
|
||||
|
||||
Extend trusted-device metadata backward-compatibly.
|
||||
|
||||
Current `createClient` input:
|
||||
|
||||
```js
|
||||
{
|
||||
label,
|
||||
expiresAt,
|
||||
clientKind,
|
||||
dedupeKey,
|
||||
}
|
||||
```
|
||||
|
||||
Extend to:
|
||||
|
||||
```js
|
||||
{
|
||||
label,
|
||||
expiresAt,
|
||||
clientKind,
|
||||
dedupeKey,
|
||||
authMethod,
|
||||
pairingId,
|
||||
deviceName,
|
||||
devicePlatform,
|
||||
deviceModel,
|
||||
appVersion,
|
||||
}
|
||||
```
|
||||
|
||||
Add normalized public fields:
|
||||
|
||||
```text
|
||||
authMethod
|
||||
pairingId
|
||||
deviceName
|
||||
devicePlatform
|
||||
deviceModel
|
||||
appVersion
|
||||
```
|
||||
|
||||
Backward compatibility rules:
|
||||
|
||||
```text
|
||||
Existing remote-clients.json remains valid.
|
||||
Missing new fields normalize to null.
|
||||
Existing tokens continue authenticating.
|
||||
Public client output never exposes tokenHash.
|
||||
Raw token is returned only from createClient.
|
||||
```
|
||||
|
||||
Recommended `authMethod` values:
|
||||
|
||||
```text
|
||||
pairing
|
||||
password
|
||||
passkey
|
||||
desktop-local
|
||||
manual
|
||||
legacy
|
||||
```
|
||||
|
||||
Do not force migration for old records. Treat missing `authMethod` as legacy/null.
|
||||
|
||||
### 3. `packages/web/server/index.js`
|
||||
|
||||
Instantiate the new pairing runtime next to `remoteClientAuthRuntime`.
|
||||
|
||||
Existing:
|
||||
|
||||
```js
|
||||
const remoteClientAuthRuntime = createRemoteClientAuthRuntime({
|
||||
fsPromises,
|
||||
path,
|
||||
crypto,
|
||||
storePath: REMOTE_CLIENTS_FILE_PATH,
|
||||
});
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```js
|
||||
const CLIENT_PAIRING_SESSIONS_FILE_PATH = path.join(
|
||||
OPENCHAMBER_DATA_DIR,
|
||||
'client-pairing-sessions.json',
|
||||
);
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```js
|
||||
const clientPairingRuntime = createClientPairingRuntime({
|
||||
fsPromises,
|
||||
path,
|
||||
crypto,
|
||||
storePath: CLIENT_PAIRING_SESSIONS_FILE_PATH,
|
||||
remoteClientAuthRuntime,
|
||||
});
|
||||
```
|
||||
|
||||
Pass `clientPairingRuntime` into `registerAuthAndAccessRoutes` dependencies.
|
||||
|
||||
### 4. `packages/web/server/lib/opencode/core-routes.js`
|
||||
|
||||
Add pairing routes near existing client-auth routes:
|
||||
|
||||
```text
|
||||
/api/client-auth/clients
|
||||
```
|
||||
|
||||
Add:
|
||||
|
||||
```http
|
||||
POST /api/client-auth/pairing/sessions
|
||||
DELETE /api/client-auth/pairing/sessions/:id
|
||||
POST /api/client-auth/pairing/redeem
|
||||
```
|
||||
|
||||
Optional, can be deferred:
|
||||
|
||||
```http
|
||||
GET /api/client-auth/pairing/sessions/:id
|
||||
```
|
||||
|
||||
Since UI polling is out of scope, `GET` is not required for this phase.
|
||||
|
||||
#### Route: `POST /api/client-auth/pairing/sessions`
|
||||
|
||||
Purpose:
|
||||
|
||||
```text
|
||||
Create one short-lived pairing session and return data needed to build QR/deep link.
|
||||
```
|
||||
|
||||
Auth:
|
||||
|
||||
```text
|
||||
Require UI session auth.
|
||||
Allow desktop-local client only if consistent with existing client-create exception.
|
||||
Reject arbitrary remote client tokens.
|
||||
Reject url-token auth.
|
||||
```
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"label": "Pair new device",
|
||||
"allowedClientKinds": ["mobile", "desktop"]
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"pairing": {
|
||||
"id": "pair_...",
|
||||
"secret": "one_time_secret",
|
||||
"expiresAt": "...",
|
||||
"fingerprint": "ABCD-1234",
|
||||
"label": "Pair new device"
|
||||
},
|
||||
"server": {
|
||||
"label": "OpenChamber",
|
||||
"candidates": [
|
||||
{
|
||||
"type": "lan",
|
||||
"url": "http://192.168.1.20:4096",
|
||||
"priority": 10
|
||||
},
|
||||
{
|
||||
"type": "tunnel",
|
||||
"url": "https://abc.ngrok.app",
|
||||
"priority": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Headers:
|
||||
|
||||
```http
|
||||
Cache-Control: no-store
|
||||
```
|
||||
|
||||
Note:
|
||||
|
||||
```text
|
||||
This route does not render QR.
|
||||
UI can later encode the returned data into openchamber://connect?v=2&p=...
|
||||
```
|
||||
|
||||
#### Route: `DELETE /api/client-auth/pairing/sessions/:id`
|
||||
|
||||
Purpose:
|
||||
|
||||
```text
|
||||
Cancel an unused pairing session.
|
||||
```
|
||||
|
||||
Auth:
|
||||
|
||||
```text
|
||||
Require owner/session auth.
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
```text
|
||||
Set cancelledAt.
|
||||
Do not delete immediately.
|
||||
If already used, cancellation should not revoke the issued client.
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"cancelled": true
|
||||
}
|
||||
```
|
||||
|
||||
#### Route: `POST /api/client-auth/pairing/redeem`
|
||||
|
||||
Purpose:
|
||||
|
||||
```text
|
||||
Exchange pairingId + one-time secret for a trusted-device client token.
|
||||
```
|
||||
|
||||
Auth:
|
||||
|
||||
```text
|
||||
No existing auth required.
|
||||
The one-time pairing secret is the authentication factor.
|
||||
```
|
||||
|
||||
Request:
|
||||
|
||||
```json
|
||||
{
|
||||
"pairingId": "pair_...",
|
||||
"secret": "one_time_secret",
|
||||
"clientLabel": "Iryna iPhone",
|
||||
"clientKind": "mobile",
|
||||
"deviceName": "Iryna iPhone",
|
||||
"devicePlatform": "ios",
|
||||
"deviceModel": "iPhone",
|
||||
"appVersion": "1.12.0",
|
||||
"dedupeKey": "optional-stable-device-key"
|
||||
}
|
||||
```
|
||||
|
||||
Server behavior:
|
||||
|
||||
```text
|
||||
Validate pairing exists.
|
||||
Validate secret using constant-time comparison.
|
||||
Validate not expired.
|
||||
Validate not cancelled.
|
||||
Validate not used.
|
||||
Validate clientKind is allowed.
|
||||
Mark pairing used.
|
||||
Create remote client through remoteClientAuthRuntime.createClient.
|
||||
Return clientToken once.
|
||||
```
|
||||
|
||||
Create client with:
|
||||
|
||||
```js
|
||||
{
|
||||
label: clientLabel || deviceName || 'Remote client',
|
||||
clientKind,
|
||||
dedupeKey,
|
||||
authMethod: 'pairing',
|
||||
pairingId,
|
||||
deviceName,
|
||||
devicePlatform,
|
||||
deviceModel,
|
||||
appVersion,
|
||||
}
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"server": {
|
||||
"label": "OpenChamber",
|
||||
"url": "https://selected-or-current-url",
|
||||
"fingerprint": "ABCD-1234"
|
||||
},
|
||||
"client": {
|
||||
"id": "device_...",
|
||||
"label": "Iryna iPhone",
|
||||
"clientKind": "mobile",
|
||||
"authMethod": "pairing",
|
||||
"createdAt": "..."
|
||||
},
|
||||
"clientToken": "oc_client_..."
|
||||
}
|
||||
```
|
||||
|
||||
Headers:
|
||||
|
||||
```http
|
||||
Cache-Control: no-store
|
||||
```
|
||||
|
||||
Failure response should be generic:
|
||||
|
||||
```json
|
||||
{
|
||||
"error": "Invalid or expired pairing session"
|
||||
}
|
||||
```
|
||||
|
||||
Do not reveal whether id, secret, expiry, used, or cancellation caused failure.
|
||||
|
||||
### 5. `packages/web/server/lib/ui-auth/ui-auth.js`
|
||||
|
||||
Preserve existing password/passkey behavior.
|
||||
|
||||
Only add metadata to client token issuance when `issueClientToken === true`.
|
||||
|
||||
Password issuance should pass:
|
||||
|
||||
```js
|
||||
authMethod: 'password'
|
||||
clientKind: req.body?.clientKind
|
||||
dedupeKey: req.body?.dedupeKey
|
||||
deviceName: req.body?.deviceName
|
||||
devicePlatform: req.body?.devicePlatform
|
||||
deviceModel: req.body?.deviceModel
|
||||
appVersion: req.body?.appVersion
|
||||
```
|
||||
|
||||
Passkey issuance should pass:
|
||||
|
||||
```js
|
||||
authMethod: 'passkey'
|
||||
clientKind: req.body?.clientKind
|
||||
dedupeKey: req.body?.dedupeKey
|
||||
deviceName: req.body?.deviceName
|
||||
devicePlatform: req.body?.devicePlatform
|
||||
deviceModel: req.body?.deviceModel
|
||||
appVersion: req.body?.appVersion
|
||||
```
|
||||
|
||||
Backward compatibility:
|
||||
|
||||
```text
|
||||
Existing POST /auth/session payload still works.
|
||||
Existing response shape still works.
|
||||
Existing clientToken issuance still works.
|
||||
Password login remains disabled for tunnel/public scope.
|
||||
```
|
||||
|
||||
### 6. `packages/ui/src/lib/connectionPayload.ts`
|
||||
|
||||
Extend existing connect payload helpers.
|
||||
|
||||
Keep current v1 behavior:
|
||||
|
||||
```text
|
||||
openchamber://connect?v=1&server=...&token=...&label=...
|
||||
```
|
||||
|
||||
Add v2 payload types and helpers.
|
||||
|
||||
Suggested types:
|
||||
|
||||
```ts
|
||||
export type ClientConnectionPayloadV1 = {
|
||||
v: 1;
|
||||
serverUrl: string;
|
||||
token: string;
|
||||
label?: string;
|
||||
};
|
||||
|
||||
export type PairingEndpointCandidate = {
|
||||
type: 'lan' | 'tunnel' | 'relay';
|
||||
url: string;
|
||||
priority?: number;
|
||||
};
|
||||
|
||||
export type PairingConnectionPayloadV2 = {
|
||||
v: 2;
|
||||
pairingId: string;
|
||||
secret: string;
|
||||
label?: string;
|
||||
fingerprint?: string;
|
||||
expiresAt?: string;
|
||||
candidates: PairingEndpointCandidate[];
|
||||
};
|
||||
```
|
||||
|
||||
Suggested helpers:
|
||||
|
||||
```ts
|
||||
encodePairingConnectionPayload(payload: PairingConnectionPayloadV2): string
|
||||
parsePairingConnectionPayload(value: string): PairingConnectionPayloadV2 | null
|
||||
```
|
||||
|
||||
Use deep link format:
|
||||
|
||||
```text
|
||||
openchamber://connect?v=2&p=<base64url-json>
|
||||
```
|
||||
|
||||
Validation:
|
||||
|
||||
```text
|
||||
Require v=2.
|
||||
Require pairingId.
|
||||
Require secret.
|
||||
Require at least one valid http/https candidate.
|
||||
Reject malformed URL.
|
||||
Reject oversized payload.
|
||||
Reject expired payload locally if expiresAt is clearly in the past.
|
||||
```
|
||||
|
||||
Do not break current exports used by mobile QR/manual connect.
|
||||
|
||||
### 7. `packages/ui/src/apps/mobileQrScan.ts`
|
||||
|
||||
Update parser only.
|
||||
|
||||
Current scan parser recognizes legacy fields like:
|
||||
|
||||
```text
|
||||
server
|
||||
label
|
||||
```
|
||||
|
||||
Add support for v2 connect links.
|
||||
|
||||
Output should be able to distinguish:
|
||||
|
||||
```text
|
||||
legacy v1 token import
|
||||
pairing v2 payload
|
||||
plain URL
|
||||
```
|
||||
|
||||
Do not implement full mobile UI flow in this scope unless there is already a non-UI callable path.
|
||||
|
||||
### 8. `packages/ui/src/apps/mobileConnections.ts`
|
||||
|
||||
Add non-visual callable mechanism for redeeming pairing payload.
|
||||
|
||||
Add a function conceptually like:
|
||||
|
||||
```ts
|
||||
redeemPairingConnection(payload: PairingConnectionPayloadV2): Promise<void>
|
||||
```
|
||||
|
||||
Responsibilities:
|
||||
|
||||
```text
|
||||
Try endpoint candidates.
|
||||
POST /api/client-auth/pairing/redeem.
|
||||
Persist issued token securely.
|
||||
Persist connection metadata.
|
||||
Switch runtime only after token write succeeds.
|
||||
```
|
||||
|
||||
No new screens/buttons.
|
||||
|
||||
Existing password flow remains unchanged.
|
||||
|
||||
Candidate selection:
|
||||
|
||||
```text
|
||||
Normalize candidates.
|
||||
Probe /health with timeout.
|
||||
Try candidates by priority.
|
||||
Prefer HTTPS when priority ties.
|
||||
If network failure, try next candidate.
|
||||
If server says invalid/expired/used, stop.
|
||||
```
|
||||
|
||||
Mobile native should reuse existing native HTTP fallback path for LAN HTTP.
|
||||
|
||||
### 9. `packages/electron/main.mjs`
|
||||
|
||||
Extend existing connect deep-link handling.
|
||||
|
||||
Current v1 behavior:
|
||||
|
||||
```text
|
||||
openchamber://connect?v=1&server=...&token=...
|
||||
```
|
||||
|
||||
Keep it.
|
||||
|
||||
Add v2 branch:
|
||||
|
||||
```text
|
||||
openchamber://connect?v=2&p=...
|
||||
```
|
||||
|
||||
Behavior:
|
||||
|
||||
```text
|
||||
Parse v2 payload.
|
||||
Show confirmation before redeem/write/switch.
|
||||
Probe candidates.
|
||||
Redeem pairing secret.
|
||||
Store returned clientToken in desktop hosts config.
|
||||
Ask/switch according to existing remote host behavior.
|
||||
Never show token.
|
||||
Never write config before confirmation.
|
||||
```
|
||||
|
||||
If this phase is strictly backend-only, this file can be deferred. But if desktop app as client must be functionally supported by deep link in this phase, include this change.
|
||||
|
||||
### 10. `packages/electron/preload.mjs`
|
||||
|
||||
No change expected unless a renderer-side desktop API is needed for pairing redeem.
|
||||
|
||||
Prefer keeping pairing redeem in main process only for deep-link handling if desktop v2 is implemented there.
|
||||
|
||||
### 11. `packages/web/server/lib/ui-auth/DOCUMENTATION.md`
|
||||
|
||||
Update module documentation to reflect the unified issuance model:
|
||||
|
||||
```text
|
||||
Password, passkey, and pairing are issuance methods.
|
||||
Trusted-device client token is the durable credential.
|
||||
Pairing v2 uses one-time secrets and issues remote client tokens.
|
||||
```
|
||||
|
||||
Optionally add:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/DOCUMENTATION.md
|
||||
```
|
||||
|
||||
if the client-auth module needs ownership docs.
|
||||
|
||||
## Route Registration Summary
|
||||
|
||||
Add to `registerAuthAndAccessRoutes`:
|
||||
|
||||
```http
|
||||
POST /api/client-auth/pairing/sessions
|
||||
DELETE /api/client-auth/pairing/sessions/:id
|
||||
POST /api/client-auth/pairing/redeem
|
||||
```
|
||||
|
||||
Optional later:
|
||||
|
||||
```http
|
||||
GET /api/client-auth/pairing/sessions/:id
|
||||
```
|
||||
|
||||
Route placement:
|
||||
|
||||
```text
|
||||
Register before generic OpenCode proxy.
|
||||
Place near existing /api/client-auth/clients routes.
|
||||
```
|
||||
|
||||
## Execution Sequence
|
||||
|
||||
### Step 1: Extend Remote Client Metadata
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/remote-clients.js
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Add metadata normalization.
|
||||
Extend createClient input.
|
||||
Extend publicClient output.
|
||||
Keep old records valid.
|
||||
Do not change token generation/authentication behavior.
|
||||
```
|
||||
|
||||
### Step 2: Add Password/Passkey Metadata Issuance
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/ui-auth/ui-auth.js
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
When issueClientToken is true, pass authMethod='password' from password login.
|
||||
When issueClientToken is true, pass authMethod='passkey' from passkey auth.
|
||||
Pass optional device metadata through.
|
||||
Preserve response shape.
|
||||
```
|
||||
|
||||
### Step 3: Create Pairing Runtime Module
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/pairing.js
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Implement session creation.
|
||||
Implement hashed secret storage.
|
||||
Implement cancel.
|
||||
Implement redeem.
|
||||
Implement expiry/used/cancelled checks.
|
||||
Integrate remoteClientAuthRuntime.createClient in redeem.
|
||||
```
|
||||
|
||||
### Step 4: Instantiate Pairing Runtime
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/index.js
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Define CLIENT_PAIRING_SESSIONS_FILE_PATH.
|
||||
Instantiate createClientPairingRuntime.
|
||||
Pass clientPairingRuntime to registerAuthAndAccessRoutes.
|
||||
```
|
||||
|
||||
### Step 5: Add Pairing Routes
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/opencode/core-routes.js
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Destructure clientPairingRuntime from dependencies.
|
||||
Add POST /api/client-auth/pairing/sessions.
|
||||
Add DELETE /api/client-auth/pairing/sessions/:id.
|
||||
Add POST /api/client-auth/pairing/redeem.
|
||||
Use correct auth gates.
|
||||
Set Cache-Control: no-store where secrets/tokens are returned.
|
||||
Keep error responses generic for redeem.
|
||||
```
|
||||
|
||||
### Step 6: Add v2 Payload Helpers
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/ui/src/lib/connectionPayload.ts
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Keep v1 helpers unchanged.
|
||||
Add v2 payload type.
|
||||
Add encode v2 helper.
|
||||
Add parse v2 helper.
|
||||
Use openchamber://connect?v=2&p=<base64url-json>.
|
||||
Validate candidates.
|
||||
Reject malformed/expired/oversized payloads.
|
||||
```
|
||||
|
||||
### Step 7: Update QR Scan Parser Shape
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/ui/src/apps/mobileQrScan.ts
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Recognize v2 connect payload.
|
||||
Return structured v2 result.
|
||||
Do not add new UI.
|
||||
Do not break v1/manual URL behavior.
|
||||
```
|
||||
|
||||
### Step 8: Add Non-UI Mobile Redeem Plumbing
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/ui/src/apps/mobileConnections.ts
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Add callable redeem pairing function.
|
||||
Try endpoint candidates.
|
||||
Redeem via /api/client-auth/pairing/redeem.
|
||||
Persist token before runtime switch.
|
||||
Reuse existing storage model.
|
||||
Keep password/manual connect unchanged.
|
||||
```
|
||||
|
||||
### Step 9: Add Desktop Deep-Link v2 Handling If In Scope
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/electron/main.mjs
|
||||
```
|
||||
|
||||
Do:
|
||||
|
||||
```text
|
||||
Extend connect deep-link parser to recognize v2.
|
||||
Confirm before redeem.
|
||||
Redeem against candidate endpoint.
|
||||
Store remote host config with returned token.
|
||||
Switch only after confirmation and successful storage.
|
||||
Keep v1 behavior unchanged.
|
||||
```
|
||||
|
||||
If desktop client deep-link support is deferred, skip this step and document that v2 backend/shared payload exists but desktop consumer is not wired yet.
|
||||
|
||||
### Step 10: Update Documentation
|
||||
|
||||
Files:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/ui-auth/DOCUMENTATION.md
|
||||
```
|
||||
|
||||
Optionally add:
|
||||
|
||||
```text
|
||||
packages/web/server/lib/client-auth/DOCUMENTATION.md
|
||||
```
|
||||
|
||||
Document:
|
||||
|
||||
```text
|
||||
Unified trusted-device token issuance.
|
||||
Pairing v2 flow.
|
||||
Password/passkey/pairing authMethod values.
|
||||
Security rules.
|
||||
Backward compatibility guarantees.
|
||||
```
|
||||
|
||||
## Important Non-Goals
|
||||
|
||||
Do not implement:
|
||||
|
||||
```text
|
||||
Settings page
|
||||
Pair Device button
|
||||
QR modal
|
||||
Device list UI
|
||||
Translations
|
||||
Visual design
|
||||
Relay transport
|
||||
LAN discovery
|
||||
Account/cloud sync
|
||||
Token migration to OS keychain on desktop
|
||||
```
|
||||
|
||||
## Backward Compatibility Requirements
|
||||
|
||||
Must remain true:
|
||||
|
||||
```text
|
||||
Existing v1 openchamber://connect links keep working.
|
||||
Existing password login with issueClientToken keeps working.
|
||||
Existing passkey issueClientToken keeps working.
|
||||
Existing remote-clients.json keeps loading.
|
||||
Existing client tokens keep authenticating.
|
||||
Existing mobile saved connections keep working.
|
||||
Existing desktop remote hosts keep working.
|
||||
```
|
||||
|
||||
## Security Requirements
|
||||
|
||||
Must hold:
|
||||
|
||||
```text
|
||||
No long-lived token in v2 link.
|
||||
Pairing secret persisted only as hash.
|
||||
Pairing secret returned only once.
|
||||
Client token returned only once.
|
||||
Token hash persisted server-side.
|
||||
Redeem is one-time.
|
||||
Redeem is expiry-aware.
|
||||
Redeem is cancellation-aware.
|
||||
Redeem errors are generic.
|
||||
Password login remains disabled for tunnel/public scope.
|
||||
Pairing session creation requires owner/session auth.
|
||||
Pairing redeem requires no prior auth but requires valid one-time secret.
|
||||
Desktop v2 connect confirms before writing host config or switching runtime.
|
||||
```
|
||||
@@ -0,0 +1,47 @@
|
||||
import { defineConfig } from "oxlint";
|
||||
|
||||
// Oxlint here runs only the vendored anti-slop plugin; ESLint remains the
|
||||
// general-purpose linter for this repository.
|
||||
export default defineConfig({
|
||||
categories: {
|
||||
correctness: "off",
|
||||
},
|
||||
ignorePatterns: [
|
||||
"**/node_modules/**",
|
||||
"**/dist/**",
|
||||
"**/build/**",
|
||||
"**/out/**",
|
||||
"**/.next/**",
|
||||
"**/ios/**",
|
||||
"**/android/**",
|
||||
".agents/**",
|
||||
".claude/**",
|
||||
".conductor/**",
|
||||
".opencode/**",
|
||||
".openchamber/**",
|
||||
".tmp/**",
|
||||
"patches/**",
|
||||
"bun-patches/**",
|
||||
"tools/oxlint/anti-slop/**",
|
||||
],
|
||||
jsPlugins: [
|
||||
{ name: "anti-slop", specifier: "./tools/oxlint/anti-slop/index.ts" },
|
||||
],
|
||||
rules: {
|
||||
"anti-slop/no-chained-type-assertions": "error",
|
||||
"anti-slop/no-conditional-empty-object-spread": "error",
|
||||
"anti-slop/no-known-value-widening": "error",
|
||||
"anti-slop/no-module-mocking": "error",
|
||||
"anti-slop/no-object-parameters": "error",
|
||||
"anti-slop/no-reflect-apply": "error",
|
||||
"anti-slop/no-reflect-get": "error",
|
||||
"anti-slop/no-runtime-typeof": "error",
|
||||
"anti-slop/no-shape-in-symbol-names": "error",
|
||||
"anti-slop/no-unknown-parameters": "error",
|
||||
"anti-slop/no-unknown-returns": "error",
|
||||
"anti-slop/no-unknown-type-aliases": "error",
|
||||
"anti-slop/no-unsafe-dictionary-type": "error",
|
||||
"anti-slop/no-widen-then-assert": "error",
|
||||
"anti-slop/require-safety-comment-for-type-assertion": "error",
|
||||
},
|
||||
});
|
||||
+31
-16
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openchamber-monorepo",
|
||||
"version": "1.18.1",
|
||||
"version": "1.20.0",
|
||||
"description": "OpenChamber monorepo workspace for web, ui, and desktop runtimes",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -38,6 +38,8 @@
|
||||
"lint:ui": "bun run --cwd packages/ui lint",
|
||||
"lint:electron": "bun run --cwd packages/electron lint",
|
||||
"lint:mobile": "bun run --cwd packages/mobile lint",
|
||||
"lint:anti-slop": "oxlint",
|
||||
"test": "node scripts/run-isolated-tests.mjs scripts && bun run --cwd packages/ui test && bun run --cwd packages/vscode test && bun run --cwd packages/electron test && bun run --cwd packages/web test",
|
||||
"clean": "bun run --filter '*' clean",
|
||||
"changelog-card": "node scripts/changelog-card/generate.mjs",
|
||||
"postinstall": "node ./fix-deprecation.js && patch-package && node ./packages/electron/scripts/ensure-electron.mjs --best-effort",
|
||||
@@ -73,6 +75,7 @@
|
||||
"docs:validate": "node scripts/docs/validate-docs.mjs",
|
||||
"dead-code": "bunx knip@5.80.0 --no-exit-code --include files,exports,nsExports,types,nsTypes,enumMembers,duplicates",
|
||||
"doctor": "node scripts/react-doctor.mjs",
|
||||
"deslop": "node scripts/anti-slop.mjs",
|
||||
"profile:browser": "node scripts/profile-browser.mjs",
|
||||
"icons:sprite": "node scripts/generate-file-type-sprite.mjs",
|
||||
"icons:generate": "bun run scripts/generate-icon-sprite.mjs",
|
||||
@@ -88,31 +91,31 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.4.0",
|
||||
"@codemirror/autocomplete": "^6.20.0",
|
||||
"@codemirror/commands": "^6.10.1",
|
||||
"@codemirror/autocomplete": "^6.20.3",
|
||||
"@codemirror/commands": "^6.11.0",
|
||||
"@codemirror/lang-cpp": "^6.0.3",
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-go": "^6.0.1",
|
||||
"@codemirror/lang-html": "^6.4.11",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-html": "^6.4.12",
|
||||
"@codemirror/lang-javascript": "^6.2.5",
|
||||
"@codemirror/lang-json": "^6.0.2",
|
||||
"@codemirror/lang-markdown": "^6.5.0",
|
||||
"@codemirror/lang-markdown": "^6.5.2",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-rust": "^6.0.2",
|
||||
"@codemirror/lang-sql": "^6.10.0",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/lang-yaml": "^6.1.2",
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/lint": "^6.9.2",
|
||||
"@codemirror/search": "^6.6.0",
|
||||
"@codemirror/state": "^6.5.4",
|
||||
"@codemirror/view": "6.39.13",
|
||||
"@codemirror/lang-yaml": "^6.1.3",
|
||||
"@codemirror/language": "6.12.4",
|
||||
"@codemirror/lint": "^6.9.7",
|
||||
"@codemirror/search": "^6.7.1",
|
||||
"@codemirror/state": "^6.7.1",
|
||||
"@codemirror/view": "6.43.9",
|
||||
"@heroui/scroll-shadow": "^2.3.18",
|
||||
"@heroui/system": "^2.4.23",
|
||||
"@heroui/theme": "^2.4.23",
|
||||
"@lezer/highlight": "^1.2.3",
|
||||
"@octokit/rest": "^22.0.1",
|
||||
"@opencode-ai/sdk": "1.18.12",
|
||||
"@opencode-ai/sdk": "1.18.21",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||
@@ -145,12 +148,24 @@
|
||||
"zustand": "^5.0.8"
|
||||
},
|
||||
"overrides": {
|
||||
"@codemirror/language": "6.12.2",
|
||||
"@codemirror/view": "6.39.13"
|
||||
"@codemirror/autocomplete": "6.20.3",
|
||||
"@codemirror/commands": "6.11.0",
|
||||
"@codemirror/lang-html": "6.4.12",
|
||||
"@codemirror/lang-javascript": "6.2.5",
|
||||
"@codemirror/lang-markdown": "6.5.2",
|
||||
"@codemirror/lang-yaml": "6.1.3",
|
||||
"@codemirror/language": "6.12.4",
|
||||
"@codemirror/legacy-modes": "6.5.3",
|
||||
"@codemirror/lint": "6.9.7",
|
||||
"@codemirror/search": "6.7.1",
|
||||
"@codemirror/state": "6.7.1",
|
||||
"@codemirror/view": "6.43.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@clack/prompts": "^1.1.0",
|
||||
"@eslint/js": "^9.33.0",
|
||||
"@oxlint/plugins": "1.78.0",
|
||||
"@remixicon/react": "^4.7.0",
|
||||
"@tailwindcss/postcss": "^4.0.0",
|
||||
"@types/dom-speech-recognition": "^0.0.12",
|
||||
"@types/node": "^24.3.1",
|
||||
@@ -168,8 +183,8 @@
|
||||
"globals": "^16.3.0",
|
||||
"node-addon-api": "7.1.1",
|
||||
"nodemon": "^3.1.7",
|
||||
"oxlint": "1.78.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"@remixicon/react": "^4.7.0",
|
||||
"sharp": "^0.35.0",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"tsx": "^4.20.6",
|
||||
|
||||
@@ -28,7 +28,7 @@ The tool can list projects and model preferences, create and follow up on sessio
|
||||
|
||||
## Turn the tool on or off
|
||||
|
||||
Open **Settings → General → OpenCode CLI**, change **Agent control tool**, then select **Save + Reload**. The setting applies after the managed OpenCode server restarts.
|
||||
Open **Settings → General → OpenChamber Tools** and change **Agent control tool**. The setting applies once the managed OpenCode server restarts, which OpenChamber offers as **Apply & Restart**.
|
||||
|
||||
The tool is not available when OpenChamber connects to an external OpenCode server through `OPENCODE_HOST` or skip-start, or inside the VS Code extension. Desktop and web installations that use OpenChamber's managed OpenCode server support it automatically.
|
||||
|
||||
@@ -37,3 +37,4 @@ The tool is not available when OpenChamber connects to an external OpenCode serv
|
||||
- [Scheduled Tasks](/scheduled-tasks/)
|
||||
- [Worktree Sessions](/worktrees/)
|
||||
- [Session Goals](/session-goals/)
|
||||
- [Browser Panel](/desktop-browser/) — the OpenChamber Web tool, for looking at and driving a page
|
||||
|
||||
@@ -28,7 +28,7 @@ Das Werkzeug kann Projekte und Modelleinstellungen auflisten, Sitzungen erstelle
|
||||
|
||||
## Werkzeug ein- oder ausschalten
|
||||
|
||||
Öffne **Einstellungen → Allgemein → OpenCode CLI**, ändere **Agent control tool** und wähle dann **Save + Reload**. Die Einstellung gilt, nachdem der verwaltete OpenCode-Server neu gestartet wurde.
|
||||
Öffne **Einstellungen → Allgemein → OpenChamber-Werkzeuge** und ändere **Agent control tool**. Die Einstellung gilt, sobald der verwaltete OpenCode-Server neu startet — OpenChamber bietet das als **Apply & Restart** an.
|
||||
|
||||
Das Werkzeug ist nicht verfügbar, wenn OpenChamber über `OPENCODE_HOST` oder skip-start mit einem externen OpenCode-Server verbunden ist oder innerhalb der VS-Code-Erweiterung läuft. Desktop- und Web-Installationen, die den verwalteten OpenCode-Server von OpenChamber verwenden, unterstützen es automatisch.
|
||||
|
||||
@@ -37,3 +37,4 @@ Das Werkzeug ist nicht verfügbar, wenn OpenChamber über `OPENCODE_HOST` oder s
|
||||
- [Geplante Aufgaben](/scheduled-tasks/)
|
||||
- [Worktree-Sitzungen](/worktrees/)
|
||||
- [Sitzungsziele](/session-goals/)
|
||||
- [Browser-Panel](/desktop-browser/) — das OpenChamber-Web-Werkzeug, um eine Seite anzusehen und zu bedienen
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: Desktop-Browser
|
||||
description: Durchsuche jede Seite in der Desktop-App mit Inspektion und Konsolenaufzeichnung.
|
||||
title: Browser-Panel
|
||||
description: Öffne jede Seite in der App, annotiere sie und lass den Agenten sie bedienen.
|
||||
---
|
||||
|
||||
# Desktop-Browser
|
||||
# Browser-Panel
|
||||
|
||||
Die Desktop-App hat einen eingebauten Browser, damit du jede Seite direkt neben deinem Chat öffnen, auf Elemente zeigen und danach fragen sowie die Konsole der Seite aufzeichnen kannst. Öffne ihn über die Globus-Schaltfläche im App-Kopfbereich.
|
||||
Das Browser-Panel öffnet jede Seite direkt neben deinem Chat. Öffne es über die Globus-Schaltfläche in der Kopfzeile.
|
||||
|
||||
> Der Desktop-Browser ist eine Funktion **nur für den Desktop**. Im Web bietet das [Preview](/preview/)-Panel dieselben Inspektions- und Konsolentools für deinen lokalen Dev-Server.
|
||||
In der Desktop-App ist es ein echter Browser: Deine Logins bleiben erhalten, Hot Reload funktioniert, und die Entwicklerwerkzeuge sind einen Klick entfernt. In einem Browser-Tab zeigt das Panel eine Seite zwar an, kann aber nicht in sie hineinsehen — die Annotationswerkzeuge unten gibt es nur auf dem Desktop.
|
||||
|
||||
## Inspizieren und annotieren
|
||||
Seiten, die hier geöffnet werden, bekommen keinen Zugriff auf Kamera, Mikrofon oder Standort: solche Anfragen werden abgelehnt.
|
||||
|
||||
Aktiviere **inspect** und klicke auf ein beliebiges Element auf der Seite. OpenChamber erstellt dazu eine Notiz — was es ist, welche Stile es hat, wo es sich befindet und einen Screenshot — und hängt sie an deine Chatnachricht an. Das ist der schnellste Weg, dem Agenten zu sagen: „dieses Element, genau hier“.
|
||||
## Die Werkzeugleiste
|
||||
|
||||
## Konsolenaufzeichnung
|
||||
Die Adressleiste merkt sich Seiten, die du in diesem Projekt geöffnet hast, und schlägt sie beim Tippen vor — passend zu einem Teil der Adresse oder des Seitentitels. Mit den Pfeiltasten gehst du durch die Liste, Enter öffnet den markierten Eintrag, und die Schaltfläche in einer Zeile entfernt ihn.
|
||||
|
||||
Der Browser sammelt die Konsolenausgabe der Seite — Fehler, Warnungen und Logs — damit du sie filtern und lesen kannst, ohne die Entwicklertools zu öffnen.
|
||||
Daneben liegt **Neu laden**, dazu ein **hartes Neuladen**, das den Cache übergeht, wenn eine Änderung partout nicht erscheint, sowie eine Zoomsteuerung, die nur die Seite skaliert.
|
||||
|
||||
**Cookies löschen** und **Zwischengespeicherte Daten löschen** gelten allein für dieses Panel. Deine OpenChamber-Sitzung und andere Fenster bleiben unberührt.
|
||||
|
||||
## Eine Seite annotieren
|
||||
|
||||
Drücke **Annotieren**, und über der Seite erscheint eine Leiste mit drei Werkzeugen:
|
||||
|
||||
- **Element** — klicke ein Element an. Ein Klick auf ein anderes verschiebt die Auswahl, ein erneuter Klick auf dasselbe hebt sie auf.
|
||||
- **Bereich** — ziehe einen Rahmen um einen Ausschnitt, wenn es um mehr als ein Element geht.
|
||||
- **Zeichnen** — skizziere frei über die Seite.
|
||||
|
||||
Schreib dein Anliegen in das Feld neben deiner Markierung und drücke **Anhängen** — oder einfach Enter. Deine Chat-Nachricht bekommt eine Karte mit allem Markierten, deiner Notiz und einem Screenshot der sichtbaren Seite mit deinen Markierungen darauf — du kannst also „dieser Button, etwas runder" sagen, statt zu beschreiben, wo er steht.
|
||||
|
||||
Die Seite selbst wird nie verändert — Annotieren markiert nur, was da ist. `Esc` bricht ab und schließt die Leiste.
|
||||
|
||||
## Den Agenten steuern lassen
|
||||
|
||||
Der Agent kann das Browser-Panel selbst benutzen — eine Seite öffnen, lesen, was darauf steht, klicken, tippen, scrollen und zwischen mobiler, Tablet- und Desktop-Ansicht wechseln — um seine eigene Arbeit zu prüfen, statt dich darum zu bitten. Du siehst es im Panel passieren.
|
||||
|
||||
Beliebigen Code kann der Agent auf der Seite nicht ausführen. Der Browser behält deine echten Logins, deshalb bleibt er auf die genannten Aktionen beschränkt.
|
||||
|
||||
Er kann außerdem ein Bild dessen, was er sieht, in `.openchamber/screenshots/` in deinem Projekt speichern und es dir in seiner Antwort zeigen. Genau das macht ein Vorher-Nachher möglich, und die Datei bleibt danach liegen, um sie an einen Pull Request zu hängen.
|
||||
|
||||
Die Browser-Aktionen sind das **OpenChamber-Web-Werkzeug**, das sich unter **Einstellungen → Allgemein → OpenChamber-Werkzeuge** einzeln ein- und ausschalten lässt.
|
||||
|
||||
Dafür braucht es die Desktop-App: eine Seite in einem Browser-Tab lässt sich nicht steuern.
|
||||
|
||||
## Entwicklerwerkzeuge
|
||||
|
||||
Drücke die Terminal-Schaltfläche in der Leiste, um Chromiums eigene Entwicklerwerkzeuge für die Seite zu öffnen — Konsole, Netzwerk, Elemente, alles Gewohnte.
|
||||
|
||||
## Verwandt
|
||||
|
||||
- [Preview & Dev Servers](/preview/) — dieselben Tools für deinen lokalen Dev-Server
|
||||
- [Vorschau & Dev-Server](/preview/) — deine laufende App öffnen, auch auf einem entfernten Rechner
|
||||
- [Agenten-Steuerungswerkzeug](/agent-control-tool/) — Sitzungen, Worktrees und geplante Aufgaben aus dem Chat
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Integrationen
|
||||
description: Nutze dein Claude- oder Cursor-Abo als Provider.
|
||||
---
|
||||
|
||||
# Integrationen
|
||||
|
||||
Eine Integration ist ein kleines Plugin, das OpenChamber einen Provider hinzufügt — auf Basis eines Abos, das du bereits hast. Verwalten kannst du sie unter **Settings → Integrations**.
|
||||
|
||||
> **Experimentelle Funktion.** Wir bemühen uns, die Richtlinien der Anbieter zu respektieren, aber Kontobeschränkungen und Sperrungen liegen bei jedem Anbieter. Nutze Integrationen auf eigenes Risiko.
|
||||
|
||||
Verfügbare Integrationen:
|
||||
|
||||
- **Claude Code** — dein Claude Pro- oder Max-Plan, ohne API-Keys
|
||||
- **Cursor** — die Modell-Limits deines Cursor-Plans
|
||||
|
||||
## Integration installieren
|
||||
|
||||
1. Öffne **Settings → Integrations**.
|
||||
2. Suche die Integration und wähle **Install**.
|
||||
3. Starte OpenCode neu, wenn darum gebeten wird — der Provider erscheint nach dem Neustart.
|
||||
4. Wähle **Set up** und melde dich an. Die Modelle erscheinen danach in der Modellauswahl im Chat.
|
||||
|
||||
Integrationen werden für deinen Benutzer installiert und funktionieren damit in jedem Projekt. Aktualisieren oder entfernen kannst du sie jederzeit über dieselbe Karte.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code nutzt deinen Claude Pro- oder Max-Plan — ohne API-Keys und ohne separate Claude-App.
|
||||
|
||||
1. Installiere die Integration (siehe oben).
|
||||
2. Wähle **Set up** und melde dich an. Wenn du die Claude Code CLI noch nicht hast, bietet die Einrichtung an, sie zuerst zu installieren, und meldet dich danach an.
|
||||
|
||||
Claude Code ist die einzige Integration hier, die ihre Provider-CLI installiert und angemeldet benötigt. Cursor braucht seine CLI nicht.
|
||||
|
||||
**Wie dein Claude-Konto geschützt bleibt:** Diese Integration nutzt das offizielle Claude Agent SDK von Anthropic und deine installierte Claude Code CLI. Sie kapert kein OAuth, extrahiert oder wiederholt keine Browser-Tokens, gibt sich nicht als nicht unterstützter Client aus und umgeht nicht Anthropics Authentifizierung. Sie bleibt auf dem von Anthropic unterstützten Zugriffsweg und trägt daher nicht das mit Token-Hijacking oder unautorisierten Authentifizierungsumgehungen verbundene Sperrrisiko.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor macht die Modelle deines Cursor-Plans in OpenChamber nutzbar.
|
||||
|
||||
1. Installiere die Integration (siehe oben).
|
||||
2. Wähle **Set up**, öffne den Link und genehmige den Zugriff im Browser. Kein API-Key nötig. Die Modellliste lädt nach der Anmeldung automatisch.
|
||||
|
||||
## Aktualisieren oder entfernen
|
||||
|
||||
- **Update** installiert die neueste veröffentlichte Version des Plugins.
|
||||
- **Remove** löscht das Plugin aus deiner OpenCode-Konfiguration. Der Provider wird beim nächsten Neuladen von OpenCode nicht mehr geladen.
|
||||
|
||||
Wenn eine Karte meldet, dass Einträge manuell verwaltet werden müssen, wähle **Manage plugins** und bereinige die Duplikate dort.
|
||||
|
||||
## Verwandtes
|
||||
|
||||
- [Anbieter, Modelle und Agenten](/de/providers/) — weitere Provider verbinden und Modelle wählen
|
||||
- [Nutzung und Kontingente](/de/usage/) — verfolge, wie viel du genutzt hast
|
||||
@@ -1,32 +1,35 @@
|
||||
---
|
||||
title: Vorschau & Entwicklungsserver
|
||||
description: Öffne einen laufenden Entwicklungsserver direkt in OpenChamber.
|
||||
title: Vorschau & Dev-Server
|
||||
description: Öffne einen laufenden Dev-Server direkt in OpenChamber.
|
||||
---
|
||||
|
||||
# Vorschau & Entwicklungsserver
|
||||
# Vorschau & Dev-Server
|
||||
|
||||
Wenn du einen Entwicklungsserver startest, kann OpenChamber ihn direkt in der App öffnen statt in einem separaten Browser-Tab — so kannst du deine Seite neben dem Chat sehen, ihre Konsole aufzeichnen und Elemente anstupsen, um Fragen dazu zu stellen.
|
||||
Wenn du einen Dev-Server startest, kann OpenChamber ihn direkt in der App öffnen statt in einem separaten Browser-Tab — so siehst du deine Seite neben dem Chat und kannst auf Elemente zeigen, um danach zu fragen.
|
||||
|
||||
## Eine Vorschau öffnen
|
||||
## Einen Dev-Server öffnen
|
||||
|
||||
OpenChamber überwacht die Terminalausgabe auf eine lokale Adresse (die `Local:`-Zeile, die Werkzeuge wie Vite, Next.js oder Astro ausgeben). Sobald es eine findet:
|
||||
Öffne das Browser-Panel über die Globus-Schaltfläche in der Kopfzeile. Läuft bereits ein Dev-Server, steht er dort in der Liste und ein Klick öffnet ihn — OpenChamber findet ihn daran, was auf deinem Rechner tatsächlich lauscht, also unabhängig davon, wie du ihn gestartet hast.
|
||||
|
||||
- erscheint im Terminal eine Schaltfläche **Open preview**
|
||||
- öffnet eine [Projektaktion](/project-actions/) mit aktiviertem Auto-Open die Vorschau für dich
|
||||
- kann auch ein lokaler Link in einer Chatnachricht sie öffnen
|
||||
Ein Dev-Server öffnet sich außerdem automatisch, wenn:
|
||||
|
||||
Die Seite lädt im Seitenbereich. Nur lokale Adressen (auf deinem eigenen Rechner) können als Vorschau geöffnet werden.
|
||||
- du im Terminal bei einer lokalen Adresse auf **Vorschau öffnen** drückst
|
||||
- eine [Projektaktion](/project-actions/) mit aktiviertem Auto-Öffnen einen startet
|
||||
- du einem lokalen Link in einer Chat-Nachricht folgst
|
||||
|
||||
## Konsole und Inspektion
|
||||
Du kannst die Adresse jederzeit selbst eintippen. Ein bloßes `localhost:5173` wird als `http://` verstanden, das Schema musst du also nicht mitschreiben.
|
||||
|
||||
Im Vorschau-Bereich kannst du:
|
||||
## Mit einem entfernten OpenChamber arbeiten
|
||||
|
||||
- die **Konsole** der Seite beobachten — Fehler, Warnungen und Protokolle, so gefiltert, wie du möchtest
|
||||
- **inspect** einschalten, auf ein beliebiges Element klicken und eine Notiz dazu senden — Selektor, Stile, Position und ein Screenshot — direkt in den Chat
|
||||
Läuft OpenChamber auf einem anderen Rechner, liegt sein Dev-Server ebenfalls auf *jenem* Rechner — `localhost` auf deinem Laptop führt ganz woandershin. Die Desktop-App erledigt das für dich: Sie öffnet einen lokalen Port, der die Verbindung zum entfernten Dev-Server durchreicht. Die Seite lädt ganz normal, mit funktionierendem Hot Reload und Entwicklerwerkzeugen. Du tippst weiterhin die Adresse, die du erwartest; die Technik dahinter bleibt dir aus dem Weg.
|
||||
|
||||
Das ist der schnellste Weg, dem Agenten "diese Schaltfläche hier" zu sagen, ohne sie beschreiben zu müssen.
|
||||
Dafür brauchst du die Desktop-App. In einem Browser-Tab lassen sich nur Dev-Server auf deinem eigenen Rechner öffnen.
|
||||
|
||||
## Die Seite annotieren
|
||||
|
||||
Wie du auf Elemente zeigst, auf der Seite zeichnest und alles in den Chat schickst, steht unter [Browser-Panel](/desktop-browser/).
|
||||
|
||||
## Verwandt
|
||||
|
||||
- [Projektaktionen](/project-actions/) — einen Server automatisch öffnen, wenn du ihn startest
|
||||
- [Desktop-Browser](/desktop-browser/) — dieselben Werkzeuge für jede Seite, auf dem Desktop
|
||||
- [Projektaktionen](/project-actions/) — einen Server beim Start automatisch öffnen
|
||||
- [Browser-Panel](/desktop-browser/) — Seiten annotieren und den Agenten steuern lassen
|
||||
|
||||
@@ -45,5 +45,6 @@ Provider-Anmeldungen werden von OpenCode gespeichert, nicht von OpenChamber, dah
|
||||
|
||||
## Weiterführend
|
||||
|
||||
- [Integrationen](/integrations/) — nutze ein Claude-, Command-Code- oder Cursor-Abo als Provider
|
||||
- [MCP-Server](/mcp/) — füge Agents zusätzliche Werkzeuge hinzu
|
||||
- [Nutzung & Kontingente](/usage/) — verfolge, wie viel du verbraucht hast
|
||||
|
||||
@@ -12,7 +12,7 @@ Zum Schreiben eigener Skills siehe [Skills](/skills/).
|
||||
## Einen Skill installieren
|
||||
|
||||
1. Öffne den Katalog.
|
||||
2. Durchsuche die eingebauten Quellen — das Anthropic-Skills-Repo und die ClawdHub-Community-Registry — oder nutze die Suche.
|
||||
2. Durchsuche die eingebauten Quellen — wie das Anthropic-Skills-Repo — oder nutze die Suche.
|
||||
3. Wähle einen Skill aus und installiere ihn.
|
||||
4. Entscheide, wo er installiert werden soll: für alles, was du tust, oder nur für das aktuelle Projekt.
|
||||
|
||||
|
||||
@@ -1,22 +1,63 @@
|
||||
---
|
||||
title: Desktop Browser
|
||||
description: Browse any page inside the desktop app, with inspect and console capture.
|
||||
title: Browser Panel
|
||||
description: Browse any page inside the app, annotate it, and let the agent drive it.
|
||||
---
|
||||
|
||||
# Desktop Browser
|
||||
# Browser Panel
|
||||
|
||||
The desktop app has a built-in browser so you can open any page right next to your chat, point at elements to ask about them, and capture the page's console. Open it from the globe button in the app header.
|
||||
The browser panel opens any page right next to your chat. Open it from the globe button in the app header.
|
||||
|
||||
> The desktop browser is a **desktop-only** feature. On the web, the [preview](/preview/) panel offers the same inspect-and-console tools for your local dev server.
|
||||
On the desktop app it is a real browser: your logins persist, hot reload works, and developer tools are one click away. In a web browser tab the panel can still display a page, but it cannot look inside one — the annotation tools below are desktop-only. The VS Code extension has no browser panel at all: VS Code is already an editor with a browser beside it, and everything that makes this panel worth having needs the desktop app.
|
||||
|
||||
## Inspect and annotate
|
||||
Pages opened here cannot use your camera, microphone, or location: those requests are refused.
|
||||
|
||||
Turn on **inspect** and click any element on the page. OpenChamber captures a note about it — what it is, its styles, where it sits, and a screenshot — and attaches it to your chat message. It's the quickest way to tell the agent "this element, right here."
|
||||
## The toolbar
|
||||
|
||||
## Console capture
|
||||
The address bar remembers pages you have opened in this project and offers them as you type, matching part of an address or a page title. Arrow keys move through the list, Enter opens the highlighted entry, and the button on a row removes it.
|
||||
|
||||
The browser collects the page's console output — errors, warnings, and logs — so you can filter and read it without opening developer tools.
|
||||
**Reload** is next to it, along with a **hard reload** that ignores the cache when a change refuses to show up, and zoom controls that scale the page only.
|
||||
|
||||
**Clear cookies** and **Clear cached data** apply to this panel alone. Your OpenChamber session and any other window are untouched.
|
||||
|
||||
## Annotate a page
|
||||
|
||||
Press **Annotate** and a toolbar appears over the page with three tools:
|
||||
|
||||
- **Element** — click an element. Clicking another moves the selection; clicking the same one again clears it.
|
||||
- **Region** — drag a box around an area, when what you mean covers more than one element.
|
||||
- **Draw** — sketch freehand over the page.
|
||||
|
||||
Write what you want in the box that appears beside your mark, and press **Attach** — or just press Enter. Your chat message gets a card with everything you marked, your note, and a screenshot of the visible page with your marks drawn on it — so you can say "this button, a bit rounder" instead of describing where it is.
|
||||
|
||||
The page itself is never modified — annotating marks what is there. `Esc` cancels and closes the toolbar.
|
||||
|
||||
## Let the agent drive
|
||||
|
||||
The agent can use the browser panel itself — opening a page, reading what is on it, clicking, typing, scrolling, and switching between mobile, tablet and desktop layouts — so it can check its own work instead of asking you to. You will see it happening in the panel.
|
||||
|
||||
The agent cannot run arbitrary code in the page. The browser keeps your real logins, so it is limited to the specific actions above.
|
||||
|
||||
It can also save a picture of what it is looking at into `.openchamber/screenshots/` in your project and show it to you in its reply. That is what makes a before-and-after possible, and the file stays there afterwards to attach to a pull request.
|
||||
|
||||
The browser actions are the **OpenChamber Web tool**, which can be turned on and off on its own in **Settings → General → OpenChamber Tools**.
|
||||
|
||||
This needs the desktop app: a page shown in a web browser tab cannot be driven.
|
||||
|
||||
## Size and appearance
|
||||
|
||||
Press the phone button to open the device bar. Pick a preset or type a width and
|
||||
height, and the page is laid out at that size — scaled down to fit the panel
|
||||
when it is bigger, but still measuring itself at the size you asked for.
|
||||
|
||||
The same bar forces the page to light or dark, so a theme can be checked without
|
||||
changing anything on your machine. It leaves DevTools alone; a page can only
|
||||
have one debugger attached, so close DevTools first if it is open.
|
||||
|
||||
## Developer tools
|
||||
|
||||
Press the terminal button in the toolbar to open Chromium's own developer tools for the page — console, network, elements, everything you would expect.
|
||||
|
||||
## Related
|
||||
|
||||
- [Preview & Dev Servers](/preview/) — the same tools for your local dev server
|
||||
- [Preview & Dev Servers](/preview/) — opening your running app, including on a remote machine
|
||||
- [Agent Control Tool](/agent-control-tool/) — sessions, worktrees and scheduled tasks from chat
|
||||
|
||||
@@ -28,7 +28,7 @@ La herramienta puede listar proyectos y preferencias de modelos, crear y continu
|
||||
|
||||
## Activar o desactivar la herramienta
|
||||
|
||||
Abre **Ajustes → General → OpenCode CLI**, cambia **Herramienta de control para agentes** y selecciona **Save + Reload**. El ajuste se aplica cuando se reinicia el servidor OpenCode gestionado.
|
||||
Abre **Ajustes → General → Herramientas de OpenChamber** y cambia **Herramienta de control para agentes**. El ajuste se aplica cuando se reinicia el servidor OpenCode gestionado, que OpenChamber ofrece como **Apply & Restart**.
|
||||
|
||||
La herramienta no está disponible cuando OpenChamber se conecta a un servidor OpenCode externo mediante `OPENCODE_HOST` o skip-start, ni dentro de la extensión de VS Code. Las instalaciones web y de escritorio que usan el servidor OpenCode gestionado por OpenChamber la admiten automáticamente.
|
||||
|
||||
@@ -37,3 +37,4 @@ La herramienta no está disponible cuando OpenChamber se conecta a un servidor O
|
||||
- [Tareas programadas](/es/scheduled-tasks/)
|
||||
- [Sesiones de worktree](/es/worktrees/)
|
||||
- [Objetivos de sesión](/es/session-goals/)
|
||||
- [Panel del navegador](/es/desktop-browser/) — la herramienta OpenChamber Web, para ver una página y manejarla
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: Navegador de escritorio
|
||||
description: Navega cualquier página dentro de la app de escritorio, con inspección y captura de consola.
|
||||
title: Panel del navegador
|
||||
description: Navega cualquier página dentro de la aplicación, anótala y deja que el agente la maneje.
|
||||
---
|
||||
|
||||
# Navegador de escritorio
|
||||
# Panel del navegador
|
||||
|
||||
La app de escritorio tiene un navegador integrado para que abras cualquier página justo al lado de tu chat, señales elementos para preguntar sobre ellos y captures la consola de la página. Ábrelo desde el botón del globo en el encabezado de la app.
|
||||
El panel del navegador abre cualquier página justo al lado del chat. Ábrelo con el botón del globo de la cabecera.
|
||||
|
||||
> El navegador de escritorio es una función **solo de escritorio**. En la web, el panel de [vista previa](/es/preview/) ofrece las mismas herramientas de inspección y consola para tu servidor de desarrollo local.
|
||||
En la aplicación de escritorio es un navegador de verdad: tus sesiones se mantienen, la recarga en caliente funciona y las herramientas de desarrollo están a un clic. En una pestaña del navegador el panel puede mostrar una página, pero no mirar dentro de ella: las herramientas de anotación de abajo son solo de escritorio.
|
||||
|
||||
## Inspecciona y anota
|
||||
Las páginas que abras aquí no pueden usar tu cámara, tu micrófono ni tu ubicación: esas peticiones se rechazan.
|
||||
|
||||
Activa **inspect** y haz clic en cualquier elemento de la página. OpenChamber captura una nota sobre él —qué es, sus estilos, dónde se sitúa y una captura de pantalla— y la adjunta a tu mensaje del chat. Es la forma más rápida de decirle al agente "este elemento, justo aquí".
|
||||
## La barra de herramientas
|
||||
|
||||
## Captura de consola
|
||||
La barra de direcciones recuerda las páginas que has abierto en este proyecto y las ofrece mientras escribes, buscando en parte de la dirección o del título de la página. Las flechas recorren la lista, Enter abre la entrada resaltada y el botón de una fila la quita.
|
||||
|
||||
El navegador recopila la salida de la consola de la página —errores, advertencias y registros— para que puedas filtrarla y leerla sin abrir las herramientas de desarrollo.
|
||||
Al lado está **Recargar**, junto con una **recarga forzada** que ignora la caché cuando un cambio se niega a aparecer, y los controles de zoom, que escalan solo la página.
|
||||
|
||||
**Borrar cookies** y **Borrar datos en caché** afectan únicamente a este panel. Tu sesión de OpenChamber y cualquier otra ventana quedan intactas.
|
||||
|
||||
## Anotar una página
|
||||
|
||||
Pulsa **Anotar** y aparecerá una barra sobre la página con tres herramientas:
|
||||
|
||||
- **Elemento** — haz clic en un elemento. Hacer clic en otro mueve la selección; volver a hacer clic en el mismo la quita.
|
||||
- **Región** — arrastra un recuadro alrededor de una zona cuando te refieras a más de un elemento.
|
||||
- **Dibujar** — traza a mano alzada sobre la página.
|
||||
|
||||
Escribe lo que quieres en el cuadro que aparece junto a tu marca y pulsa **Adjuntar**, o simplemente Enter. Tu mensaje recibe una tarjeta con todo lo que has marcado, tu nota y una captura de la página visible con tus marcas dibujadas encima — así puedes decir "este botón, un poco más redondeado" en vez de describir dónde está.
|
||||
|
||||
La página en sí nunca se modifica: anotar solo marca lo que ya está ahí. `Esc` cancela y cierra la barra.
|
||||
|
||||
## Dejar que el agente maneje
|
||||
|
||||
El agente puede usar el panel del navegador por su cuenta — abrir una página, leer lo que hay en ella, hacer clic, escribir, desplazarse y alternar entre diseño móvil, de tableta y de escritorio — para comprobar su propio trabajo en lugar de pedírtelo a ti. Lo verás ocurrir en el panel.
|
||||
|
||||
El agente no puede ejecutar código arbitrario en la página. El navegador conserva tus sesiones reales, así que se limita a las acciones anteriores.
|
||||
|
||||
También puede guardar una imagen de lo que está viendo en `.openchamber/screenshots/` de tu proyecto y mostrártela en su respuesta. Eso es lo que hace posible un antes y después, y el archivo se queda ahí para adjuntarlo a un pull request.
|
||||
|
||||
Las acciones del navegador son la **herramienta OpenChamber Web**, que se activa y desactiva por separado en **Ajustes → General → Herramientas de OpenChamber**.
|
||||
|
||||
Esto necesita la aplicación de escritorio: una página mostrada en una pestaña del navegador no se puede controlar.
|
||||
|
||||
## Herramientas de desarrollo
|
||||
|
||||
Pulsa el botón de terminal de la barra para abrir las herramientas de desarrollo propias de Chromium — consola, red, elementos, todo lo habitual.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Vista previa y servidores de desarrollo](/es/preview/) — las mismas herramientas para tu servidor de desarrollo local
|
||||
- [Vista previa y servidores de desarrollo](/preview/) — abrir tu aplicación en marcha, también en una máquina remota
|
||||
- [Herramienta de control para agentes](/es/agent-control-tool/) — sesiones, worktrees y tareas programadas desde el chat
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Integraciones
|
||||
description: Usa tu suscripción de Claude o Cursor como proveedor.
|
||||
---
|
||||
|
||||
# Integraciones
|
||||
|
||||
Una integración es un pequeño plugin que añade un proveedor a OpenChamber usando una suscripción que ya tienes. Las gestionas en **Settings → Integrations**.
|
||||
|
||||
> **Función experimental.** Buscamos respetar las políticas de los proveedores, pero las restricciones y suspensiones de cuentas son decisión de cada proveedor. Usa las integraciones bajo tu propia responsabilidad.
|
||||
|
||||
Integraciones disponibles:
|
||||
|
||||
- **Claude Code** — tu plan Claude Pro o Max, sin claves de API
|
||||
- **Cursor** — los límites de modelos de tu plan de Cursor
|
||||
|
||||
## Instalar una integración
|
||||
|
||||
1. Abre **Settings → Integrations**.
|
||||
2. Busca la integración y elige **Install**.
|
||||
3. Reinicia OpenCode cuando se te pida — el proveedor aparece tras el reinicio.
|
||||
4. Elige **Set up** e inicia sesión. Los modelos aparecerán luego en el selector de modelos del chat.
|
||||
|
||||
Las integraciones se instalan para tu usuario, así que funcionan en todos los proyectos. Puedes actualizarlas o eliminarlas desde la misma tarjeta en cualquier momento.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code usa tu plan Claude Pro o Max — sin claves de API y sin una app de Claude aparte.
|
||||
|
||||
1. Instala la integración (arriba).
|
||||
2. Elige **Set up** e inicia sesión. Si aún no tienes la CLI de Claude Code, la configuración ofrece instalarla primero y luego iniciar sesión.
|
||||
|
||||
Claude Code es la única integración de esta página que requiere tener la CLI de su proveedor instalada y con sesión iniciada. Cursor no requiere su CLI.
|
||||
|
||||
**Cómo se protege tu cuenta de Claude:** esta integración usa el Claude Agent SDK oficial de Anthropic y tu CLI de Claude Code instalada. No secuestra OAuth, no extrae ni reutiliza tokens del navegador, no se hace pasar por un cliente no admitido ni omite la autenticación de Anthropic. Se mantiene en la vía de acceso admitida por Anthropic, por lo que no conlleva el riesgo de baneo asociado al secuestro de tokens o a rodeos de autenticación no autorizados.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor hace disponibles en OpenChamber los modelos incluidos en tu plan de Cursor.
|
||||
|
||||
1. Instala la integración (arriba).
|
||||
2. Elige **Set up**, abre el enlace y autoriza el acceso en tu navegador. No necesitas clave de API. La lista de modelos se carga automáticamente tras iniciar sesión.
|
||||
|
||||
## Actualizar o eliminar
|
||||
|
||||
- **Update** instala la última versión publicada del plugin.
|
||||
- **Remove** elimina el plugin de tu configuración de OpenCode. El proveedor deja de cargarse cuando OpenCode se recarga.
|
||||
|
||||
Si una tarjeta indica que las entradas requieren gestión manual, elige **Manage plugins** y limpia ahí los duplicados.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Proveedores, modelos y agentes](/es/providers/) — conecta otros proveedores y elige modelos
|
||||
- [Uso y cuotas](/es/usage/) — sigue cuánto has usado
|
||||
@@ -5,28 +5,31 @@ description: Abre un servidor de desarrollo en marcha dentro de OpenChamber.
|
||||
|
||||
# Vista previa y servidores de desarrollo
|
||||
|
||||
Cuando inicias un servidor de desarrollo, OpenChamber puede abrirlo dentro de la propia app en lugar de en una pestaña de navegador aparte, para que veas tu sitio junto al chat, captures su consola y señales elementos para preguntar sobre ellos.
|
||||
Cuando arrancas un servidor de desarrollo, OpenChamber puede abrirlo dentro de la propia aplicación en lugar de en una pestaña aparte — así ves tu sitio junto al chat y puedes señalar elementos para preguntar por ellos.
|
||||
|
||||
## Abre una vista previa
|
||||
## Abrir un servidor de desarrollo
|
||||
|
||||
OpenChamber observa la salida de la terminal en busca de una dirección local (la línea `Local:` que imprimen herramientas como Vite, Next.js o Astro). Cuando detecta una:
|
||||
Abre el panel del navegador con el botón del globo de la cabecera. Si ya hay un servidor en marcha, aparece en la lista y se abre con un clic: OpenChamber lo encuentra mirando qué está escuchando de verdad en tu máquina, así que funciona sin importar cómo lo hayas arrancado.
|
||||
|
||||
- en la terminal aparece un botón **Open preview**
|
||||
- una [acción de proyecto](/es/project-actions/) con la apertura automática activada la abre por ti
|
||||
- un enlace local en un mensaje del chat también puede abrirla
|
||||
Un servidor de desarrollo también se abre solo cuando:
|
||||
|
||||
El sitio se carga en el panel lateral. Solo se pueden previsualizar direcciones locales (en tu propia máquina).
|
||||
- pulsas **Abrir vista previa** sobre una dirección local en la terminal
|
||||
- una [acción de proyecto](/project-actions/) con apertura automática arranca uno
|
||||
- sigues un enlace local en un mensaje del chat
|
||||
|
||||
## Consola e inspección
|
||||
Siempre puedes escribir la dirección a mano. Un simple `localhost:5173` se entiende como `http://`, así que no hace falta escribir el esquema.
|
||||
|
||||
En el panel de vista previa puedes:
|
||||
## Trabajar con un OpenChamber remoto
|
||||
|
||||
- ver la **consola** de la página —errores, advertencias y registros— filtrada como prefieras
|
||||
- activar **inspect**, hacer clic en cualquier elemento y enviar una nota sobre él —selector, estilos, posición y una captura de pantalla— directamente al chat
|
||||
Cuando OpenChamber corre en otra máquina, su servidor de desarrollo está en *esa* máquina — `localhost` en tu portátil apunta a otro sitio completamente distinto. La aplicación de escritorio se encarga: abre un puerto local que lleva la conexión hasta el servidor remoto, de modo que la página carga con normalidad, con recarga en caliente y herramientas de desarrollo funcionando. Tú sigues escribiendo la dirección que esperas; la fontanería no te estorba.
|
||||
|
||||
Esta es la forma más rápida de decirle al agente "este botón, aquí" sin describirlo.
|
||||
Esto requiere la aplicación de escritorio. En una pestaña del navegador solo se pueden abrir servidores de tu propia máquina.
|
||||
|
||||
## Anotar la página
|
||||
|
||||
Consulta [Panel del navegador](/desktop-browser/) para señalar elementos, dibujar sobre la página y enviarlo todo al chat.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Acciones de proyecto](/es/project-actions/) — abre automáticamente un servidor al iniciarlo
|
||||
- [Navegador de escritorio](/es/desktop-browser/) — las mismas herramientas para cualquier página, en el escritorio
|
||||
- [Acciones de proyecto](/project-actions/) — abrir un servidor automáticamente al arrancarlo
|
||||
- [Panel del navegador](/desktop-browser/) — anotar páginas y dejar que el agente las maneje
|
||||
|
||||
@@ -45,5 +45,6 @@ Los inicios de sesión de los proveedores los guarda OpenCode, no OpenChamber, a
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Integraciones](/es/integrations/) — usa una suscripción de Claude o Cursor como proveedor
|
||||
- [Servidores MCP](/es/mcp/) — añade herramientas extra para los agentes
|
||||
- [Uso y cuotas](/es/usage/) — controla cuánto has consumido
|
||||
|
||||
@@ -12,7 +12,7 @@ Para escribir tus propias skills, consulta [Skills](/es/skills/).
|
||||
## Instala una skill
|
||||
|
||||
1. Abre el catálogo.
|
||||
2. Explora las fuentes integradas —el repositorio de skills de Anthropic y el registro comunitario de ClawdHub— o busca.
|
||||
2. Explora las fuentes integradas —como el repositorio de skills de Anthropic— o busca.
|
||||
3. Elige una skill e instálala.
|
||||
4. Elige dónde instalarla: para todo lo que hagas, o solo en el proyecto actual.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ L’outil peut répertorier les projets et les préférences de modèles, créer
|
||||
|
||||
## Activer ou désactiver l’outil
|
||||
|
||||
Ouvrez **Paramètres → Général → OpenCode CLI**, modifiez **Outil de contrôle pour les agents**, puis sélectionnez **Save + Reload**. Le réglage s’applique après le redémarrage du serveur OpenCode géré.
|
||||
Ouvrez **Paramètres → Général → Outils OpenChamber** et modifiez **Outil de contrôle pour les agents**. Le réglage s’applique au redémarrage du serveur OpenCode géré, que OpenChamber propose sous **Apply & Restart**.
|
||||
|
||||
L’outil n’est pas disponible quand OpenChamber se connecte à un serveur OpenCode externe avec `OPENCODE_HOST` ou skip-start, ni dans l’extension VS Code. Les installations desktop et web utilisant le serveur OpenCode géré par OpenChamber le prennent automatiquement en charge.
|
||||
|
||||
@@ -37,3 +37,4 @@ L’outil n’est pas disponible quand OpenChamber se connecte à un serveur Ope
|
||||
- [Tâches planifiées](/fr/scheduled-tasks/)
|
||||
- [Sessions worktree](/fr/worktrees/)
|
||||
- [Objectifs de session](/fr/session-goals/)
|
||||
- [Panneau navigateur](/fr/desktop-browser/) — l'outil OpenChamber Web, pour consulter une page et la piloter
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: Navigateur desktop
|
||||
description: Parcourez n’importe quelle page dans l’application desktop, avec inspection et capture de console.
|
||||
title: Panneau navigateur
|
||||
description: Parcourez n'importe quelle page dans l'application, annotez-la et laissez l'agent la piloter.
|
||||
---
|
||||
|
||||
# Navigateur desktop
|
||||
# Panneau navigateur
|
||||
|
||||
L’application desktop possède un navigateur intégré pour ouvrir n’importe quelle page juste à côté de votre chat, pointer des éléments pour poser des questions à leur sujet et capturer la console de la page. Ouvrez-le avec le bouton globe dans l’en-tête de l’application.
|
||||
Le panneau navigateur ouvre n'importe quelle page juste à côté de votre discussion. Ouvrez-le depuis le bouton globe de l'en-tête.
|
||||
|
||||
> Le navigateur desktop est une fonctionnalité **desktop uniquement**. Sur le web, le panneau [aperçu](/preview/) offre les mêmes outils d’inspection et de console pour votre serveur de dev local.
|
||||
Dans l'application de bureau, c'est un vrai navigateur : vos connexions persistent, le rechargement à chaud fonctionne et les outils de développement sont à un clic. Dans un onglet de navigateur, le panneau affiche bien une page mais ne peut pas regarder à l'intérieur — les outils d'annotation ci-dessous sont réservés au bureau.
|
||||
|
||||
## Inspecter et annoter
|
||||
Les pages ouvertes ici ne peuvent pas utiliser votre caméra, votre micro ni votre position : ces demandes sont refusées.
|
||||
|
||||
Activez **inspect** et cliquez sur n’importe quel élément de la page. OpenChamber capture une note à son sujet — ce que c’est, ses styles, sa position et une capture d’écran — puis l’attache à votre message de chat. C’est le moyen le plus rapide de dire à l’agent « cet élément, juste ici ».
|
||||
## La barre d'outils
|
||||
|
||||
## Capture de console
|
||||
La barre d'adresse retient les pages que vous avez ouvertes dans ce projet et les propose pendant la saisie, en cherchant dans une partie de l'adresse ou du titre de la page. Les flèches parcourent la liste, Entrée ouvre l'entrée surlignée, et le bouton d'une ligne la retire.
|
||||
|
||||
Le navigateur collecte la sortie console de la page — erreurs, avertissements et logs — pour que vous puissiez la filtrer et la lire sans ouvrir les outils développeur.
|
||||
À côté se trouve **Recharger**, ainsi qu'un **rechargement forcé** qui ignore le cache quand un changement refuse d'apparaître, et des commandes de zoom qui agrandissent la page seule.
|
||||
|
||||
## Pages liées
|
||||
**Effacer les cookies** et **Effacer les données en cache** ne concernent que ce panneau. Votre session OpenChamber et les autres fenêtres n'y touchent pas.
|
||||
|
||||
- [Aperçu et serveurs de dev](/preview/) — les mêmes outils pour votre serveur de dev local
|
||||
## Annoter une page
|
||||
|
||||
Appuyez sur **Annoter** : une barre apparaît au-dessus de la page avec trois outils.
|
||||
|
||||
- **Élément** — cliquez sur un élément. Cliquer sur un autre déplace la sélection ; recliquer sur le même la retire.
|
||||
- **Zone** — tracez un cadre autour d'une portion lorsque votre remarque porte sur plusieurs éléments.
|
||||
- **Dessin** — croquez à main levée par-dessus la page.
|
||||
|
||||
Écrivez votre demande dans le champ qui apparaît à côté de votre marque, puis appuyez sur **Joindre** — ou simplement sur Entrée. Votre message reçoit une carte avec tout ce que vous avez marqué, votre note et une capture de la page visible avec vos marques dessinées dessus — vous pouvez donc dire « ce bouton, un peu plus arrondi » au lieu de décrire où il se trouve.
|
||||
|
||||
La page elle-même n'est jamais modifiée : annoter ne fait que marquer ce qui s'y trouve. `Échap` annule et ferme la barre.
|
||||
|
||||
## Laisser l'agent piloter
|
||||
|
||||
L'agent peut se servir lui-même du panneau navigateur — ouvrir une page, lire ce qu'elle contient, cliquer, saisir du texte, faire défiler et basculer entre les mises en page mobile, tablette et bureau — afin de vérifier son propre travail plutôt que de vous le demander. Vous le voyez faire dans le panneau.
|
||||
|
||||
L'agent ne peut pas exécuter de code arbitraire dans la page. Le navigateur conserve vos vraies connexions ; il s'en tient donc aux actions ci-dessus.
|
||||
|
||||
Il peut aussi enregistrer une image de ce qu'il regarde dans `.openchamber/screenshots/` de votre projet et vous la montrer dans sa réponse. C'est ce qui rend un avant-après possible, et le fichier reste ensuite disponible pour l'attacher à une pull request.
|
||||
|
||||
Les actions du navigateur constituent l'**outil OpenChamber Web**, qui s'active et se désactive séparément dans **Réglages → Général → Outils OpenChamber**.
|
||||
|
||||
Cela nécessite l'application de bureau : une page affichée dans un onglet de navigateur ne peut pas être pilotée.
|
||||
|
||||
## Outils de développement
|
||||
|
||||
Appuyez sur le bouton terminal de la barre pour ouvrir les outils de développement de Chromium pour la page — console, réseau, éléments, tout ce à quoi vous vous attendez.
|
||||
|
||||
## Voir aussi
|
||||
|
||||
- [Aperçu et serveurs de développement](/preview/) — ouvrir votre application en cours, y compris sur une machine distante
|
||||
- [Outil de contrôle pour les agents](/fr/agent-control-tool/) — sessions, worktrees et tâches planifiées depuis la discussion
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Intégrations
|
||||
description: Utilise ton abonnement Claude ou Cursor comme fournisseur.
|
||||
---
|
||||
|
||||
# Intégrations
|
||||
|
||||
Une intégration est un petit plugin qui ajoute un fournisseur à OpenChamber à partir d'un abonnement que tu possèdes déjà. Tu les gères dans **Settings → Integrations**.
|
||||
|
||||
> **Fonctionnalité expérimentale.** Nous cherchons à respecter les règles des fournisseurs, mais les restrictions et suspensions de compte relèvent de leur décision. Utilise les intégrations à tes risques.
|
||||
|
||||
Intégrations disponibles :
|
||||
|
||||
- **Claude Code** — ton plan Claude Pro ou Max, sans clés API
|
||||
- **Cursor** — les limites de modèles de ton plan Cursor
|
||||
|
||||
## Installer une intégration
|
||||
|
||||
1. Ouvre **Settings → Integrations**.
|
||||
2. Trouve l'intégration et choisis **Install**.
|
||||
3. Redémarre OpenCode quand c'est demandé — le fournisseur apparaît après le redémarrage.
|
||||
4. Choisis **Set up** et connecte-toi. Les modèles apparaissent ensuite dans le sélecteur de modèles du chat.
|
||||
|
||||
Les intégrations s'installent pour ton utilisateur et fonctionnent donc dans tous les projets. Tu peux les mettre à jour ou les retirer à tout moment depuis la même carte.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code utilise ton plan Claude Pro ou Max — sans clés API et sans application Claude séparée.
|
||||
|
||||
1. Installe l'intégration (ci-dessus).
|
||||
2. Choisis **Set up** et connecte-toi. Si tu n'as pas encore la CLI Claude Code, la configuration propose de l'installer d'abord, puis de te connecter.
|
||||
|
||||
Claude Code est la seule intégration ici qui exige que la CLI de son fournisseur soit installée et connectée. Cursor n'exige pas sa CLI.
|
||||
|
||||
**Comment ton compte Claude reste protégé :** cette intégration utilise le Claude Agent SDK officiel d'Anthropic et ta CLI Claude Code installée. Elle ne détourne pas l'OAuth, n'extrait ni rejoue de tokens de navigateur, ne se fait pas passer pour un client non pris en charge et ne contourne pas l'authentification d'Anthropic. Elle reste sur la voie d'accès prise en charge par Anthropic et ne porte donc pas le risque de bannissement associé au détournement de tokens ou aux contournements d'authentification non autorisés.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor rend disponibles dans OpenChamber les modèles inclus dans ton plan Cursor.
|
||||
|
||||
1. Installe l'intégration (ci-dessus).
|
||||
2. Choisis **Set up**, ouvre le lien et autorise l'accès dans ton navigateur. Aucune clé API n'est nécessaire. La liste des modèles se charge automatiquement après la connexion.
|
||||
|
||||
## Mettre à jour ou retirer
|
||||
|
||||
- **Update** installe la dernière version publiée du plugin.
|
||||
- **Remove** supprime le plugin de ta configuration OpenCode. Le fournisseur cesse d'être chargé au prochain rechargement d'OpenCode.
|
||||
|
||||
Si une carte indique que les entrées nécessitent une gestion manuelle, choisis **Manage plugins** et nettoie les doublons à cet endroit.
|
||||
|
||||
## À voir aussi
|
||||
|
||||
- [Fournisseurs, modèles et agents](/fr/providers/) — connecter d'autres fournisseurs et choisir des modèles
|
||||
- [Utilisation et quotas](/fr/usage/) — suis ta consommation
|
||||
@@ -1,32 +1,35 @@
|
||||
---
|
||||
title: Aperçu et serveurs de dev
|
||||
description: Ouvrez un serveur de dev en cours d’exécution dans OpenChamber.
|
||||
title: Aperçu et serveurs de développement
|
||||
description: Ouvrez un serveur de développement en cours d'exécution dans OpenChamber.
|
||||
---
|
||||
|
||||
# Aperçu et serveurs de dev
|
||||
# Aperçu et serveurs de développement
|
||||
|
||||
Quand vous démarrez un serveur de dev, OpenChamber peut l’ouvrir directement dans l’application au lieu d’un onglet de navigateur séparé — vous voyez ainsi votre site à côté du chat, vous capturez sa console et vous pouvez pointer des éléments pour poser des questions à leur sujet.
|
||||
Quand vous lancez un serveur de développement, OpenChamber peut l'ouvrir directement dans l'application plutôt que dans un onglet séparé — vous voyez ainsi votre site à côté de la discussion et pouvez désigner des éléments pour poser des questions à leur sujet.
|
||||
|
||||
## Ouvrir un aperçu
|
||||
## Ouvrir un serveur de développement
|
||||
|
||||
OpenChamber surveille la sortie du terminal pour détecter une adresse locale (la ligne `Local:` affichée par des outils comme Vite, Next.js ou Astro). Quand il en trouve une :
|
||||
Ouvrez le panneau navigateur depuis le bouton globe de l'en-tête. Si un serveur tourne déjà, il apparaît dans la liste et un clic suffit à l'ouvrir : OpenChamber le repère à partir de ce qui écoute réellement sur votre machine, quelle que soit la façon dont vous l'avez lancé.
|
||||
|
||||
- dans le terminal, un bouton **Ouvrir l’aperçu** apparaît
|
||||
- une [action de projet](/project-actions/) avec l’ouverture automatique activée l’ouvre pour vous
|
||||
- un lien local dans un message de chat peut aussi l’ouvrir
|
||||
Un serveur s'ouvre également tout seul quand :
|
||||
|
||||
Le site se charge dans le panneau latéral. Seules les adresses locales (sur votre propre machine) peuvent être prévisualisées.
|
||||
- vous appuyez sur **Ouvrir l'aperçu** sur une adresse locale dans le terminal
|
||||
- une [action de projet](/project-actions/) avec ouverture automatique en démarre un
|
||||
- vous suivez un lien local dans un message de la discussion
|
||||
|
||||
## Console et inspection
|
||||
Vous pouvez toujours saisir l'adresse vous-même. Un simple `localhost:5173` est compris comme `http://`, inutile donc d'écrire le schéma.
|
||||
|
||||
Dans le panneau d’aperçu, vous pouvez :
|
||||
## Travailler avec un OpenChamber distant
|
||||
|
||||
- regarder la **console** de la page — erreurs, avertissements et logs, filtrés comme vous le voulez
|
||||
- activer **inspect**, cliquer sur n’importe quel élément et envoyer une note à son sujet — sélecteur, styles, position et capture d’écran — directement dans le chat
|
||||
Quand OpenChamber tourne sur une autre machine, son serveur de développement s'y trouve aussi — `localhost` sur votre portable désigne tout autre chose. L'application de bureau s'en charge : elle ouvre un port local qui achemine la connexion jusqu'au serveur distant, si bien que la page se charge normalement, avec rechargement à chaud et outils de développement fonctionnels. Vous continuez à saisir l'adresse attendue ; la tuyauterie reste hors de votre chemin.
|
||||
|
||||
C’est le moyen le plus rapide de dire à l’agent « ce bouton, ici » sans devoir le décrire.
|
||||
Cela nécessite l'application de bureau. Dans un onglet de navigateur, seuls les serveurs de votre propre machine peuvent être ouverts.
|
||||
|
||||
## Pages liées
|
||||
## Annoter la page
|
||||
|
||||
- [Actions de projet](/project-actions/) — ouvrir automatiquement un serveur quand vous le démarrez
|
||||
- [Navigateur desktop](/desktop-browser/) — les mêmes outils pour n’importe quelle page, sur desktop
|
||||
Voyez [Panneau navigateur](/desktop-browser/) pour désigner des éléments, dessiner sur la page et envoyer le tout dans la discussion.
|
||||
|
||||
## Voir aussi
|
||||
|
||||
- [Actions de projet](/project-actions/) — ouvrir automatiquement un serveur à son démarrage
|
||||
- [Panneau navigateur](/desktop-browser/) — annoter les pages et laisser l'agent les piloter
|
||||
|
||||
@@ -45,5 +45,6 @@ Les connexions aux fournisseurs sont stockées par OpenCode, pas OpenChamber ; e
|
||||
|
||||
## Pages liées
|
||||
|
||||
- [Intégrations](/integrations/) — utiliser un abonnement Claude ou Cursor comme fournisseur
|
||||
- [Serveurs MCP](/mcp/) — ajouter des outils supplémentaires aux agents
|
||||
- [Utilisation et quotas](/usage/) — suivre votre consommation
|
||||
|
||||
@@ -12,7 +12,7 @@ Pour écrire vos propres skills, voir [Skills](/skills/).
|
||||
## Installer un skill
|
||||
|
||||
1. Ouvrez le catalogue.
|
||||
2. Parcourez les sources intégrées — le dépôt de skills Anthropic et le registre communautaire ClawdHub — ou lancez une recherche.
|
||||
2. Parcourez les sources intégrées — comme le dépôt de skills Anthropic — ou lancez une recherche.
|
||||
3. Choisissez un skill et installez-le.
|
||||
4. Choisissez où l’installer : pour tout ce que vous faites, ou seulement pour le projet actuel.
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Integrations
|
||||
description: Use your Claude or Cursor subscription as a provider.
|
||||
---
|
||||
|
||||
# Integrations
|
||||
|
||||
An integration is a small plugin that adds a provider to OpenChamber using a subscription you already have. You manage them at **Settings → Integrations**.
|
||||
|
||||
> **Experimental feature.** We aim to respect provider policies, but account restrictions and suspensions remain each provider's decision. Use integrations at your own risk.
|
||||
|
||||
Available integrations:
|
||||
|
||||
- **Claude Code** — your Claude Pro or Max plan, no API keys
|
||||
- **Cursor** — the model limits of your Cursor plan
|
||||
|
||||
## Install an integration
|
||||
|
||||
1. Open **Settings → Integrations**.
|
||||
2. Find the integration and choose **Install**.
|
||||
3. Restart OpenCode when asked — the provider appears after the restart.
|
||||
4. Choose **Set up** and sign in. The models then appear in the chat model picker.
|
||||
|
||||
Integrations install for your user, so they work in every project. You can update or remove them from the same card at any time.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code uses your Claude Pro or Max plan — no API keys and no separate Claude app.
|
||||
|
||||
1. Install the integration (above).
|
||||
2. Choose **Set up** and sign in. If you don't have the Claude Code CLI yet, setup offers to install it first and then sign you in.
|
||||
|
||||
Claude Code is the only integration here that requires its provider CLI to be installed and signed in. Cursor does not require its CLI.
|
||||
|
||||
**How your Claude account stays safe:** this integration uses Anthropic's official Claude Agent SDK and your installed Claude Code CLI. It does not hijack OAuth, extract or replay browser tokens, impersonate an unsupported client, or bypass Anthropic's authentication flow. It stays on Anthropic's supported access path, so it does not carry the account-ban risk of token hijacking or unauthorized authentication workarounds.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor makes the models included in your Cursor plan available in OpenChamber.
|
||||
|
||||
1. Install the integration (above).
|
||||
2. Choose **Set up**, open the link, and approve access in your browser. No API key is required. The model list loads automatically after you sign in.
|
||||
|
||||
## Update or remove
|
||||
|
||||
- **Update** installs the latest published version of the plugin.
|
||||
- **Remove** deletes the plugin from your OpenCode config. The provider stops loading after OpenCode refreshes.
|
||||
|
||||
If a card says the entries need manual management, choose **Manage plugins** and clean up the duplicates there.
|
||||
|
||||
## Related
|
||||
|
||||
- [Providers, Models & Agents](/providers/) — connect other providers and pick models
|
||||
- [Usage & Quotas](/usage/) — track how much you've used
|
||||
@@ -28,7 +28,7 @@ description: エージェントがチャットから OpenChamber のセッショ
|
||||
|
||||
## ツールを有効または無効にする
|
||||
|
||||
**設定 → 一般 → OpenCode CLI** を開き、**エージェント制御ツール**を変更して、**Save + Reload** を選択します。この設定は、管理対象の OpenCode サーバーが再起動した後に反映されます。
|
||||
**設定 → 一般 → OpenChamber ツール** を開き、**エージェント制御ツール**を変更します。この設定は、管理対象の OpenCode サーバーが再起動すると反映されます。再起動は OpenChamber が **Apply & Restart** として案内します。
|
||||
|
||||
OpenChamber が `OPENCODE_HOST` または skip-start で外部 OpenCode サーバーに接続している場合や、VS Code 拡張機能内では、このツールを利用できません。OpenChamber が管理する OpenCode サーバーを使用するデスクトップ版と Web 版では自動的に利用できます。
|
||||
|
||||
@@ -37,3 +37,4 @@ OpenChamber が `OPENCODE_HOST` または skip-start で外部 OpenCode サー
|
||||
- [スケジュールタスク](/ja/scheduled-tasks/)
|
||||
- [Worktree セッション](/ja/worktrees/)
|
||||
- [セッションゴール](/ja/session-goals/)
|
||||
- [ブラウザパネル](/ja/desktop-browser/) — ページを見て操作するための OpenChamber Web ツール
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: デスクトップブラウザ
|
||||
description: デスクトップアプリ内で任意のページを開き、検査とコンソール取得を使います。
|
||||
title: ブラウザパネル
|
||||
description: アプリ内で任意のページを開き、注釈を付け、エージェントに操作させます。
|
||||
---
|
||||
|
||||
# デスクトップブラウザ
|
||||
# ブラウザパネル
|
||||
|
||||
デスクトップアプリには組み込みブラウザがあります。チャットのすぐ横で任意のページを開き、要素を指して質問したり、ページのコンソールを取得したりできます。アプリヘッダーの地球儀ボタンから開きます。
|
||||
ブラウザパネルはチャットのすぐ隣に任意のページを開きます。ヘッダーの地球儀ボタンから開いてください。
|
||||
|
||||
> デスクトップブラウザは**デスクトップ専用**機能です。Web では、[プレビュー](/preview/) パネルがローカル開発サーバー向けに同じ検査・コンソールツールを提供します。
|
||||
デスクトップアプリでは本物のブラウザです。ログイン状態は保持され、ホットリロードが動き、開発者ツールはワンクリックで開けます。ブラウザのタブでもページの表示はできますが、中を覗くことはできません。以下の注釈ツールはデスクトップ専用です。
|
||||
|
||||
## 検査して注釈を付ける
|
||||
ここで開いたページは、カメラ・マイク・位置情報を使えません。これらの要求は拒否されます。
|
||||
|
||||
**inspect** をオンにして、ページ上の任意の要素をクリックします。OpenChamber はその要素について、何であるか、スタイル、位置、スクリーンショットを含むメモを取得し、チャットメッセージに添付します。エージェントに「この要素、ここ」と伝える最短の方法です。
|
||||
## ツールバー
|
||||
|
||||
## コンソール取得
|
||||
アドレスバーはこのプロジェクトで開いたページを覚えていて、入力中に候補として出します。アドレスの一部でもページタイトルの一部でも一致します。矢印キーで候補を移動し、Enter で選択中の候補を開き、行のボタンでその候補を消せます。
|
||||
|
||||
ブラウザはページのコンソール出力(エラー、警告、ログ)を集めるので、開発者ツールを開かずにフィルターして読めます。
|
||||
隣には **再読み込み** があり、変更がどうしても反映されないときのためにキャッシュを無視する **強制再読み込み**、そしてページだけを拡大縮小するズーム操作も並びます。
|
||||
|
||||
**Cookie を消去** と **キャッシュを消去** はこのパネルにだけ効きます。OpenChamber のセッションや他のウィンドウには影響しません。
|
||||
|
||||
## ページに注釈を付ける
|
||||
|
||||
**注釈** を押すと、ページの上に3つのツールを備えたバーが表示されます。
|
||||
|
||||
- **要素** — 要素をクリックします。別の要素をクリックすると選択が移り、同じ要素をもう一度クリックすると解除されます。
|
||||
- **範囲** — 複数の要素にまたがる話をしたいときは、領域をドラッグで囲みます。
|
||||
- **描画** — ページの上にフリーハンドで描きます。
|
||||
|
||||
印の隣に現れる入力欄に希望を書き、**添付** を押します。Enter でも送れます。チャットメッセージには、印を付けた内容、あなたのメモ、表示中のページに印を描き込んだスクリーンショットを含むカードが付きます。「このボタン、もう少し角を丸く」と言えば済み、場所を説明する必要はありません。
|
||||
|
||||
ページ自体は変更されません。注釈はそこにあるものに印を付けるだけです。`Esc` で取り消してツールバーを閉じます。
|
||||
|
||||
## エージェントに操作させる
|
||||
|
||||
エージェントはブラウザパネルを自分で使えます。ページを開き、内容を読み、クリックし、文字を入力し、スクロールし、モバイル・タブレット・デスクトップのレイアウトを切り替えて、自分の作業をあなたに頼まず自分で確認します。その様子はパネルで見えます。
|
||||
|
||||
エージェントがページ内で任意のコードを実行することはできません。ブラウザは実際のログイン状態を保持しているため、上記の操作に限定されています。
|
||||
|
||||
見ている内容をプロジェクト内の `.openchamber/screenshots/` に画像として保存し、返答の中で見せることもできます。ビフォー・アフターができるのはこのためで、ファイルはその後もプルリクエストに添付できる形で残ります。
|
||||
|
||||
ブラウザ操作は **OpenChamber Web ツール** で、**設定 → 一般 → OpenChamber ツール** から単独でオン・オフできます。
|
||||
|
||||
これにはデスクトップアプリが必要です。ブラウザのタブに表示したページは操作できません。
|
||||
|
||||
## 開発者ツール
|
||||
|
||||
バーのターミナルボタンを押すと、そのページに対する Chromium 本来の開発者ツールが開きます。コンソール、ネットワーク、要素など、期待どおりのものがすべて使えます。
|
||||
|
||||
## 関連
|
||||
|
||||
- [プレビューと開発サーバー](/preview/) — ローカル開発サーバー向けの同じツール
|
||||
- [プレビューと開発サーバー](/preview/) — リモートマシン上のものも含め、実行中のアプリを開く
|
||||
- [エージェント制御ツール](/ja/agent-control-tool/) — チャットからセッション・worktree・スケジュールタスクを扱う
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: 統合機能
|
||||
description: Claude または Cursor のサブスクリプションをプロバイダーとして使う。
|
||||
---
|
||||
|
||||
# 統合機能
|
||||
|
||||
統合機能(インテグレーション)は、すでに持っているサブスクリプションを使って OpenChamber にプロバイダーを追加する小さなプラグインです。**Settings → Integrations** で管理します。
|
||||
|
||||
> **実験的な機能。** プロバイダーの方針を尊重するよう努めていますが、アカウントの制限や停止は各プロバイダーの判断に委ねられます。自己責任で連携を使用してください。
|
||||
|
||||
利用できる統合機能:
|
||||
|
||||
- **Claude Code** — Claude Pro または Max プラン、API キー不要
|
||||
- **Cursor** — Cursor プランのモデル利用枠
|
||||
|
||||
## 統合機能をインストールする
|
||||
|
||||
1. **Settings → Integrations** を開きます。
|
||||
2. 統合機能を見つけて **Install** を選びます。
|
||||
3. 求められたら OpenCode を再起動します — 再起動後にプロバイダーが現れます。
|
||||
4. **Set up** を選んでサインインします。するとチャットのモデル選択にモデルが表示されます。
|
||||
|
||||
統合機能はユーザー単位でインストールされるため、すべてのプロジェクトで使えます。同じカードからいつでも更新や削除ができます。
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code は Claude Pro または Max プランを使います — API キーも Claude アプリも不要です。
|
||||
|
||||
1. 統合機能をインストールします(上記)。
|
||||
2. **Set up** を選んでサインインします。Claude Code CLI がまだない場合は、セットアップがまずインストールを提案し、その後サインインします。
|
||||
|
||||
Claude Code は、ここで唯一プロバイダーの CLI のインストールとサインインを必要とする統合機能です。Cursor は CLI を必要としません。
|
||||
|
||||
**Claude アカウントが守られる仕組み:** この統合機能は Anthropic の公式 Claude Agent SDK と、インストール済みの Claude Code CLI を使用します。OAuth の乗っ取り、ブラウザートークンの抽出や再生、未対応クライアントへの偽装、Anthropic の認証フローの回避は一切行いません。Anthropic がサポートする正規のアクセス経路を使うため、トークン乗っ取りや不正な認証の回避につきもののアカウント停止リスクはありません。
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor は Cursor プランに含まれるモデルを OpenChamber で使えるようにします。
|
||||
|
||||
1. 統合機能をインストールします(上記)。
|
||||
2. **Set up** を選び、リンクを開いてブラウザーでアクセスを許可します。API キーは不要です。サインイン後、モデル一覧は自動的に読み込まれます。
|
||||
|
||||
## 更新と削除
|
||||
|
||||
- **Update** はプラグインの最新の公開バージョンをインストールします。
|
||||
- **Remove** は OpenCode の設定からプラグインを削除します。OpenCode が再読み込みされるとプロバイダーは読み込まれなくなります。
|
||||
|
||||
カードに手動での管理が必要だと表示された場合は、**Manage plugins** を選んで重複を整理してください。
|
||||
|
||||
## 関連情報
|
||||
|
||||
- [プロバイダー、モデル、エージェント](/ja/providers/) — 他のプロバイダーの接続とモデルの選択
|
||||
- [使用量とクォータ](/ja/usage/) — 利用量を追跡
|
||||
@@ -1,32 +1,35 @@
|
||||
---
|
||||
title: プレビューと開発サーバー
|
||||
description: 実行中の開発サーバーを OpenChamber 内で開きます。
|
||||
description: 実行中の開発サーバーを OpenChamber の中で開きます。
|
||||
---
|
||||
|
||||
# プレビューと開発サーバー
|
||||
|
||||
開発サーバーを起動すると、OpenChamber は別のブラウザタブではなくアプリ内で直接開けます。サイトをチャットの横で見ながら、コンソールを取得し、要素を指して質問できます。
|
||||
開発サーバーを起動すると、OpenChamber は別のブラウザタブではなくアプリ内でそれを開けます。チャットの隣にサイトを表示したまま、要素を指し示して質問できます。
|
||||
|
||||
## プレビューを開く
|
||||
## 開発サーバーを開く
|
||||
|
||||
OpenChamber はターミナル出力からローカルアドレスを監視します(Vite、Next.js、Astro などが表示する `Local:` 行)。見つけると次のことができます。
|
||||
ヘッダーの地球儀ボタンからブラウザパネルを開きます。開発サーバーがすでに動いていれば一覧に表示され、クリックひとつで開けます。OpenChamber はマシン上で実際に待ち受けているものから見つけるので、どうやって起動したかに関係なく機能します。
|
||||
|
||||
- ターミナルに **Open preview** ボタンが表示されます
|
||||
- 自動オープンを有効にした [プロジェクトアクション](/project-actions/) が開きます
|
||||
- チャットメッセージ内のローカルリンクからも開けます
|
||||
次の場合にも開発サーバーは自動で開きます。
|
||||
|
||||
サイトはサイドパネルに読み込まれます。プレビューできるのはローカルアドレス(あなたのマシン上)のみです。
|
||||
- ターミナルのローカルアドレスで **プレビューを開く** を押したとき
|
||||
- 自動オープンを有効にした[プロジェクトアクション](/project-actions/)が起動したとき
|
||||
- チャットメッセージ内のローカルリンクをたどったとき
|
||||
|
||||
## コンソールと検査
|
||||
アドレスはいつでも自分で入力できます。`localhost:5173` のようにスキームを省いた入力は `http://` として扱われます。
|
||||
|
||||
プレビューパネルでは次のことができます。
|
||||
## リモートの OpenChamber を使う場合
|
||||
|
||||
- ページの **console** を見る — エラー、警告、ログを好きなようにフィルターできます
|
||||
- **inspect** をオンにし、任意の要素をクリックして、そのメモ(セレクター、スタイル、位置、スクリーンショット)をそのままチャットへ送る
|
||||
OpenChamber が別のマシンで動いているとき、開発サーバーも*そちら*のマシンにあります。手元のノートPCの `localhost` はまったく別の場所を指します。デスクトップアプリはこれを引き受けます。ローカルポートを開いてリモートの開発サーバーまで接続を通すので、ページは普通に読み込まれ、ホットリロードも開発者ツールも動きます。入力するアドレスは期待どおりのままで、裏側の仕組みが邪魔をすることはありません。
|
||||
|
||||
これは「このボタン、ここ」とエージェントに伝える最速の方法です。
|
||||
これにはデスクトップアプリが必要です。ブラウザのタブでは、自分のマシン上の開発サーバーだけを開けます。
|
||||
|
||||
## ページに注釈を付ける
|
||||
|
||||
要素を指し示す、ページに描き込む、それらをまとめてチャットへ送る方法は[ブラウザパネル](/desktop-browser/)を参照してください。
|
||||
|
||||
## 関連
|
||||
|
||||
- [プロジェクトアクション](/project-actions/) — サーバー起動時に自動で開く
|
||||
- [デスクトップブラウザ](/desktop-browser/) — デスクトップで任意のページに同じツールを使う
|
||||
- [プロジェクトアクション](/project-actions/) — 起動時にサーバーを自動で開く
|
||||
- [ブラウザパネル](/desktop-browser/) — ページへの注釈とエージェントによる操作
|
||||
|
||||
@@ -45,5 +45,6 @@ OpenChamber が何かを行うには、少なくとも 1 つの AI プロバイ
|
||||
|
||||
## 関連
|
||||
|
||||
- [統合機能](/integrations/) — Claude または Cursor のサブスクリプションをプロバイダーとして使う
|
||||
- [MCP サーバー](/mcp/) — エージェントに追加ツールを加える
|
||||
- [使用量とクォータ](/usage/) — 使った量を追跡する
|
||||
|
||||
@@ -12,7 +12,7 @@ Skills Catalog では、自分で書く代わりに、他の人が公開した
|
||||
## スキルをインストールする
|
||||
|
||||
1. カタログを開きます。
|
||||
2. 組み込みソース(Anthropic skills repo と ClawdHub community registry)を閲覧するか、検索します。
|
||||
2. 組み込みソース(Anthropic skills repo など)を閲覧するか、検索します。
|
||||
3. スキルを選び、インストールします。
|
||||
4. インストール先を選びます。すべての作業で使うか、現在のプロジェクトだけで使うかです。
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ description: 에이전트가 채팅에서 OpenChamber 세션, worktree, 예약
|
||||
|
||||
## 도구 켜기 또는 끄기
|
||||
|
||||
**설정 → 일반 → OpenCode CLI**를 열고 **에이전트 제어 도구**를 변경한 다음 **Save + Reload**를 선택하세요. 관리형 OpenCode 서버가 다시 시작된 후 설정이 적용됩니다.
|
||||
**설정 → 일반 → OpenChamber 도구**를 열고 **에이전트 제어 도구**를 변경하세요. 설정은 관리형 OpenCode 서버가 다시 시작되면 적용되며, OpenChamber가 **Apply & Restart** 로 안내합니다.
|
||||
|
||||
OpenChamber가 `OPENCODE_HOST` 또는 skip-start를 통해 외부 OpenCode 서버에 연결된 경우와 VS Code 확장에서는 이 도구를 사용할 수 없습니다. OpenChamber의 관리형 OpenCode 서버를 사용하는 데스크톱 및 웹 설치에서는 자동으로 지원됩니다.
|
||||
|
||||
@@ -37,3 +37,4 @@ OpenChamber가 `OPENCODE_HOST` 또는 skip-start를 통해 외부 OpenCode 서
|
||||
- [예약 작업](/ko/scheduled-tasks/)
|
||||
- [Worktree 세션](/ko/worktrees/)
|
||||
- [세션 목표](/ko/session-goals/)
|
||||
- [브라우저 패널](/ko/desktop-browser/) — 페이지를 보고 조작하는 OpenChamber Web 도구
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: 데스크톱 브라우저
|
||||
description: 검사 및 콘솔 캡처 기능과 함께 데스크톱 앱 안에서 임의의 페이지를 탐색하세요.
|
||||
title: 브라우저 패널
|
||||
description: 앱 안에서 아무 페이지나 열고 주석을 달며 에이전트가 조작하게 합니다.
|
||||
---
|
||||
|
||||
# 데스크톱 브라우저
|
||||
# 브라우저 패널
|
||||
|
||||
데스크톱 앱에는 내장 브라우저가 있어 채팅 바로 옆에서 임의의 페이지를 열고, 요소를 가리켜 질문하고, 페이지의 콘솔을 캡처할 수 있습니다. 앱 헤더의 지구본 버튼에서 엽니다.
|
||||
브라우저 패널은 채팅 바로 옆에 아무 페이지나 엽니다. 앱 헤더의 지구본 버튼으로 여세요.
|
||||
|
||||
> 데스크톱 브라우저는 **데스크톱 전용** 기능입니다. 웹에서는 [미리보기](/ko/preview/) 패널이 로컬 개발 서버에 대해 동일한 검사 및 콘솔 도구를 제공합니다.
|
||||
데스크톱 앱에서는 진짜 브라우저입니다. 로그인 상태가 유지되고 핫 리로드가 동작하며 개발자 도구도 클릭 한 번이면 열립니다. 브라우저 탭에서도 페이지를 보여줄 수는 있지만 내부를 들여다볼 수는 없습니다. 아래 주석 도구는 데스크톱 전용입니다.
|
||||
|
||||
## 검사 및 주석
|
||||
여기서 연 페이지는 카메라, 마이크, 위치를 사용할 수 없습니다. 그런 요청은 거부됩니다.
|
||||
|
||||
**inspect**를 켜고 페이지의 임의 요소를 클릭합니다. OpenChamber가 그것이 무엇인지, 스타일, 위치, 스크린샷을 담은 메모를 캡처해 채팅 메시지에 첨부합니다. 에이전트에게 "바로 여기 이 요소"라고 알리는 가장 빠른 방법입니다.
|
||||
## 도구 모음
|
||||
|
||||
## 콘솔 캡처
|
||||
주소창은 이 프로젝트에서 열었던 페이지를 기억해 두었다가 입력하는 동안 제안합니다. 주소의 일부나 페이지 제목의 일부와 맞춰 봅니다. 화살표 키로 목록을 이동하고, Enter로 선택한 항목을 열고, 행의 버튼으로 목록에서 지웁니다.
|
||||
|
||||
브라우저는 페이지의 콘솔 출력(오류, 경고, 로그)을 수집하므로 개발자 도구를 열지 않고도 필터링하여 읽을 수 있습니다.
|
||||
그 옆에는 **새로 고침**이 있고, 변경이 도무지 반영되지 않을 때 캐시를 무시하는 **강력 새로 고침**, 그리고 페이지만 확대·축소하는 확대 조절이 있습니다.
|
||||
|
||||
## 관련 항목
|
||||
**쿠키 지우기**와 **캐시 데이터 지우기**는 이 패널에만 적용됩니다. OpenChamber 세션이나 다른 창은 그대로입니다.
|
||||
|
||||
- [Preview & Dev Servers](/ko/preview/) — 로컬 개발 서버에 대한 동일한 도구
|
||||
## 페이지에 주석 달기
|
||||
|
||||
**주석** 을 누르면 페이지 위에 세 가지 도구가 있는 막대가 나타납니다.
|
||||
|
||||
- **요소** — 요소를 클릭합니다. 다른 요소를 클릭하면 선택이 옮겨가고, 같은 요소를 다시 클릭하면 해제됩니다.
|
||||
- **영역** — 여러 요소에 걸친 이야기를 할 때는 해당 부분을 드래그해 감쌉니다.
|
||||
- **그리기** — 페이지 위에 자유롭게 스케치합니다.
|
||||
|
||||
표시 옆에 나타나는 입력란에 원하는 내용을 적고 **첨부** 를 누르세요. Enter 로도 됩니다. 채팅 메시지에 표시한 모든 것, 남긴 메모, 표시 중인 페이지에 표시를 그려 넣은 스크린샷이 담긴 카드가 붙습니다. 위치를 설명하는 대신 "이 버튼, 조금 더 둥글게"라고 말하면 됩니다.
|
||||
|
||||
페이지 자체는 변경되지 않습니다. 주석은 있는 것을 표시할 뿐입니다. `Esc` 로 취소하고 도구 막대를 닫습니다.
|
||||
|
||||
## 에이전트에게 조작 맡기기
|
||||
|
||||
에이전트는 브라우저 패널을 직접 쓸 수 있습니다. 페이지를 열고, 내용을 읽고, 클릭하고, 입력하고, 스크롤하고, 모바일·태블릿·데스크톱 레이아웃을 바꿔 가며 자기 작업을 여러분에게 부탁하지 않고 스스로 확인합니다. 그 과정은 패널에서 보입니다.
|
||||
|
||||
에이전트가 페이지에서 임의의 코드를 실행할 수는 없습니다. 브라우저가 실제 로그인 상태를 유지하므로 위에 적힌 동작으로만 제한됩니다.
|
||||
|
||||
보고 있는 화면을 프로젝트의 `.openchamber/screenshots/` 에 이미지로 저장하고 답변에서 보여 줄 수도 있습니다. 전후 비교가 가능한 이유가 이것이며, 파일은 그대로 남아 풀 리퀘스트에 첨부할 수 있습니다.
|
||||
|
||||
브라우저 동작은 **OpenChamber Web 도구**이며, **설정 → 일반 → OpenChamber 도구** 에서 따로 켜고 끌 수 있습니다.
|
||||
|
||||
이 기능에는 데스크톱 앱이 필요합니다. 브라우저 탭에 표시된 페이지는 조작할 수 없습니다.
|
||||
|
||||
## 개발자 도구
|
||||
|
||||
막대의 터미널 버튼을 누르면 해당 페이지에 대한 Chromium 자체 개발자 도구가 열립니다. 콘솔, 네트워크, 요소 등 기대하는 모든 기능을 쓸 수 있습니다.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [미리보기와 개발 서버](/preview/) — 원격 컴퓨터의 것을 포함해 실행 중인 앱 열기
|
||||
- [에이전트 제어 도구](/ko/agent-control-tool/) — 채팅에서 세션, worktree, 예약 작업 다루기
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: 통합 기능
|
||||
description: Claude 또는 Cursor 구독을 공급자로 사용하세요.
|
||||
---
|
||||
|
||||
# 통합 기능
|
||||
|
||||
통합 기능(인테그레이션)은 이미 가지고 있는 구독을 사용해 OpenChamber에 공급자를 추가하는 작은 플러그인입니다. **Settings → Integrations**에서 관리합니다.
|
||||
|
||||
> **실험 단계 기능.** 프로바이더 정책을 존중하려 노력하지만, 계정 제한과 정지는 각 프로바이더의 결정입니다. 본인의 책임 아래 통합 기능을 사용하세요.
|
||||
|
||||
사용 가능한 통합 기능:
|
||||
|
||||
- **Claude Code** — Claude Pro 또는 Max 플랜, API 키 불필요
|
||||
- **Cursor** — Cursor 플랜의 모델 한도
|
||||
|
||||
## 통합 기능 설치
|
||||
|
||||
1. **Settings → Integrations**를 엽니다.
|
||||
2. 통합 기능을 찾아 **Install**을 선택합니다.
|
||||
3. 요청되면 OpenCode를 다시 시작합니다 — 재시작 후 공급자가 나타납니다.
|
||||
4. **Set up**를 선택하고 로그인합니다. 그러면 채팅의 모델 선택기에 모델이 나타납니다.
|
||||
|
||||
통합 기능은 사용자 단위로 설치되므로 모든 프로젝트에서 작동합니다. 같은 카드에서 언제든 업데이트하거나 제거할 수 있습니다.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code는 Claude Pro 또는 Max 플랜을 사용합니다 — API 키도 별도의 Claude 앱도 필요 없습니다.
|
||||
|
||||
1. 통합 기능을 설치합니다(위 참고).
|
||||
2. **Set up**를 선택하고 로그인합니다. Claude Code CLI가 아직 없으면 설정에서 먼저 설치를 제안한 뒤 로그인을 진행합니다.
|
||||
|
||||
Claude Code는 여기에서 유일하게 공급자 CLI 설치와 로그인을 필요로 하는 통합 기능입니다. Cursor는 CLI가 필요 없습니다.
|
||||
|
||||
**Claude 계정이 안전하게 유지되는 방식:** 이 통합 기능은 Anthropic의 공식 Claude Agent SDK와 설치된 Claude Code CLI를 사용합니다. OAuth 탈취, 브라우저 토큰 추출·재사용, 지원되지 않는 클라이언트로의 위장, Anthropic 인증 우회를 하지 않습니다. Anthropic이 지원하는 정상 경로를 사용하므로 토큰 탈취나 비인가 인증 우회에 따른 계정 정지 위험이 없습니다.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor는 Cursor 플랜에 포함된 모델을 OpenChamber에서 사용할 수 있게 합니다.
|
||||
|
||||
1. 통합 기능을 설치합니다(위 참고).
|
||||
2. **Set up**를 선택하고 링크를 열어 브라우저에서 접근을 승인합니다. API 키는 필요 없습니다. 로그인 후 모델 목록이 자동으로 로드됩니다.
|
||||
|
||||
## 업데이트 및 제거
|
||||
|
||||
- **Update**는 플러그인의 최신 공개 버전을 설치합니다.
|
||||
- **Remove**는 OpenCode 설정에서 플러그인을 삭제합니다. OpenCode가 다시 로드되면 공급자는 더 이상 로드되지 않습니다.
|
||||
|
||||
카드에 항목을 수동으로 관리해야 한다고 표시되면 **Manage plugins**를 선택해 중복 항목을 정리하세요.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [공급자, 모델, 에이전트](/ko/providers/) — 다른 공급자 연결과 모델 선택
|
||||
- [사용량 및 할당량](/ko/usage/) — 사용량 추적
|
||||
@@ -1,32 +1,35 @@
|
||||
---
|
||||
title: 미리보기 및 개발 서버
|
||||
description: 실행 중인 개발 서버를 OpenChamber 안에서 여세요.
|
||||
title: 미리보기와 개발 서버
|
||||
description: 실행 중인 개발 서버를 OpenChamber 안에서 엽니다.
|
||||
---
|
||||
|
||||
# 미리보기 및 개발 서버
|
||||
# 미리보기와 개발 서버
|
||||
|
||||
개발 서버를 시작하면 OpenChamber는 별도의 브라우저 탭이 아니라 앱 안에서 바로 열 수 있습니다. 그래서 채팅 옆에서 사이트를 보고, 콘솔을 캡처하고, 요소를 가리켜 질문할 수 있습니다.
|
||||
개발 서버를 띄우면 OpenChamber가 별도의 브라우저 탭 대신 앱 안에서 바로 열어 줍니다. 채팅 옆에 사이트를 두고 요소를 가리키며 물어볼 수 있습니다.
|
||||
|
||||
## 미리보기 열기
|
||||
## 개발 서버 열기
|
||||
|
||||
OpenChamber는 터미널 출력에서 로컬 주소(Vite, Next.js, Astro 같은 도구가 출력하는 `Local:` 줄)를 감시합니다. 발견하면 다음과 같이 동작합니다.
|
||||
앱 헤더의 지구본 버튼으로 브라우저 패널을 엽니다. 개발 서버가 이미 실행 중이면 목록에 나타나고 클릭 한 번으로 열립니다. OpenChamber는 컴퓨터에서 실제로 수신 대기 중인 것을 보고 찾아내므로, 어떻게 실행했든 상관없이 동작합니다.
|
||||
|
||||
- 터미널에 **Open preview** 버튼이 나타납니다
|
||||
- auto-open이 켜진 [프로젝트 액션](/ko/project-actions/)이 대신 열어줍니다
|
||||
- 채팅 메시지의 로컬 링크로도 열 수 있습니다
|
||||
다음 경우에도 개발 서버가 자동으로 열립니다.
|
||||
|
||||
사이트는 사이드 패널에 로드됩니다. 로컬 주소(사용자 자신의 컴퓨터)만 미리볼 수 있습니다.
|
||||
- 터미널의 로컬 주소에서 **미리보기 열기** 를 누를 때
|
||||
- 자동 열기를 켠 [프로젝트 작업](/project-actions/)이 서버를 시작할 때
|
||||
- 채팅 메시지의 로컬 링크를 따라갈 때
|
||||
|
||||
## 콘솔과 검사
|
||||
주소는 언제든 직접 입력할 수 있습니다. `localhost:5173` 처럼 스킴을 생략하면 `http://` 로 처리됩니다.
|
||||
|
||||
미리보기 패널에서 다음을 할 수 있습니다.
|
||||
## 원격 OpenChamber와 함께 쓰기
|
||||
|
||||
- 페이지의 **console**(오류, 경고, 로그)을 원하는 대로 필터링하여 확인
|
||||
- **inspect**를 켜고 임의의 요소를 클릭한 뒤 그에 대한 메모(선택자, 스타일, 위치, 스크린샷)를 바로 채팅으로 전송
|
||||
OpenChamber가 다른 컴퓨터에서 실행 중이면 개발 서버도 *그* 컴퓨터에 있습니다. 노트북의 `localhost`는 전혀 다른 곳을 가리키죠. 데스크톱 앱이 이를 대신 처리합니다. 로컬 포트를 열어 원격 개발 서버까지 연결을 이어 주므로 페이지가 평소처럼 로드되고 핫 리로드와 개발자 도구도 동작합니다. 여러분은 기대한 주소를 그대로 입력하면 되고, 내부 배관은 눈에 띄지 않습니다.
|
||||
|
||||
이것은 설명 없이 에이전트에게 "여기 이 버튼"이라고 알리는 가장 빠른 방법입니다.
|
||||
이 기능에는 데스크톱 앱이 필요합니다. 브라우저 탭에서는 자신의 컴퓨터에 있는 개발 서버만 열 수 있습니다.
|
||||
|
||||
## 관련 항목
|
||||
## 페이지에 주석 달기
|
||||
|
||||
- [Project Actions](/ko/project-actions/) — 서버를 시작할 때 자동으로 열기
|
||||
- [Desktop Browser](/ko/desktop-browser/) — 데스크톱에서 임의의 페이지에 동일한 도구 사용
|
||||
요소를 가리키고, 페이지에 그리고, 스타일 변경을 시험해 보고, 이 모두를 채팅으로 보내는 방법은 [브라우저 패널](/desktop-browser/)을 참고하세요.
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [프로젝트 작업](/project-actions/) — 서버 시작 시 자동으로 열기
|
||||
- [브라우저 패널](/desktop-browser/) — 페이지 주석과 에이전트 조작
|
||||
|
||||
@@ -45,5 +45,6 @@ OpenChamber가 무언가를 하려면 먼저 최소한 하나의 AI 공급자가
|
||||
|
||||
## 관련 항목
|
||||
|
||||
- [통합 기능](/ko/integrations/) — Claude 또는 Cursor 구독을 공급자로 사용
|
||||
- [MCP Servers](/ko/mcp/) — 에이전트에 추가 도구를 제공합니다
|
||||
- [Usage & Quotas](/ko/usage/) — 사용량을 추적합니다
|
||||
|
||||
@@ -12,7 +12,7 @@ Skills Catalog를 사용하면 직접 작성하는 대신 다른 사람이 게
|
||||
## 스킬 설치하기
|
||||
|
||||
1. 카탈로그를 엽니다.
|
||||
2. 내장된 소스(Anthropic 스킬 저장소와 ClawdHub 커뮤니티 레지스트리)를 둘러보거나 검색합니다.
|
||||
2. 내장된 소스(예: Anthropic 스킬 저장소)를 둘러보거나 검색합니다.
|
||||
3. 스킬을 선택하고 설치합니다.
|
||||
4. 설치 위치를 선택합니다. 모든 작업에 적용할지, 현재 프로젝트에만 적용할지 선택합니다.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Narzędzie może wyświetlać projekty i preferencje modeli, tworzyć i kontynuo
|
||||
|
||||
## Włączanie i wyłączanie narzędzia
|
||||
|
||||
Otwórz **Ustawienia → Ogólne → OpenCode CLI**, zmień **Narzędzie sterowania dla agentów**, a następnie wybierz **Save + Reload**. Ustawienie zacznie działać po ponownym uruchomieniu zarządzanego serwera OpenCode.
|
||||
Otwórz **Ustawienia → Ogólne → Narzędzia OpenChamber** i zmień **Narzędzie sterowania dla agentów**. Ustawienie zacznie działać po ponownym uruchomieniu zarządzanego serwera OpenCode, które OpenChamber proponuje jako **Apply & Restart**.
|
||||
|
||||
Narzędzie nie jest dostępne, gdy OpenChamber łączy się z zewnętrznym serwerem OpenCode przez `OPENCODE_HOST` lub skip-start, ani w rozszerzeniu VS Code. Instalacje desktopowe i webowe korzystające z serwera OpenCode zarządzanego przez OpenChamber obsługują je automatycznie.
|
||||
|
||||
@@ -37,3 +37,4 @@ Narzędzie nie jest dostępne, gdy OpenChamber łączy się z zewnętrznym serwe
|
||||
- [Zaplanowane zadania](/pl/scheduled-tasks/)
|
||||
- [Sesje worktree](/pl/worktrees/)
|
||||
- [Cele sesji](/pl/session-goals/)
|
||||
- [Panel przeglądarki](/pl/desktop-browser/) — narzędzie OpenChamber Web — oglądanie strony i sterowanie nią
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: Przeglądarka na komputerze
|
||||
description: Przeglądaj dowolną stronę wewnątrz aplikacji na komputerze, z inspekcją i przechwytywaniem konsoli.
|
||||
title: Panel przeglądarki
|
||||
description: Przeglądaj dowolną stronę w aplikacji, dodawaj do niej adnotacje i pozwól agentowi nią sterować.
|
||||
---
|
||||
|
||||
# Przeglądarka na komputerze
|
||||
# Panel przeglądarki
|
||||
|
||||
Aplikacja na komputerze ma wbudowaną przeglądarkę, dzięki czemu możesz otworzyć dowolną stronę tuż obok czatu, wskazywać elementy, aby o nie zapytać, oraz przechwytywać konsolę strony. Otwórz ją z przycisku globusa w nagłówku aplikacji.
|
||||
Panel przeglądarki otwiera dowolną stronę tuż obok czatu. Otwórz go przyciskiem globusa w nagłówku aplikacji.
|
||||
|
||||
> Przeglądarka na komputerze to funkcja **tylko na komputerze**. W wersji webowej panel [podglądu](/pl/preview/) oferuje te same narzędzia inspekcji i konsoli dla Twojego lokalnego serwera deweloperskiego.
|
||||
W aplikacji desktopowej to prawdziwa przeglądarka: twoje logowania są zachowywane, przeładowanie na gorąco działa, a narzędzia deweloperskie są o jedno kliknięcie. W karcie przeglądarki panel wyświetli stronę, ale nie zajrzy do jej wnętrza — poniższe narzędzia adnotacji są dostępne tylko na desktopie.
|
||||
|
||||
## Inspekcja i adnotacje
|
||||
Strony otwarte tutaj nie mogą użyć twojej kamery, mikrofonu ani lokalizacji: takie prośby są odrzucane.
|
||||
|
||||
Włącz **inspect** i kliknij dowolny element na stronie. OpenChamber przechwytuje o nim notatkę — czym jest, jakie ma style, gdzie się znajduje, oraz zrzut ekranu — i dołącza ją do Twojej wiadomości czatu. To najszybszy sposób, by powiedzieć agentowi „ten element, dokładnie tutaj”.
|
||||
## Pasek narzędzi
|
||||
|
||||
## Przechwytywanie konsoli
|
||||
Pasek adresu pamięta strony otwierane w tym projekcie i podpowiada je podczas pisania, dopasowując fragment adresu albo tytułu strony. Strzałki przechodzą po liście, Enter otwiera podświetloną pozycję, a przycisk w wierszu usuwa ją z listy.
|
||||
|
||||
Przeglądarka zbiera wynik konsoli strony — błędy, ostrzeżenia i logi — dzięki czemu możesz go filtrować i czytać bez otwierania narzędzi deweloperskich.
|
||||
Obok jest **odświeżenie**, a także **twarde odświeżenie**, które pomija pamięć podręczną, gdy zmiana uparcie się nie pokazuje, oraz sterowanie powiększeniem działające tylko na stronę.
|
||||
|
||||
**Wyczyść ciasteczka** i **Wyczyść dane w pamięci podręcznej** dotyczą wyłącznie tego panelu. Twoja sesja OpenChamber i pozostałe okna zostają nietknięte.
|
||||
|
||||
## Dodawanie adnotacji
|
||||
|
||||
Naciśnij **Adnotuj** — nad stroną pojawi się pasek z trzema narzędziami:
|
||||
|
||||
- **Element** — kliknij element. Kliknięcie innego przenosi zaznaczenie, ponowne kliknięcie tego samego je zdejmuje.
|
||||
- **Obszar** — obrysuj fragment ramką, gdy chodzi o więcej niż jeden element.
|
||||
- **Rysuj** — szkicuj odręcznie po stronie.
|
||||
|
||||
Napisz, czego oczekujesz, w polu obok swojego oznaczenia i naciśnij **Dołącz** — albo po prostu Enter. Do wiadomości trafi karta ze wszystkim, co zaznaczyłeś, z twoją notatką i ze zrzutem widocznej strony z naniesionymi oznaczeniami — możesz więc powiedzieć „ten przycisk, trochę bardziej zaokrąglony" zamiast opisywać, gdzie jest.
|
||||
|
||||
Sama strona nie jest zmieniana — adnotacja tylko oznacza to, co już tam jest. `Esc` anuluje i zamyka pasek.
|
||||
|
||||
## Sterowanie przez agenta
|
||||
|
||||
Agent może sam korzystać z panelu przeglądarki — otworzyć stronę, odczytać jej zawartość, klikać, wpisywać tekst, przewijać i przełączać układ mobilny, tabletowy i desktopowy — żeby sprawdzić własną pracę zamiast prosić o to ciebie. Zobaczysz to w panelu.
|
||||
|
||||
Agent nie może uruchamiać dowolnego kodu na stronie. Przeglądarka zachowuje twoje prawdziwe logowania, więc ogranicza się do powyższych działań.
|
||||
|
||||
Może też zapisać obraz tego, co widzi, w `.openchamber/screenshots/` w twoim projekcie i pokazać go w odpowiedzi. To właśnie umożliwia porównanie przed i po, a plik zostaje, by dołączyć go do pull requesta.
|
||||
|
||||
Działania w przeglądarce to **narzędzie OpenChamber Web**, które włącza się i wyłącza osobno w **Ustawienia → Ogólne → Narzędzia OpenChamber**.
|
||||
|
||||
Wymaga to aplikacji desktopowej: stroną pokazaną w karcie przeglądarki nie da się sterować.
|
||||
|
||||
## Narzędzia deweloperskie
|
||||
|
||||
Naciśnij przycisk terminala na pasku, aby otworzyć własne narzędzia deweloperskie Chromium dla strony — konsolę, sieć, elementy, wszystko czego oczekujesz.
|
||||
|
||||
## Powiązane
|
||||
|
||||
- [Podgląd i serwery deweloperskie](/pl/preview/) — te same narzędzia dla Twojego lokalnego serwera deweloperskiego
|
||||
- [Podgląd i serwery deweloperskie](/preview/) — otwieranie działającej aplikacji, także na zdalnym komputerze
|
||||
- [Narzędzie sterowania dla agentów](/pl/agent-control-tool/) — sesje, worktree i zaplanowane zadania prosto z czatu
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Integracje
|
||||
description: Używaj subskrypcji Claude lub Cursor jako dostawcy.
|
||||
---
|
||||
|
||||
# Integracje
|
||||
|
||||
Integracja to mała wtyczka, która dodaje dostawcę do OpenChamber na podstawie subskrypcji, którą już masz. Zarządzasz nimi w **Settings → Integrations**.
|
||||
|
||||
> **Funkcja eksperymentalna.** Staramy się przestrzegać zasad dostawców, ale ograniczenia i zawieszenia kont pozostają decyzją każdego dostawcy. Używaj integracji na własne ryzyko.
|
||||
|
||||
Dostępne integracje:
|
||||
|
||||
- **Claude Code** — Twój plan Claude Pro lub Max, bez kluczy API
|
||||
- **Cursor** — limity modeli z Twojego planu Cursor
|
||||
|
||||
## Instalacja integracji
|
||||
|
||||
1. Otwórz **Settings → Integrations**.
|
||||
2. Znajdź integrację i wybierz **Install**.
|
||||
3. Uruchom OpenCode ponownie, gdy o to poproszą — dostawca pojawi się po restarcie.
|
||||
4. Wybierz **Set up** i zaloguj się. Modele pojawią się potem w selektorze modeli na czacie.
|
||||
|
||||
Integracje instalują się dla Twojego użytkownika, więc działają w każdym projekcie. W każdej chwili możesz je zaktualizować lub usunąć z tej samej karty.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code korzysta z Twojego planu Claude Pro lub Max — bez kluczy API i bez osobnej aplikacji Claude.
|
||||
|
||||
1. Zainstaluj integrację (patrz wyżej).
|
||||
2. Wybierz **Set up** i zaloguj się. Jeśli nie masz jeszcze Claude Code CLI, konfiguracja zaoferuje najpierw jego instalację, a potem logowanie.
|
||||
|
||||
Claude Code jest jedyną integracją tutaj, która wymaga zainstalowanego i zalogowanego CLI swojego dostawcy. Cursor nie wymaga swojego CLI.
|
||||
|
||||
**Jak chronione jest Twoje konto Claude:** ta integracja używa oficjalnego Claude Agent SDK od Anthropic i Twojego zainstalowanego Claude Code CLI. Nie przechwytuje OAuth, nie wyodrębnia ani nie odtwarza tokenów przeglądarki, nie podszywa się pod nieobsługiwany klient i nie omija uwierzytelniania Anthropic. Działa na obsługiwanej przez Anthropic ścieżce dostępu, więc nie niesie ryzyka zablokowania konta związanego z przechwytywaniem tokenów lub nieautoryzowanymi obejściami uwierzytelniania.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor udostępnia w OpenChamber modele zawarte w Twoim planie Cursor.
|
||||
|
||||
1. Zainstaluj integrację (patrz wyżej).
|
||||
2. Wybierz **Set up**, otwórz link i zatwierdź dostęp w przeglądarce. Klucz API nie jest potrzebny. Lista modeli wczyta się automatycznie po zalogowaniu.
|
||||
|
||||
## Aktualizacja i usuwanie
|
||||
|
||||
- **Update** instaluje najnowszą opublikowaną wersję wtyczki.
|
||||
- **Remove** usuwa wtyczkę z konfiguracji OpenCode. Dostawca przestanie się ładować po odświeżeniu OpenCode.
|
||||
|
||||
Jeśli karta wskazuje, że wpisy wymagają ręcznego zarządzania, wybierz **Manage plugins** i wyczyść tam duplikaty.
|
||||
|
||||
## Powiązane
|
||||
|
||||
- [Dostawcy, modele i agenci](/pl/providers/) — podłączanie innych dostawców i wybór modeli
|
||||
- [Zużycie i limity](/pl/usage/) — śledź, ile wykorzystałeś
|
||||
@@ -5,28 +5,31 @@ description: Otwórz działający serwer deweloperski wewnątrz OpenChamber.
|
||||
|
||||
# Podgląd i serwery deweloperskie
|
||||
|
||||
Gdy uruchamiasz serwer deweloperski, OpenChamber może otworzyć go bezpośrednio w aplikacji zamiast w osobnej karcie przeglądarki — dzięki czemu widzisz swoją witrynę obok czatu, przechwytujesz jej konsolę i wskazujesz elementy, aby o nie zapytać.
|
||||
Gdy uruchamiasz serwer deweloperski, OpenChamber może otworzyć go od razu w aplikacji zamiast w osobnej karcie przeglądarki — widzisz swoją stronę obok czatu i możesz wskazywać elementy, żeby o nie zapytać.
|
||||
|
||||
## Otwórz podgląd
|
||||
## Otwieranie serwera deweloperskiego
|
||||
|
||||
OpenChamber obserwuje wynik terminala pod kątem adresu lokalnego (wiersz `Local:`, który drukują narzędzia takie jak Vite, Next.js czy Astro). Gdy go wykryje:
|
||||
Otwórz panel przeglądarki przyciskiem globusa w nagłówku aplikacji. Jeśli serwer już działa, znajdziesz go na liście i otworzysz jednym kliknięciem — OpenChamber rozpoznaje go po tym, co faktycznie nasłuchuje na twoim komputerze, więc działa niezależnie od sposobu uruchomienia.
|
||||
|
||||
- w terminalu pojawia się przycisk **Open preview**
|
||||
- [akcja projektu](/pl/project-actions/) z włączonym auto-open otwiera go za Ciebie
|
||||
- lokalny link w wiadomości czatu również może go otworzyć
|
||||
Serwer otwiera się też sam, gdy:
|
||||
|
||||
Witryna ładuje się w panelu bocznym. Podglądać można wyłącznie adresy lokalne (na Twojej własnej maszynie).
|
||||
- naciśniesz **Otwórz podgląd** przy lokalnym adresie w terminalu
|
||||
- [akcja projektu](/project-actions/) z włączonym automatycznym otwieraniem go uruchomi
|
||||
- klikniesz lokalny odnośnik w wiadomości na czacie
|
||||
|
||||
## Konsola i inspekcja
|
||||
Adres zawsze możesz wpisać ręcznie. Samo `localhost:5173` jest traktowane jako `http://`, więc schematu nie musisz podawać.
|
||||
|
||||
W panelu podglądu możesz:
|
||||
## Praca ze zdalnym OpenChamber
|
||||
|
||||
- obserwować **konsolę** strony — błędy, ostrzeżenia i logi, filtrowane wedle uznania
|
||||
- włączyć **inspect**, kliknąć dowolny element i wysłać o nim notatkę — selektor, style, pozycję i zrzut ekranu — prosto do czatu
|
||||
Gdy OpenChamber działa na innym komputerze, jego serwer deweloperski też jest na *tamtym* komputerze — `localhost` na twoim laptopie prowadzi zupełnie gdzie indziej. Aplikacja desktopowa załatwia to za ciebie: otwiera lokalny port, którym prowadzi połączenie do zdalnego serwera, dzięki czemu strona ładuje się normalnie, z działającym przeładowaniem na gorąco i narzędziami deweloperskimi. Nadal wpisujesz adres, którego się spodziewasz; technikalia nie wchodzą ci w drogę.
|
||||
|
||||
To najszybszy sposób, by powiedzieć agentowi „ten przycisk, tutaj”, bez opisywania go.
|
||||
Wymaga to aplikacji desktopowej. W karcie przeglądarki otworzysz tylko serwery na własnym komputerze.
|
||||
|
||||
## Adnotacje na stronie
|
||||
|
||||
O wskazywaniu elementów, rysowaniu po stronie, przymierzaniu zmian stylów i wysyłaniu tego wszystkiego na czat przeczytasz w [Panelu przeglądarki](/desktop-browser/).
|
||||
|
||||
## Powiązane
|
||||
|
||||
- [Akcje projektu](/pl/project-actions/) — automatycznie otwórz serwer przy uruchomieniu
|
||||
- [Przeglądarka na komputerze](/pl/desktop-browser/) — te same narzędzia dla dowolnej strony, na komputerze
|
||||
- [Akcje projektu](/project-actions/) — automatyczne otwarcie serwera po uruchomieniu
|
||||
- [Panel przeglądarki](/desktop-browser/) — adnotacje stron i sterowanie przez agenta
|
||||
|
||||
@@ -45,5 +45,6 @@ Logowania dostawców są przechowywane przez OpenCode, a nie OpenChamber, więc
|
||||
|
||||
## Powiązane
|
||||
|
||||
- [Integracje](/pl/integrations/) — używaj subskrypcji Claude lub Cursor jako dostawcy
|
||||
- [Serwery MCP](/pl/mcp/) — dodaj agentom dodatkowe narzędzia
|
||||
- [Zużycie i limity](/pl/usage/) — śledź, ile już wykorzystałeś
|
||||
|
||||
@@ -12,7 +12,7 @@ Aby pisać własne skille, zobacz [Skille](/pl/skills/).
|
||||
## Zainstaluj skill
|
||||
|
||||
1. Otwórz katalog.
|
||||
2. Przeglądaj wbudowane źródła — repozytorium skilli Anthropic oraz rejestr społeczności ClawdHub — albo wyszukaj.
|
||||
2. Przeglądaj wbudowane źródła — na przykład repozytorium skilli Anthropic — albo wyszukaj.
|
||||
3. Wybierz skill i zainstaluj go.
|
||||
4. Wybierz, gdzie go zainstalować: dla wszystkiego, co robisz, albo tylko dla bieżącego projektu.
|
||||
|
||||
|
||||
@@ -5,28 +5,31 @@ description: Open a running dev server inside OpenChamber.
|
||||
|
||||
# Preview & Dev Servers
|
||||
|
||||
When you start a dev server, OpenChamber can open it right inside the app instead of a separate browser tab — so you can see your site next to the chat, capture its console, and point at elements to ask about them.
|
||||
When you start a dev server, OpenChamber can open it right inside the app instead of a separate browser tab — so you can see your site next to the chat and point at elements to ask about them.
|
||||
|
||||
## Open a preview
|
||||
## Open a dev server
|
||||
|
||||
OpenChamber watches terminal output for a local address (the `Local:` line that tools like Vite, Next.js, or Astro print). When it spots one:
|
||||
Open the browser panel from the globe button in the app header. If a dev server is already running, it is listed there and one click opens it — OpenChamber finds it by looking at what is actually listening on your machine, so it works no matter how you started it.
|
||||
|
||||
- in the terminal, an **Open preview** button appears
|
||||
- a [project action](/project-actions/) with auto-open turned on opens it for you
|
||||
- a local link in a chat message can open it too
|
||||
A dev server also opens automatically when:
|
||||
|
||||
The site loads in the side panel. Only local addresses (on your own machine) can be previewed.
|
||||
- you press **Open preview** on a local address in the terminal
|
||||
- a [project action](/project-actions/) with auto-open turned on starts one
|
||||
- you follow a local link in a chat message
|
||||
|
||||
## Console and inspect
|
||||
You can always type an address yourself. A bare `localhost:5173` is treated as `http://`, so you do not have to type the scheme.
|
||||
|
||||
In the preview panel you can:
|
||||
## Working with a remote OpenChamber
|
||||
|
||||
- watch the page's **console** — errors, warnings, and logs, filtered however you like
|
||||
- turn on **inspect**, click any element, and send a note about it — selector, styles, position, and a screenshot — straight into chat
|
||||
When OpenChamber runs on another machine, its dev server is on *that* machine — `localhost` on your laptop is somewhere else entirely. The desktop app handles this for you: it opens a local port that carries the connection through to the remote dev server, so the page loads normally, with working hot reload and developer tools. You keep typing the address you expect; the plumbing stays out of your way.
|
||||
|
||||
This is the fastest way to tell the agent "this button, here" without describing it.
|
||||
This needs the desktop app. In a web browser tab, only dev servers on your own machine can be opened.
|
||||
|
||||
## Annotate the page
|
||||
|
||||
See [Browser Panel](/desktop-browser/) for pointing at elements, drawing on the page, and sending it all to chat.
|
||||
|
||||
## Related
|
||||
|
||||
- [Project Actions](/project-actions/) — auto-open a server when you start it
|
||||
- [Desktop Browser](/desktop-browser/) — the same tools for any page, on desktop
|
||||
- [Browser Panel](/desktop-browser/) — annotating pages and letting the agent drive
|
||||
|
||||
@@ -57,5 +57,6 @@ Provider sign-ins are stored by OpenCode, not OpenChamber, so they're shared wit
|
||||
|
||||
## Related
|
||||
|
||||
- [Integrations](/integrations/) — use a Claude or Cursor subscription as a provider
|
||||
- [MCP Servers](/mcp/) — add extra tools for agents
|
||||
- [Usage & Quotas](/usage/) — track how much you've used
|
||||
|
||||
@@ -28,7 +28,7 @@ A ferramenta pode listar projetos e preferências de modelos, criar e continuar
|
||||
|
||||
## Ativar ou desativar a ferramenta
|
||||
|
||||
Abra **Configurações → Geral → OpenCode CLI**, altere **Ferramenta de controle para agentes** e selecione **Save + Reload**. A configuração entra em vigor depois que o servidor OpenCode gerenciado reinicia.
|
||||
Abra **Configurações → Geral → Ferramentas do OpenChamber** e altere **Ferramenta de controle para agentes**. A configuração entra em vigor quando o servidor OpenCode gerenciado reinicia, o que o OpenChamber oferece como **Apply & Restart**.
|
||||
|
||||
A ferramenta não está disponível quando o OpenChamber se conecta a um servidor OpenCode externo por `OPENCODE_HOST` ou skip-start, nem na extensão do VS Code. As instalações desktop e web que usam o servidor OpenCode gerenciado pelo OpenChamber têm suporte automático.
|
||||
|
||||
@@ -37,3 +37,4 @@ A ferramenta não está disponível quando o OpenChamber se conecta a um servido
|
||||
- [Tarefas agendadas](/pt-br/scheduled-tasks/)
|
||||
- [Sessões de worktree](/pt-br/worktrees/)
|
||||
- [Objetivos de sessão](/pt-br/session-goals/)
|
||||
- [Painel do navegador](/pt-br/desktop-browser/) — a ferramenta OpenChamber Web, para ver uma página e conduzi-la
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: Navegador no Desktop
|
||||
description: Navegue por qualquer página dentro do app de desktop, com inspeção e captura de console.
|
||||
title: Painel do navegador
|
||||
description: Navegue em qualquer página dentro do aplicativo, anote-a e deixe o agente conduzi-la.
|
||||
---
|
||||
|
||||
# Navegador no Desktop
|
||||
# Painel do navegador
|
||||
|
||||
O app de desktop tem um navegador integrado para você abrir qualquer página logo ao lado do seu chat, apontar para elementos para perguntar sobre eles e capturar o console da página. Abra-o pelo botão de globo no cabeçalho do app.
|
||||
O painel do navegador abre qualquer página bem ao lado do seu chat. Abra-o pelo botão do globo no cabeçalho.
|
||||
|
||||
> O navegador no desktop é um recurso **apenas para desktop**. Na web, o painel de [preview](/pt-br/preview/) oferece as mesmas ferramentas de inspeção e console para o seu servidor de desenvolvimento local.
|
||||
No aplicativo desktop é um navegador de verdade: seus logins persistem, a recarga a quente funciona e as ferramentas de desenvolvedor estão a um clique. Em uma aba do navegador o painel exibe a página, mas não consegue olhar dentro dela — as ferramentas de anotação abaixo são exclusivas do desktop.
|
||||
|
||||
## Inspecionar e anotar
|
||||
Páginas abertas aqui não podem usar sua câmera, seu microfone nem sua localização: esses pedidos são recusados.
|
||||
|
||||
Ative o **inspect** e clique em qualquer elemento da página. O OpenChamber captura uma nota sobre ele — o que é, seus estilos, onde fica e uma captura de tela — e a anexa à sua mensagem no chat. É a forma mais rápida de dizer ao agente "este elemento, bem aqui".
|
||||
## A barra de ferramentas
|
||||
|
||||
## Captura de console
|
||||
A barra de endereço lembra as páginas que você abriu neste projeto e as oferece enquanto você digita, procurando por parte do endereço ou do título da página. As setas percorrem a lista, Enter abre o item destacado e o botão da linha o remove.
|
||||
|
||||
O navegador coleta a saída do console da página — erros, avisos e logs — para que você possa filtrá-la e lê-la sem abrir as ferramentas de desenvolvedor.
|
||||
Ao lado fica **Recarregar**, junto de uma **recarga forçada** que ignora o cache quando uma mudança teima em não aparecer, e os controles de zoom, que ampliam apenas a página.
|
||||
|
||||
**Limpar cookies** e **Limpar dados em cache** valem só para este painel. Sua sessão do OpenChamber e as outras janelas ficam intactas.
|
||||
|
||||
## Anotar uma página
|
||||
|
||||
Pressione **Anotar** e uma barra aparece sobre a página com três ferramentas:
|
||||
|
||||
- **Elemento** — clique em um elemento. Clicar em outro move a seleção; clicar no mesmo de novo a remove.
|
||||
- **Região** — arraste um retângulo em volta de uma área quando o assunto envolver mais de um elemento.
|
||||
- **Desenhar** — rabisque à mão livre sobre a página.
|
||||
|
||||
Escreva o que quer no campo que aparece ao lado da sua marcação e pressione **Anexar** — ou apenas Enter. Sua mensagem ganha um cartão com tudo o que você marcou, sua nota e uma captura da página visível com suas marcações desenhadas nela — assim você pode dizer "este botão, um pouco mais arredondado" em vez de descrever onde ele está.
|
||||
|
||||
A página em si nunca é modificada — anotar apenas marca o que já está lá. `Esc` cancela e fecha a barra.
|
||||
|
||||
## Deixar o agente conduzir
|
||||
|
||||
O agente pode usar o painel do navegador sozinho — abrir uma página, ler o que há nela, clicar, digitar, rolar e alternar entre layout móvel, de tablet e de desktop — para conferir o próprio trabalho em vez de pedir isso a você. Você vê acontecendo no painel.
|
||||
|
||||
O agente não pode executar código arbitrário na página. O navegador guarda seus logins reais, então ele fica limitado às ações acima.
|
||||
|
||||
Ele também pode salvar uma imagem do que está vendo em `.openchamber/screenshots/` no seu projeto e mostrá-la na resposta. É isso que torna possível um antes e depois, e o arquivo continua lá para anexar a um pull request.
|
||||
|
||||
As ações do navegador são a **ferramenta OpenChamber Web**, que pode ser ligada e desligada por conta própria em **Configurações → Geral → Ferramentas do OpenChamber**.
|
||||
|
||||
Isso exige o aplicativo de desktop: uma página exibida numa aba do navegador não pode ser controlada.
|
||||
|
||||
## Ferramentas de desenvolvedor
|
||||
|
||||
Pressione o botão de terminal na barra para abrir as ferramentas de desenvolvedor do próprio Chromium para a página — console, rede, elementos, tudo o que você espera.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Preview e Servidores de Desenvolvimento](/pt-br/preview/) — as mesmas ferramentas para o seu servidor de desenvolvimento local
|
||||
- [Pré-visualização e servidores de desenvolvimento](/preview/) — abrir seu aplicativo em execução, inclusive em uma máquina remota
|
||||
- [Ferramenta de controle para agentes](/pt-br/agent-control-tool/) — sessões, worktrees e tarefas agendadas pelo chat
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Integrações
|
||||
description: Use sua assinatura Claude ou Cursor como provedor.
|
||||
---
|
||||
|
||||
# Integrações
|
||||
|
||||
Uma integração é um pequeno plugin que adiciona um provedor ao OpenChamber usando uma assinatura que você já tem. Você as gerencia em **Settings → Integrations**.
|
||||
|
||||
> **Recurso experimental.** Buscamos respeitar as políticas dos provedores, mas restrições e suspensões de conta continuam sendo decisão de cada provedor. Use as integrações por sua conta e risco.
|
||||
|
||||
Integrações disponíveis:
|
||||
|
||||
- **Claude Code** — seu plano Claude Pro ou Max, sem chaves de API
|
||||
- **Cursor** — os limites de modelos do seu plano Cursor
|
||||
|
||||
## Instalar uma integração
|
||||
|
||||
1. Abra **Settings → Integrations**.
|
||||
2. Encontre a integração e escolha **Install**.
|
||||
3. Reinicie o OpenCode quando solicitado — o provedor aparece após a reinicialização.
|
||||
4. Escolha **Set up** e faça login. Os modelos aparecem então no seletor de modelos do chat.
|
||||
|
||||
As integrações são instaladas para o seu usuário, então funcionam em todos os projetos. Você pode atualizá-las ou removê-las do mesmo cartão a qualquer momento.
|
||||
|
||||
## Claude Code
|
||||
|
||||
O Claude Code usa seu plano Claude Pro ou Max — sem chaves de API e sem um app Claude separado.
|
||||
|
||||
1. Instale a integração (acima).
|
||||
2. Escolha **Set up** e faça login. Se você ainda não tem a CLI do Claude Code, a configuração oferece instalá-la primeiro e depois fazer login.
|
||||
|
||||
O Claude Code é a única integração aqui que exige que a CLI do provedor esteja instalada e autenticada. Cursor não exige sua CLI.
|
||||
|
||||
**Como sua conta Claude fica protegida:** esta integração usa o Claude Agent SDK oficial da Anthropic e a CLI do Claude Code instalada em sua máquina. Ela não sequestra OAuth, não extrai nem reproduz tokens do navegador, não se passa por um cliente não suportado e não contorna a autenticação da Anthropic. Ela permanece no caminho de acesso suportado pela Anthropic, portanto não traz o risco de banimento de conta associado a sequestro de tokens ou a contornos de autenticação não autorizados.
|
||||
|
||||
## Cursor
|
||||
|
||||
O Cursor torna disponíveis no OpenChamber os modelos incluídos no seu plano Cursor.
|
||||
|
||||
1. Instale a integração (acima).
|
||||
2. Escolha **Set up**, abra o link e autorize o acesso no navegador. Nenhuma chave de API é necessária. A lista de modelos carrega automaticamente após o login.
|
||||
|
||||
## Atualizar ou remover
|
||||
|
||||
- **Update** instala a versão publicada mais recente do plugin.
|
||||
- **Remove** exclui o plugin da sua configuração do OpenCode. O provedor deixa de ser carregado quando o OpenCode é recarregado.
|
||||
|
||||
Se um cartão indicar que as entradas precisam de gerenciamento manual, escolha **Manage plugins** e limpe as duplicatas lá.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Provedores, modelos e agentes](/pt-br/providers/) — conecte outros provedores e escolha modelos
|
||||
- [Uso e cotas](/pt-br/usage/) — acompanhe quanto você usou
|
||||
@@ -1,32 +1,35 @@
|
||||
---
|
||||
title: Preview e Servidores de Desenvolvimento
|
||||
title: Pré-visualização e servidores de desenvolvimento
|
||||
description: Abra um servidor de desenvolvimento em execução dentro do OpenChamber.
|
||||
---
|
||||
|
||||
# Preview e Servidores de Desenvolvimento
|
||||
# Pré-visualização e servidores de desenvolvimento
|
||||
|
||||
Quando você inicia um servidor de desenvolvimento, o OpenChamber pode abri-lo logo dentro do app em vez de uma aba separada do navegador — para que você veja seu site ao lado do chat, capture seu console e aponte para elementos para perguntar sobre eles.
|
||||
Quando você sobe um servidor de desenvolvimento, o OpenChamber pode abri-lo dentro do próprio aplicativo em vez de uma aba separada — assim você vê seu site ao lado do chat e pode apontar para elementos para perguntar sobre eles.
|
||||
|
||||
## Abrir um preview
|
||||
## Abrir um servidor de desenvolvimento
|
||||
|
||||
O OpenChamber observa a saída do terminal em busca de um endereço local (a linha `Local:` que ferramentas como Vite, Next.js ou Astro imprimem). Quando ele detecta um:
|
||||
Abra o painel do navegador pelo botão do globo no cabeçalho. Se já houver um servidor rodando, ele aparece na lista e um clique o abre: o OpenChamber o encontra olhando o que está de fato escutando na sua máquina, então funciona independentemente de como você o iniciou.
|
||||
|
||||
- no terminal, aparece um botão **Open preview**
|
||||
- uma [ação de projeto](/pt-br/project-actions/) com auto-open ativado o abre para você
|
||||
- um link local em uma mensagem do chat também pode abri-lo
|
||||
Um servidor também abre sozinho quando:
|
||||
|
||||
O site carrega no painel lateral. Apenas endereços locais (na sua própria máquina) podem ter preview.
|
||||
- você pressiona **Abrir pré-visualização** em um endereço local no terminal
|
||||
- uma [ação de projeto](/project-actions/) com abertura automática inicia um
|
||||
- você segue um link local em uma mensagem do chat
|
||||
|
||||
## Console e inspeção
|
||||
Você sempre pode digitar o endereço à mão. Um simples `localhost:5173` é entendido como `http://`, então não precisa escrever o esquema.
|
||||
|
||||
No painel de preview você pode:
|
||||
## Trabalhando com um OpenChamber remoto
|
||||
|
||||
- acompanhar o **console** da página — erros, avisos e logs, filtrados como você quiser
|
||||
- ativar o **inspect**, clicar em qualquer elemento e enviar uma nota sobre ele — seletor, estilos, posição e uma captura de tela — direto no chat
|
||||
Quando o OpenChamber roda em outra máquina, o servidor de desenvolvimento está *nessa* máquina — `localhost` no seu notebook aponta para outro lugar completamente. O aplicativo desktop resolve isso: ele abre uma porta local que leva a conexão até o servidor remoto, de modo que a página carrega normalmente, com recarga a quente e ferramentas de desenvolvedor funcionando. Você continua digitando o endereço que espera; o encanamento não atrapalha.
|
||||
|
||||
Esta é a forma mais rápida de dizer ao agente "este botão, aqui" sem descrevê-lo.
|
||||
Isso exige o aplicativo desktop. Em uma aba do navegador, só é possível abrir servidores da sua própria máquina.
|
||||
|
||||
## Anotar a página
|
||||
|
||||
Veja [Painel do navegador](/desktop-browser/) para apontar elementos, desenhar sobre a página e mandar tudo para o chat.
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Ações de Projeto](/pt-br/project-actions/) — abra um servidor automaticamente ao iniciá-lo
|
||||
- [Navegador no Desktop](/pt-br/desktop-browser/) — as mesmas ferramentas para qualquer página, no desktop
|
||||
- [Ações de projeto](/project-actions/) — abrir um servidor automaticamente ao iniciá-lo
|
||||
- [Painel do navegador](/desktop-browser/) — anotar páginas e deixar o agente conduzir
|
||||
|
||||
@@ -45,5 +45,6 @@ Os logins de provedores são armazenados pelo OpenCode, não pelo OpenChamber, e
|
||||
|
||||
## Relacionado
|
||||
|
||||
- [Integrações](/pt-br/integrations/) — use uma assinatura Claude ou Cursor como provedor
|
||||
- [Servidores MCP](/pt-br/mcp/) — adicione ferramentas extras para os agentes
|
||||
- [Uso e Cotas](/pt-br/usage/) — acompanhe quanto você já usou
|
||||
|
||||
@@ -12,7 +12,7 @@ Para escrever suas próprias skills, veja [Skills](/pt-br/skills/).
|
||||
## Instalar uma skill
|
||||
|
||||
1. Abra o catálogo.
|
||||
2. Navegue pelas fontes integradas — o repositório de skills da Anthropic e o registro comunitário ClawdHub — ou pesquise.
|
||||
2. Navegue pelas fontes integradas — como o repositório de skills da Anthropic — ou pesquise.
|
||||
3. Escolha uma skill e instale-a.
|
||||
4. Escolha onde instalá-la: para tudo o que você faz, ou apenas no projeto atual.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Check **Run as goal** to make the run pursue its prompt to completion instead of
|
||||
|
||||
## Loops: scheduled tasks as markdown files
|
||||
|
||||
A **loop** is a scheduled task defined as a portable markdown file you can commit to your repo. Drop a file into `.agents/loops/` and the task appears on the next sync — no dialog needed:
|
||||
A **loop** is a scheduled task defined as a portable markdown file you can commit to your repo. Drop a file into `.agents/loops/` and open the Scheduled Tasks list to sync it — no server restart needed:
|
||||
|
||||
```markdown
|
||||
---
|
||||
@@ -60,7 +60,7 @@ If a project loop and a user loop share a name, the project loop wins.
|
||||
|
||||
### How loops behave
|
||||
|
||||
- The **file is authoritative** while it exists: edits made in the UI are reverted on the next sync. The scheduled-tasks dialog marks loop tasks and disables their edit/enable/delete actions — **run now** still works. To stop a loop, delete the file (or set `enabled: false`).
|
||||
- The **file is authoritative** while it exists. **Edit** opens it in the built-in file editor, the enabled toggle updates its frontmatter, and deleting the task deletes the markdown file after confirmation. **Run now** remains available.
|
||||
- Runtime state (last run, next run, status) lives in the project config and is never written back into the markdown file.
|
||||
- Renaming the `name` field renames the task in place. If a loop file temporarily fails to parse (mid-edit, merge conflict), its task is kept with the last good definition until the file is fixed.
|
||||
- `daily`/`weekly`/`once` schedules and goal settings remain UI-only; loop files are always cron.
|
||||
|
||||
@@ -12,7 +12,7 @@ For writing your own skills, see [Skills](/skills/).
|
||||
## Install a skill
|
||||
|
||||
1. Open the catalog.
|
||||
2. Browse the built-in sources — the Anthropic skills repo and the ClawdHub community registry — or search.
|
||||
2. Browse the built-in sources — like the Anthropic skills repo — or search.
|
||||
3. Pick a skill and install it.
|
||||
4. Choose where to install it: for everything you do, or just the current project.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ description: Дозвольте агенту керувати сесіями, wo
|
||||
|
||||
## Увімкнення та вимкнення
|
||||
|
||||
Відкрийте **Налаштування → Загальні → OpenCode CLI**, змініть **Інструмент керування для агентів**, потім виберіть **Save + Reload**. Налаштування застосовується після перезапуску керованого сервера OpenCode.
|
||||
Відкрийте **Налаштування → Загальні → Інструменти OpenChamber** і змініть **Інструмент керування для агентів**. Налаштування застосовується після перезапуску керованого сервера OpenCode, який OpenChamber запропонує як **Apply & Restart**.
|
||||
|
||||
Інструмент недоступний, коли OpenChamber підключається до зовнішнього сервера OpenCode через `OPENCODE_HOST` чи skip-start, а також у розширенні VS Code. Десктопні та вебінсталяції з керованим OpenChamber сервером OpenCode підтримують його автоматично.
|
||||
|
||||
@@ -37,3 +37,4 @@ description: Дозвольте агенту керувати сесіями, wo
|
||||
- [Заплановані задачі](/uk/scheduled-tasks/)
|
||||
- [Сесії worktree](/uk/worktrees/)
|
||||
- [Цілі сесії](/uk/session-goals/)
|
||||
- [Панель браузера](/uk/desktop-browser/) — інструмент OpenChamber Web — дивитися на сторінку й керувати нею
|
||||
|
||||
@@ -1,22 +1,64 @@
|
||||
---
|
||||
title: Десктопний браузер
|
||||
description: Переглядайте будь-яку сторінку всередині десктопного застосунку, з інспекцією та перехопленням консолі.
|
||||
title: Панель браузера
|
||||
description: Переглядайте будь-яку сторінку в застосунку, анотуйте її та дозвольте агенту нею керувати.
|
||||
---
|
||||
|
||||
# Десктопний браузер
|
||||
# Панель браузера
|
||||
|
||||
Десктопний застосунок має вбудований браузер, тож ви можете відкрити будь-яку сторінку просто поруч із чатом, вказувати на елементи, щоб запитати про них, і перехоплювати консоль сторінки. Відкрийте його з кнопки глобуса в заголовку застосунку.
|
||||
Панель браузера відкриває будь-яку сторінку просто поруч із чатом. Відкрийте її кнопкою глобуса в заголовку застосунку.
|
||||
|
||||
> Десктопний браузер — це функція **лише для десктопа**. У вебі панель [перегляду](/uk/preview/) пропонує ті самі інструменти інспекції та консолі для вашого локального dev-сервера.
|
||||
У десктопному застосунку це справжній браузер: ваші входи зберігаються, гаряче перезавантаження працює, а інструменти розробника — за один клік. У вкладці веббраузера панель теж покаже сторінку, але не зможе зазирнути всередину — інструменти анотацій нижче доступні лише на десктопі.
|
||||
|
||||
## Інспекція та анотування
|
||||
Сторінки, відкриті тут, не можуть скористатися вашою камерою, мікрофоном чи місцем перебування: такі запити відхиляються.
|
||||
|
||||
Увімкніть **inspect** і клікніть будь-який елемент на сторінці. OpenChamber перехоплює нотатку про нього — що це, його стилі, де він розташований, і знімок екрана — і прикріплює її до вашого повідомлення в чаті. Це найшвидший спосіб сказати агентові «ось цей елемент, прямо тут».
|
||||
## Панель інструментів
|
||||
|
||||
## Перехоплення консолі
|
||||
Адресний рядок памʼятає сторінки, які ви відкривали в цьому проєкті, і пропонує їх під час набору, звіряючись із частиною адреси або назвою сторінки. Стрілки рухають списком, Enter відкриває підсвічений запис, а кнопка в рядку прибирає його зі списку.
|
||||
|
||||
Браузер збирає вивід консолі сторінки — помилки, попередження та логи — щоб ви могли фільтрувати й читати його, не відкриваючи інструменти розробника.
|
||||
Поруч — **перезавантаження**, а також **жорстке перезавантаження**, яке ігнорує кеш, коли зміна вперто не показується, і керування масштабом, що змінює лише сторінку.
|
||||
|
||||
## Пов'язане
|
||||
**Очистити куки** та **Очистити кеш** стосуються тільки цієї панелі. Вашої сесії OpenChamber та інших вікон це не торкається.
|
||||
|
||||
- [Перегляд і dev-сервери](/uk/preview/) — ті самі інструменти для вашого локального dev-сервера
|
||||
## Анотувати сторінку
|
||||
|
||||
Натисніть **Анотувати** — над сторінкою зʼявиться панель із трьома інструментами:
|
||||
|
||||
- **Елемент** — клікніть на елемент. Клік по іншому переносить вибір, повторний клік по тому самому — знімає його.
|
||||
- **Область** — обведіть ділянку рамкою, коли йдеться більш ніж про один елемент.
|
||||
- **Малювання** — малюйте від руки поверх сторінки.
|
||||
|
||||
Опишіть бажане в полі, що зʼявляється поруч із позначкою, і натисніть **Додати** — або просто Enter. У повідомленні чату зʼявиться картка з усім, що ви позначили, з вашою нотаткою і зі знімком видимої сторінки, на якому намальовано твої позначки — тож можна сказати «оця кнопка, трохи круглішу», а не описувати, де вона.
|
||||
|
||||
Сама сторінка при цьому не змінюється — анотація лише позначає те, що є. `Esc` скасовує й закриває панель.
|
||||
|
||||
## Дозволити агенту керувати
|
||||
|
||||
Агент може сам користуватися панеллю браузера — відкривати сторінку, читати, що на ній, клікати, вводити текст, прокручувати й перемикатися між мобільним, планшетним і десктопним розкладами — щоб перевіряти власну роботу, а не просити про це вас. Ви бачитимете це в панелі.
|
||||
|
||||
Агент не може виконувати довільний код на сторінці. Браузер зберігає ваші справжні входи, тож агент обмежений переліченими діями.
|
||||
|
||||
Він також може зберегти знімок того, що бачить, у `.openchamber/screenshots/` вашого проєкту й показати його у відповіді. Саме це робить можливим «до і після», а файл лишається на місці, щоб потім прикріпити його до pull request.
|
||||
|
||||
Дії з браузером — це **інструмент OpenChamber Web**, який вмикається й вимикається окремо в **Налаштування → Загальні → Інструменти OpenChamber**.
|
||||
|
||||
Для цього потрібен десктопний застосунок: сторінкою у вкладці веббраузера керувати не вийде.
|
||||
|
||||
## Розмір і оформлення
|
||||
|
||||
Натисніть кнопку телефона, щоб відкрити панель пристроїв. Оберіть пресет або
|
||||
введіть ширину й висоту — сторінка буде викладена саме в цьому розмірі, а якщо
|
||||
не вміщається в панель, її буде зменшено візуально. Сама сторінка при цьому
|
||||
вимірює себе в тому розмірі, який ви задали.
|
||||
|
||||
Там же можна змусити сторінку показатися світлою чи темною, не змінюючи нічого
|
||||
на своїй машині. З DevTools вони не поєднуються: у сторінки може бути лише один
|
||||
приєднаний зневаджувач, тож DevTools доведеться спершу закрити.
|
||||
|
||||
## Інструменти розробника
|
||||
|
||||
Натисніть кнопку термінала на панелі, щоб відкрити власні інструменти розробника Chromium для сторінки — консоль, мережу, елементи, усе як зазвичай.
|
||||
|
||||
## Повʼязане
|
||||
|
||||
- [Перегляд і dev-сервери](/preview/) — як відкрити запущений застосунок, зокрема на віддаленій машині
|
||||
- [Інструмент керування для агентів](/uk/agent-control-tool/) — сесії, worktree й заплановані задачі просто з чату
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Інтеграції
|
||||
description: Використовуйте підписки Claude або Cursor як провайдерів.
|
||||
---
|
||||
|
||||
# Інтеграції
|
||||
|
||||
Інтеграція — це невеликий плагін, що додає провайдера до OpenChamber на основі підписки, яка в вас уже є. Керувати ними можна в **Settings → Integrations**.
|
||||
|
||||
> **Експериментальна функція.** Ми прагнемо дотримуватися політик провайдерів, але обмеження та блокування облікових записів залишаються рішенням кожного провайдера. Використовуйте інтеграції на власний ризик.
|
||||
|
||||
Доступні інтеграції:
|
||||
|
||||
- **Claude Code** — ваша підписка Claude Pro або Max, без API-ключів
|
||||
- **Cursor** — ліміти моделей вашої підписки Cursor
|
||||
|
||||
## Встановлення інтеграції
|
||||
|
||||
1. Відкрийте **Settings → Integrations**.
|
||||
2. Знайдіть інтеграцію та натисніть **Install**.
|
||||
3. Перезапустіть OpenCode, коли про це попросять, — провайдер з'явиться після перезапуску.
|
||||
4. Натисніть **Set up** і увійдіть. Після цього моделі з'являться в перемикачі моделей у чаті.
|
||||
|
||||
Інтеграції встановлюються для вашого користувача, тож працюють у всіх проєктах. Оновити або видалити їх можна в будь-який момент з тієї ж карточки.
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code використовує вашу підписку Claude Pro або Max — без API-ключів і без окремого застосунку Claude.
|
||||
|
||||
1. Встановіть інтеграцію (вище).
|
||||
2. Натисніть **Set up** і увійдіть. Якщо у вас ще немає Claude Code CLI, програма встановлення спершу запропонує його встановити, а потім виконає вхід.
|
||||
|
||||
Claude Code — єдина інтеграція тут, яка вимагає встановленого та залогіненого CLI свого провайдера. Для Cursor CLI не потрібен.
|
||||
|
||||
**Як захищається ваш обліковий запис Claude:** ця інтеграція використовує офіційний Claude Agent SDK від Anthropic і ваш встановлений Claude Code CLI. Вона не перехоплює OAuth, не витягує й не відтворює браузерні токени, не видає себе за непідтримуваний клієнт і не обходить процес автентифікації Anthropic. Усе працює через підтримуваний Anthropic шлях доступу, тож інтеграція не несе ризику блокування облікового запису, пов'язаного з перехопленням токенів або несанкціонованими способами автентифікації.
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor робить доступними в OpenChamber моделі, що входять у вашу підписку Cursor.
|
||||
|
||||
1. Встановіть інтеграцію (вище).
|
||||
2. Натисніть **Set up**, відкрийте посилання та підтвердьте доступ у браузері. API-ключ не потрібен. Список моделей завантажиться автоматично після входу.
|
||||
|
||||
## Оновлення та видалення
|
||||
|
||||
- **Update** встановлює найновішу опубліковану версію плагіна.
|
||||
- **Remove** видаляє плагін із конфігурації OpenCode. Провайдер перестане завантажуватися після оновлення OpenCode.
|
||||
|
||||
Якщо карточка повідомляє, що записи потребують ручного керування, натисніть **Manage plugins** і приберіть дублікати там.
|
||||
|
||||
## Пов'язане
|
||||
|
||||
- [Провайдери, моделі та агенти](/uk/providers/) — підключення інших провайдерів і вибір моделей
|
||||
- [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили
|
||||
@@ -5,28 +5,31 @@ description: Відкрийте запущений dev-сервер усеред
|
||||
|
||||
# Перегляд і dev-сервери
|
||||
|
||||
Коли ви запускаєте dev-сервер, OpenChamber може відкрити його просто всередині застосунку замість окремої вкладки браузера — щоб ви могли бачити свій сайт поруч із чатом, перехоплювати його консоль і вказувати на елементи, щоб запитати про них.
|
||||
Коли ви запускаєте dev-сервер, OpenChamber може відкрити його просто всередині застосунку замість окремої вкладки браузера — щоб ви бачили свій сайт поруч із чатом і могли вказувати на елементи, щоб запитати про них.
|
||||
|
||||
## Відкриття перегляду
|
||||
## Відкрити dev-сервер
|
||||
|
||||
OpenChamber слідкує за виводом терміналу на предмет локальної адреси (рядок `Local:`, який друкують інструменти на кшталт Vite, Next.js чи Astro). Коли він її помічає:
|
||||
Відкрийте панель браузера кнопкою глобуса в заголовку застосунку. Якщо dev-сервер уже запущено, він буде у списку — один клік, і він відкриється. OpenChamber знаходить його за тим, що насправді слухає порти на вашій машині, тож це працює незалежно від того, як саме ви його запустили.
|
||||
|
||||
- у терміналі з'являється кнопка **Open preview**
|
||||
- [дія проєкту](/uk/project-actions/) з увімкненим автовідкриттям відкриває її за вас
|
||||
- локальне посилання в повідомленні чату теж може її відкрити
|
||||
Dev-сервер також відкривається автоматично, коли:
|
||||
|
||||
Сайт завантажується в бічній панелі. Переглянути можна лише локальні адреси (на вашій власній машині).
|
||||
- ви натискаєте **Відкрити перегляд** на локальній адресі в терміналі
|
||||
- [дія проєкту](/project-actions/) з увімкненим автовідкриттям запускає його
|
||||
- ви переходите за локальним посиланням у повідомленні чату
|
||||
|
||||
## Консоль та інспекція
|
||||
Адресу завжди можна ввести вручну. Простий `localhost:5173` трактується як `http://`, тож схему писати не обовʼязково.
|
||||
|
||||
У панелі перегляду ви можете:
|
||||
## Робота з віддаленим OpenChamber
|
||||
|
||||
- спостерігати за **консоллю** сторінки — помилки, попередження та логи, відфільтровані як вам зручно
|
||||
- увімкнути **inspect**, клікнути будь-який елемент і надіслати нотатку про нього — селектор, стилі, позицію та знімок екрана — прямо в чат
|
||||
Коли OpenChamber працює на іншій машині, його dev-сервер теж на *тій* машині — `localhost` на вашому ноутбуці веде зовсім не туди. Десктопний застосунок робить це за вас: відкриває локальний порт, який проводить зʼєднання до віддаленого dev-сервера, тож сторінка вантажиться як звичайно, з робочим гарячим перезавантаженням і інструментами розробника. Ви й далі вводите очікувану адресу; технічні деталі вам не заважають.
|
||||
|
||||
Це найшвидший спосіб сказати агентові «ось ця кнопка, тут», не описуючи її.
|
||||
Для цього потрібен десктопний застосунок. У вкладці браузера можна відкрити лише dev-сервери на вашій власній машині.
|
||||
|
||||
## Пов'язане
|
||||
## Анотації на сторінці
|
||||
|
||||
- [Дії проєкту](/uk/project-actions/) — автоматично відкривайте сервер при запуску
|
||||
- [Десктопний браузер](/uk/desktop-browser/) — ті самі інструменти для будь-якої сторінки на десктопі
|
||||
Про те, як вказувати на елементи, малювати на сторінці й надсилати все це в чат, читайте в розділі [Панель браузера](/desktop-browser/).
|
||||
|
||||
## Повʼязане
|
||||
|
||||
- [Дії проєкту](/project-actions/) — автовідкриття сервера після запуску
|
||||
- [Панель браузера](/desktop-browser/) — анотації сторінок і керування агентом
|
||||
|
||||
@@ -45,5 +45,6 @@ description: Підключайте AI-провайдерів, обирайте
|
||||
|
||||
## Пов'язане
|
||||
|
||||
- [Інтеграції](/uk/integrations/) — використовуйте підписки Claude або Cursor як провайдерів
|
||||
- [MCP Servers](/uk/mcp/) — додайте агентам додаткові інструменти
|
||||
- [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили
|
||||
|
||||
@@ -12,7 +12,7 @@ description: Переглядайте та встановлюйте готові
|
||||
## Встановлення навички
|
||||
|
||||
1. Відкрийте каталог.
|
||||
2. Перегляньте вбудовані джерела — репозиторій навичок Anthropic та спільнотний реєстр ClawdHub — або скористайтеся пошуком.
|
||||
2. Перегляньте вбудовані джерела — наприклад репозиторій навичок Anthropic — або скористайтеся пошуком.
|
||||
3. Оберіть навичку й установіть її.
|
||||
4. Виберіть, куди встановити: для всього, що ви робите, чи лише для поточного проєкту.
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ description: 让智能体从聊天中管理 OpenChamber 会话、worktree 和计
|
||||
|
||||
## 开启或关闭工具
|
||||
|
||||
打开 **设置 → 常规 → OpenCode CLI**,更改 **智能体控制工具**,然后选择 **Save + Reload**。该设置会在托管的 OpenCode 服务器重启后生效。
|
||||
打开 **设置 → 常规 → OpenChamber 工具**,更改 **智能体控制工具**。该设置会在托管的 OpenCode 服务器重启后生效,OpenChamber 会以 **Apply & Restart** 的形式提示重启。
|
||||
|
||||
当 OpenChamber 通过 `OPENCODE_HOST` 或 skip-start 连接外部 OpenCode 服务器时,或在 VS Code 扩展中,此工具不可用。使用 OpenChamber 托管 OpenCode 服务器的桌面端和 Web 安装会自动支持此工具。
|
||||
|
||||
@@ -37,3 +37,4 @@ description: 让智能体从聊天中管理 OpenChamber 会话、worktree 和计
|
||||
- [计划任务](/zh-cn/scheduled-tasks/)
|
||||
- [Worktree 会话](/zh-cn/worktrees/)
|
||||
- [会话目标](/zh-cn/session-goals/)
|
||||
- [浏览器面板](/zh-cn/desktop-browser/) — 用于查看并操作页面的 OpenChamber Web 工具
|
||||
|
||||
@@ -1,22 +1,53 @@
|
||||
---
|
||||
title: 桌面浏览器
|
||||
description: 在桌面应用内部浏览任意页面,并提供检查和控制台捕获功能。
|
||||
title: 浏览器面板
|
||||
description: 在应用内浏览任意页面、为其添加标注,并让智能体操作它。
|
||||
---
|
||||
|
||||
# 桌面浏览器
|
||||
# 浏览器面板
|
||||
|
||||
桌面应用内置了浏览器,因此你可以在聊天旁边直接打开任意页面、指向元素来询问相关问题,并捕获页面的控制台。从应用标题栏的地球按钮打开它。
|
||||
浏览器面板会在聊天旁边打开任意页面。用应用标题栏的地球按钮打开它。
|
||||
|
||||
> 桌面浏览器是一项**仅限桌面**的功能。在网页端,[预览](/zh-cn/preview/) 面板为你的本地开发服务器提供相同的检查与控制台工具。
|
||||
在桌面应用中,它是一个真正的浏览器:登录状态会保留,热重载可用,开发者工具一键即达。在浏览器标签页中,面板仍能显示页面,但无法查看其内部——下面的标注工具仅限桌面端。
|
||||
|
||||
## 检查与标注
|
||||
在这里打开的页面无法使用你的摄像头、麦克风或位置:这类请求会被拒绝。
|
||||
|
||||
开启 **inspect** 并点击页面上的任意元素。OpenChamber 会捕获关于它的说明 — 它是什么、它的样式、它所处的位置,以及一张截图 — 并将其附加到你的聊天消息中。这是告诉智能体“就这个元素,就在这里”的最快方式。
|
||||
## 工具栏
|
||||
|
||||
## 控制台捕获
|
||||
地址栏会记住你在这个项目里打开过的页面,并在你输入时给出候选,按地址或页面标题的任意片段匹配。方向键在列表中移动,回车打开选中的一项,行上的按钮把它从列表中移除。
|
||||
|
||||
浏览器会收集页面的控制台输出 — 错误、警告和日志 — 因此你无需打开开发者工具即可筛选和阅读它。
|
||||
旁边是**重新加载**,还有在改动怎么都不出现时忽略缓存的**强制重新加载**,以及只缩放页面的缩放控件。
|
||||
|
||||
## 相关内容
|
||||
**清除 Cookie** 和**清除缓存数据**只作用于这个面板。你的 OpenChamber 会话和其他窗口不受影响。
|
||||
|
||||
- [预览与开发服务器](/zh-cn/preview/) — 为你的本地开发服务器提供相同的工具
|
||||
## 为页面添加标注
|
||||
|
||||
按 **标注**,页面上方会出现一个包含三种工具的工具条:
|
||||
|
||||
- **元素** — 点击某个元素。点击另一个会移动选择,再次点击同一个则取消。
|
||||
- **区域** — 当要说的内容不止一个元素时,拖拽出矩形框住那块区域。
|
||||
- **绘制** — 在页面上自由手绘。
|
||||
|
||||
在标记旁出现的输入框里写下你的想法,然后按 **附加**,或直接按回车。你的聊天消息会收到一张卡片,包含你标记的全部内容、你的备注,以及一张画上你的标记的可见页面截图——于是你可以说"这个按钮,再圆一点",而不必描述它在哪里。
|
||||
|
||||
页面本身不会被修改——标注只是标记已有的内容。按 `Esc` 取消并关闭工具条。
|
||||
|
||||
## 让智能体操作
|
||||
|
||||
智能体可以自己使用浏览器面板——打开页面、读取页面内容、点击、输入、滚动,并在移动端、平板和桌面端布局之间切换——从而自行检查工作成果,而不必来问你。你可以在面板中看到这个过程。
|
||||
|
||||
智能体无法在页面中执行任意代码。浏览器保留着你真实的登录状态,因此它只能执行上述操作。
|
||||
|
||||
它还可以把当前看到的画面保存为图片,放进项目里的 `.openchamber/screenshots/`,并在回复中展示给你。「改动前后」的对比正是靠这一点,而文件会留在那里,方便附到 pull request 上。
|
||||
|
||||
浏览器相关的动作属于 **OpenChamber Web 工具**,可在**设置 → 通用 → OpenChamber 工具**中单独开关。
|
||||
|
||||
这需要桌面应用:在浏览器标签页中显示的页面无法被操作。
|
||||
|
||||
## 开发者工具
|
||||
|
||||
按工具条上的终端按钮,即可打开 Chromium 自带的页面开发者工具——控制台、网络、元素,一应俱全。
|
||||
|
||||
## 相关
|
||||
|
||||
- [预览与开发服务器](/preview/) — 打开正在运行的应用,包括远程机器上的
|
||||
- [智能体控制工具](/zh-cn/agent-control-tool/) — 在聊天中管理会话、worktree 和计划任务
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: 集成
|
||||
description: 将你的 Claude 或 Cursor 订阅用作提供商。
|
||||
---
|
||||
|
||||
# 集成
|
||||
|
||||
集成是一个小型插件,它使用你已有的订阅为 OpenChamber 添加一个提供商。你可以在 **Settings → Integrations** 中管理它们。
|
||||
|
||||
> **实验性功能。**我们力求遵守提供商的政策,但帐户限制和暂停仍由各提供商决定。请自行承担使用集成的风险。
|
||||
|
||||
可用的集成:
|
||||
|
||||
- **Claude Code** — 你的 Claude Pro 或 Max 套餐,无需 API 密钥
|
||||
- **Cursor** — 你的 Cursor 套餐的模型额度
|
||||
|
||||
## 安装集成
|
||||
|
||||
1. 打开 **Settings → Integrations**。
|
||||
2. 找到所需的集成并选择 **Install**。
|
||||
3. 在提示时重启 OpenCode — 重启后提供商就会出现。
|
||||
4. 选择 **Set up** 并登录。之后模型会出现在聊天室的模型选择器中。
|
||||
|
||||
集成按用户安装,因此在所有项目中都可用。你可以随时在同一张卡片上更新或移除它们。
|
||||
|
||||
## Claude Code
|
||||
|
||||
Claude Code 使用你的 Claude Pro 或 Max 套餐 — 无需 API 密钥,也无需单独的 Claude 应用。
|
||||
|
||||
1. 安装集成(见上文)。
|
||||
2. 选择 **Set up** 并登录。如果你还没有 Claude Code CLI,安装向导会先提供安装,然后再登录。
|
||||
|
||||
Claude Code 是这里唯一要求安装并登录其提供商 CLI 的集成。Cursor 不需要其 CLI。
|
||||
|
||||
**你的 Claude 账户如何受到保护:** 此集成使用 Anthropic 官方的 Claude Agent SDK 和你已安装的 Claude Code CLI。它不会劫持 OAuth,不会提取或重放浏览器令牌,不会冒充不受支持的客户端,也不会绕过 Anthropic 的身份验证。它始终运行在 Anthropic 支持的访问路径上,因此不会带来与令牌劫持或未授权身份验证变通手段相关的封号风险。
|
||||
|
||||
## Cursor
|
||||
|
||||
Cursor 让你的 Cursor 套餐中包含的模型可以在 OpenChamber 中使用。
|
||||
|
||||
1. 安装集成(见上文)。
|
||||
2. 选择 **Set up**,打开链接并在浏览器中授权访问。无需 API 密钥。登录后模型列表会自动加载。
|
||||
|
||||
## 更新或移除
|
||||
|
||||
- **Update** 安装插件的最新发布版本。
|
||||
- **Remove** 从你的 OpenCode 配置中删除该插件。OpenCode 重新加载后,该提供商将不再加载。
|
||||
|
||||
如果卡片提示条目需要手动管理,请选择 **Manage plugins** 并在那里清理重复项。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [提供商、模型与智能体](/zh-cn/providers/) — 连接其他提供商并选择模型
|
||||
- [用量与配额](/zh-cn/usage/) — 跟踪你的使用量
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user