AGENTS.md@packages/client/src/components/editor-pane/file-handler · git:20261020.96d059f · 2026-10-20 · sha256 2a65353cfd1c6b7c
AGENTS.md@packages/client/src/components/editor-pane/file-handler git:20261020.96d059fA
Immutable. This exact content never changes and is served at /api/v1/blob/2a65353cfd1c6b7c.
# DOX — packages/client/src/components/editor-pane/file-handler
Files in this directory. One row per source file. Plugin `editor-pane-file-handler` modes for file tabs. See change: add-editor-pane-file-handlers.
| File | Purpose |
|------|---------|
| `__tests__/file-handler-host.test.ts` | X1–X3 snapshot bracket (3 attempts, mtime-only tolerated, too-large before raw), X7 conflict dialog actions, X8 first-overwrite notice, status→reason mapping, busy. See change: add-editor-pane-file-handlers. |
| `__tests__/file-handler-store.test.ts` | F4/F5 cap + LRU clean-only eviction + save-or-discard dialog, F6 non-keepAlive close-when-clean, F7 guards, F8 reconcile, F10 shared instance, tab sync. See change: add-editor-pane-file-handlers. |
| `file-mode-offers.tsx` | `FileModeOffersContext` / `useFileModeOffers()` → `{claims, onSelect(key)}` \| `null`: the active tab's matching modes for the built-in viewer (binary notice, D11 A4). Provided by `EditorPane`. See change: extend-craft-web-to-all-apps. |
| `FileHandlerAnchor.tsx` | Pane-body placeholder a handler tab renders instead of `CappedViewer`; registers itself as the store anchor; shows "Editor closed to save memory — Resume" for an evicted key. See change: add-editor-pane-file-handlers. |
| `FileHandlerLayer.tsx` | Page-level host (mounted in `App` outside EditorPane/SplitWorkspace). Renders every live instance `position:fixed` over the anchor rect (`ResizeObserver` + window resize/scroll), hidden otherwise. Passes `FileHandlerProps` (`cwd,path,session,isActive,snapshot,save,setDirty,context`) inside `SlotErrorBoundary`+`Suspense`+`CurrentPluginLayer`. Owns dialog host, copy toast ("Open"), `beforeunload`, claims reconcile (live plugin disable overlay: Re-enable / Discard), too-large notice, pane bridge (`trackedFileWrite`/`setBaseline`/`openInSplit`). See change: add-editor-pane-file-handlers. Loaded as a `React.lazy` chunk by `App` (entry gzip cap). Passes `openFile` to handler bodies; bridge opens via `openInSplit` then `setHandlerMode` when a mode is given. See change: extend-craft-web-to-all-apps (D6). |
| `FileModeSwitcher.tsx` | Toolbar above the body: `Preview` then claim modes (caller orders); `outsideCwd` → "unavailable: outside the session folder". testids `file-mode-switcher`, `file-mode-builtin`, `file-mode-<pluginId>/<claimId>`. See change: add-editor-pane-file-handlers. |
| `file-handler-claims.ts` | `listFileHandlerClaims(registry)` (priority → plugin id → claim id), `claimsForPath` (`extOf`, case-insensitive), `isUnderSessionCwd`, `fileHandlerInstanceKey(sessionId,cwd,path,claimKey)`. See change: add-editor-pane-file-handlers. |
| `file-handler-dialogs.ts` | `HandlerDialogRequest`/`AskHandlerDialog` model (resolve action id or `null`). See change: add-editor-pane-file-handlers. |
| `file-handler-host.ts` | `createFileHandlerHost(deps)`: `snapshot()` (digest→raw `no-store`→digest bracket, sha1 token, size gate, `FileHandlerSnapshotError`), `save()` (first-overwrite notice, `POST /api/file/write-binary` via tracked write, 409 conflict loop: Reload/Save as copy/Overwrite anyway; hidden Reload+Overwrite when file gone; `busy` on 503/in-flight). See change: add-editor-pane-file-handlers. `save({target:"sibling", ext})`: declared ext only (else rejected, no request), `mode=copy&siblingExt`, no notice / token, 409 → `conflict-unresolved`, `notifyCopy`. `FileHandlerHostApi.save` = `FileHandlerProps["save"]`. See change: extend-craft-web-to-all-apps (D6). |
| `file-handler-store.ts` | Framework-free instance registry. `MAX_LIVE_HANDLERS=3`; `activate`, `setActive`, `paneClosed`, `syncTabs`, `guardDiscard(key,kind)`, `remount`, `discard`, `resume`, `reconcileClaims`, `hasUnsaved`, dialog queue (`ask`/`resolveDialog`). Page singleton `fileHandlerStore`. Dirty `"unknown"` = unsaved for every guard. See change: add-editor-pane-file-handlers. The host (`file-handler-host.ts`) loads via dynamic `import()` on the first `snapshot`/`save` (entry gzip cap, mdi-chunk-size). `openFile(key, path, claimId?)` → bridge `openFile(path, <pluginId>/<claimId>)`; bridge `openFile(path, mode?)`. See change: extend-craft-web-to-all-apps (D6). |
| `use-file-handler-pane.ts` | Pane-side wiring: matching claims, `handlerView`, `selectMode`/`guardTabClose`/`refreshHandler`, activate/setActive/sync effects; inert in folder panes; ignores the render right after a session switch. See change: add-editor-pane-file-handlers. |
| `use-file-handler-store.ts` | React bindings: `FileHandlerStoreProvider` (test injection), `useFileHandlerStore`, `useFileHandlerState`, `useFileHandlerClaims`. See change: add-editor-pane-file-handlers. |