@huanlin/dsh-plugin-aigc-canvas 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +664 -0
- package/README.md +243 -0
- package/assets/stub-audio.mp3 +0 -0
- package/assets/stub-image.png +0 -0
- package/assets/stub-video.mp4 +0 -0
- package/cordis.patch.yml +19 -0
- package/lib/client.js +3419 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +8191 -0
- package/lib/invariant.js +22 -0
- package/package.json +124 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","names":["formatTime","useState","createElement","css","Component","createElement","css","useState","createElement","useState","css","Component","Component","createElement","css","useSyncExternalStore","useState","useRef","useState","useCallback","css","Modal","Pill","useRef","createElement"],"sources":["../../../src/client/api.ts","../../../src/client/store.ts","../../../src/client/CanvasNode.tsx","../../../src/client/RequestLogPanel.tsx","../../../src/client/compare-helpers.ts","../../../src/client/CompareView.tsx","../../../src/client/CanvasView.tsx","../../../src/client/SettingsPage.tsx","../../../src/client/locales.ts","../../../src/client/index.tsx"],"sourcesContent":["/**\r\n * Typed fetch wrapper over the /aigc-canvas JSON API.\r\n */\r\n\r\n/** One wire failure. */\r\nexport class AigcApiError extends Error {\r\n constructor(\r\n readonly code: string,\r\n message: string,\r\n ) {\r\n super(message)\r\n }\r\n}\r\n\r\n/** Element kind (matches the host enum). */\r\nexport type AigcElementKind = 'prompt' | 'image' | 'video' | 'audio'\r\n\r\n/** Element lifecycle status (matches the host ElementStatus). */\r\nexport type ElementStatus = 'draft' | 'ready' | 'rejected' | 'archived'\r\n\r\n/**\r\n * Semantic relation on an edge (matches the host EdgeRelation enum).\r\n * Drives the canvas line style + label. Optional on the client side for\r\n * backward compat with old canvas.json / WS pushes that predate the field\r\n * (defaults to 'input' in renderEdge).\r\n *\r\n * @see EdgeRelation in canvas-registry.ts for the full description.\r\n */\r\nexport type EdgeRelation =\r\n | 'input'\r\n | 'first_frame'\r\n | 'last_frame'\r\n | 'audio_track'\r\n | 'reference'\r\n | 'style'\r\n | 'mask'\r\n | 'variation_of'\r\n | 'remix_of'\r\n | 'alternative_of'\r\n | 'edited_from'\r\n\r\n/** One canvas element (client view). */\r\nexport interface AigcElement {\r\n filePath: string\r\n uuid?: string\r\n sessionId?: string\r\n kind: AigcElementKind\r\n title: string\r\n /** Canvas position, world coordinates (infinite free canvas). */\r\n x: number\r\n /** Canvas position, world coordinates (infinite free canvas). */\r\n y: number\r\n createdAt: number\r\n producedBy: string\r\n promptText?: string\r\n mediaSize?: number\r\n meta?: Record<string, unknown>\r\n description?: string\r\n /** Lifecycle status: draft / ready (default) / rejected / archived. */\r\n status?: ElementStatus\r\n /** Whether this element was marked as the winner of a variation cluster. */\r\n winner?: boolean\r\n}\r\n\r\n/** One canvas edge (source filePath → target filePath, with semantic relation). */\r\nexport interface AigcEdge {\r\n source: string\r\n target: string\r\n /**\r\n * Why the source was wired to the target. Drives line style + label:\r\n * - solid: input / first_frame / last_frame / audio_track (direct inputs)\r\n * - dashed: reference / style / mask (references)\r\n * - dotted: variation_of / remix_of / alternative_of (variations)\r\n * - bold solid: edited_from (ffmpeg edit chain)\r\n * Optional for backward compat; defaults to 'input' when undefined.\r\n */\r\n relation?: EdgeRelation\r\n /** Optional short note supplementing the relation (free text). */\r\n note?: string\r\n}\r\n\r\n/** Full canvas state for one session. */\r\nexport interface AigcCanvasState {\r\n sessionId: string\r\n elements: AigcElement[]\r\n edges: AigcEdge[]\r\n}\r\n\r\n/** One provider (wire shape, matches the host ResolvedAigcProvider). */\r\nexport interface RuntimeProvider {\r\n id: string\r\n name: string\r\n endpoint: string\r\n apiKey: string\r\n instructions: string\r\n auth: { scheme: 'bearer' | 'header' | 'query'; name: string }\r\n builtin: boolean\r\n /**\r\n * Structured capability catalog (per docs/product/03-provider-catalog.md).\r\n * Empty array = legacy auto-sniff + instructions (backward compat).\r\n */\r\n endpoints?: RuntimeEndpointSpec[]\r\n /** Selection priority (smaller = higher; default 100). */\r\n priority?: number\r\n /** Cost per call in USD (for cost tracking). */\r\n costPerCall?: number\r\n /** Cost per 1k tokens in USD (chat / transcribe). */\r\n costPerKiloToken?: number\r\n /** Cost per second of video/audio in USD (t2v / tts). */\r\n costPerSecond?: number\r\n /** Average latency in ms (host auto-statistic; future use). */\r\n avgLatencyMs?: number\r\n /** Quality hint: fast / balanced / quality. */\r\n qualityHint?: RuntimeQualityHint\r\n}\r\n\r\n/** Quality hint (client-side mirror of the host QualityHint enum). */\r\nexport type RuntimeQualityHint = 'fast' | 'balanced' | 'quality'\r\n\r\n/** All QualityHint values as a readonly array (for select dropdowns). */\r\nexport const RUNTIME_QUALITY_HINTS: readonly RuntimeQualityHint[] = ['fast', 'balanced', 'quality'] as const\r\n\r\n/** One AIGC capability (client-side mirror of the host Capability enum). */\r\nexport type RuntimeCapability =\r\n | 't2i' | 'i2i' | 't2v' | 'i2v' | 'fl2v' | 'ref2v'\r\n | 'tts' | 'music' | 'transcribe' | 'edit' | 'chat'\r\n\r\n/** All Capability values (for select dropdowns). */\r\nexport const RUNTIME_CAPABILITIES: readonly RuntimeCapability[] = [\r\n 't2i', 'i2i', 't2v', 'i2v', 'fl2v', 'ref2v',\r\n 'tts', 'music', 'transcribe', 'edit', 'chat',\r\n] as const\r\n\r\n/** Response kind (client-side mirror of the host ResponseKind enum). */\r\nexport type RuntimeResponseKind =\r\n | 'b64_json_array' | 'b64_json_field' | 'binary' | 'url_field' | 'json_text'\r\n\r\n/** All ResponseKind values (for select dropdowns). */\r\nexport const RUNTIME_RESPONSE_KINDS: readonly RuntimeResponseKind[] = [\r\n 'b64_json_array', 'b64_json_field', 'binary', 'url_field', 'json_text',\r\n] as const\r\n\r\n/** HTTP method (client-side mirror of the host EndpointSpec.method). */\r\nexport type RuntimeHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH'\r\n\r\n/** All HTTP methods (for select dropdowns). */\r\nexport const RUNTIME_HTTP_METHODS: readonly RuntimeHttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH'] as const\r\n\r\n/** One parameter on an endpoint (client-side mirror of ParamSpec). */\r\nexport interface RuntimeParamSpec {\r\n name: string\r\n type: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'image_ref' | 'video_ref' | 'audio_ref'\r\n required: boolean\r\n default?: unknown\r\n description?: string\r\n}\r\n\r\n/** All parameter types (for select dropdowns). */\r\nexport const RUNTIME_PARAM_TYPES: readonly RuntimeParamSpec['type'][] = [\r\n 'string', 'number', 'integer', 'boolean', 'array', 'object',\r\n 'image_ref', 'video_ref', 'audio_ref',\r\n] as const\r\n\r\n/** Response shape declaration (client-side mirror of ResponseSpec). */\r\nexport interface RuntimeResponseSpec {\r\n kind: RuntimeResponseKind\r\n path?: string\r\n}\r\n\r\n/** One provider endpoint's complete description (client-side mirror of EndpointSpec). */\r\nexport interface RuntimeEndpointSpec {\r\n path: string\r\n method: RuntimeHttpMethod\r\n capability: RuntimeCapability\r\n params?: RuntimeParamSpec[]\r\n response: RuntimeResponseSpec\r\n acceptsCanvasRef?: boolean\r\n notes?: string\r\n}\r\n\r\n/** Global settings wire shape. */\r\nexport interface RuntimeGlobalSettings {\r\n requestTimeoutMs: number\r\n mediaSizeLimit: number\r\n}\r\n\r\n/** Full config response (providers + global settings). */\r\nexport interface RuntimeConfig extends RuntimeGlobalSettings {\r\n providers: RuntimeProvider[]\r\n}\r\n\r\nasync function call<T>(method: string, payload: Record<string, unknown>, signal?: AbortSignal): Promise<T> {\r\n let response: Response\r\n try {\r\n response = await fetch(`/aigc-canvas/api/${method}`, {\r\n method: 'POST',\r\n headers: { 'content-type': 'application/json' },\r\n body: JSON.stringify(payload),\r\n signal,\r\n })\r\n } catch (error) {\r\n throw new AigcApiError('network', error instanceof Error ? error.message : String(error))\r\n }\r\n const parsed: { ok?: boolean; value?: unknown; error?: { code?: string; message?: string } } | null\r\n = await response.json().catch(() => null)\r\n if (!response.ok || parsed === null || parsed.ok !== true || parsed.value === undefined) {\r\n throw new AigcApiError(\r\n parsed?.error?.code ?? 'http',\r\n parsed?.error?.message ?? `HTTP ${response.status}`,\r\n )\r\n }\r\n return parsed.value as T\r\n}\r\n\r\n/** Fetch the canvas state (elements + edges) for one session. */\r\nexport function fetchCanvas(sessionId: string, signal?: AbortSignal): Promise<AigcCanvasState> {\r\n return call<AigcCanvasState>('canvas.list', { sessionId }, signal)\r\n}\r\n\r\n/** Persist one element's new canvas position (after a client drag). */\r\nexport function moveCanvasElement(sessionId: string, uuid: string, x: number, y: number, signal?: AbortSignal): Promise<AigcElement> {\r\n return call<AigcElement>('canvas.move', { sessionId, uuid, x, y }, signal)\r\n}\r\n\r\n/** Delete one element from the canvas (also removes its edges). */\r\nexport function deleteCanvasElement(sessionId: string, uuid: string, signal?: AbortSignal): Promise<{ ok: boolean }> {\r\n return call<{ ok: boolean }>('canvas.delete', { sessionId, uuid }, signal)\r\n}\r\n\r\n/** Upload a file (drag-dropped onto the canvas) and place it as a new element. */\r\nexport function uploadCanvasFile(sessionId: string, fileName: string, mediaBase64: string, opts?: { x?: number; y?: number; description?: string }, signal?: AbortSignal): Promise<{ ok: boolean; element: AigcElement }> {\r\n return call<{ ok: boolean; element: AigcElement }>('canvas.upload', { sessionId, fileName, mediaBase64, ...opts }, signal)\r\n}\r\n\r\n/**\r\n * Inject a user-role notice into the agent's next-step context\r\n * (non-waking). Used by the canvas UI's right-click menu and quick\r\n * action toolbar to ask the agent to regenerate / edit / run a\r\n * workflow. Per docs/product/04-ux-reliability.md §1 + §7.\r\n *\r\n * The optional `summary` is the short label shown in the agent's\r\n * inbox (truncated to 120 chars by the host).\r\n */\r\nexport function notifyAgent(sessionId: string, message: string, summary?: string, signal?: AbortSignal): Promise<{ ok: boolean }> {\r\n const payload: Record<string, unknown> = { sessionId, message }\r\n if (summary !== undefined) payload.summary = summary\r\n return call<{ ok: boolean }>('canvas.notify', payload, signal)\r\n}\r\n\r\n/**\r\n * Update one element's lifecycle status (draft/ready/rejected/archived)\r\n * and optional winner flag. Per docs/product/01-agent-autonomy.md §5\r\n * + docs/product/04-ux-reliability.md §1 (right-click → mark as\r\n * winner / rejected / archive).\r\n */\r\nexport function setElementStatus(sessionId: string, uuid: string, status: ElementStatus, winner?: boolean, signal?: AbortSignal): Promise<{ ok: boolean; element: AigcElement }> {\r\n const payload: Record<string, unknown> = { sessionId, uuid, status }\r\n if (winner !== undefined) payload.winner = winner\r\n return call<{ ok: boolean; element: AigcElement }>('canvas.set_status', payload, signal)\r\n}\r\n\r\n/** Fetch the full runtime config (providers + global settings). */\r\nexport function fetchConfig(signal?: AbortSignal): Promise<RuntimeConfig> {\r\n return call<RuntimeConfig>('config.get', {}, signal)\r\n}\r\n\r\n/** List all providers. */\r\nexport function listProviders(signal?: AbortSignal): Promise<{ providers: RuntimeProvider[] }> {\r\n return call<{ providers: RuntimeProvider[] }>('providers.list', {}, signal)\r\n}\r\n\r\n/** Add a new provider. */\r\nexport function addProvider(provider: RuntimeProvider, signal?: AbortSignal): Promise<{ providers: RuntimeProvider[] }> {\r\n return call<{ providers: RuntimeProvider[] }>('providers.add', { provider }, signal)\r\n}\r\n\r\n/** Update an existing provider. */\r\nexport function updateProvider(provider: RuntimeProvider, signal?: AbortSignal): Promise<{ providers: RuntimeProvider[] }> {\r\n return call<{ providers: RuntimeProvider[] }>('providers.update', { provider }, signal)\r\n}\r\n\r\n/** Remove a provider by id. */\r\nexport function removeProvider(id: string, signal?: AbortSignal): Promise<{ providers: RuntimeProvider[] }> {\r\n return call<{ providers: RuntimeProvider[] }>('providers.remove', { id }, signal)\r\n}\r\n\r\n/** Build the media URL for one element's media file (by uuid; the host resolves to the file). */\r\nexport function mediaUrlOf(sessionId: string, uuid: string, download = false): string {\r\n const params = new URLSearchParams({ sessionId, uuid })\r\n if (download) params.set('download', '1')\r\n return `/aigc-canvas/file?${params.toString()}`\r\n}\r\n\r\n/** Build the WebSocket URL for the canvas push endpoint. */\r\nexport function canvasWsUrl(sessionId: string): string {\r\n const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:'\r\n return `${proto}//${window.location.host}/aigc-canvas/ws/canvas?sessionId=${encodeURIComponent(sessionId)}`\r\n}\r\n\r\n// ── Request log (per docs/product/04-ux-reliability.md §3) ──────────────\r\n\r\n/** One request log entry (client view; matches the host RequestLogEntry). */\r\nexport interface RequestLogEntry {\r\n id: number\r\n timestamp: number\r\n type: 'http' | 'media_edit'\r\n providerId?: string\r\n method?: string\r\n path?: string\r\n operation?: string\r\n inputs?: string[]\r\n status: number\r\n durationMs: number\r\n size?: number\r\n error?: string\r\n requestHeaders?: Record<string, string>\r\n requestQuery?: Record<string, string>\r\n requestBodyPreview?: string\r\n responseContentType?: string\r\n responseBodyPreview?: string\r\n elementPath?: string\r\n}\r\n\r\n/** Fetch the request log for one session (newest last). */\r\nexport function fetchRequestLog(sessionId: string, signal?: AbortSignal): Promise<{ entries: RequestLogEntry[] }> {\r\n return call<{ entries: RequestLogEntry[] }>('logs.list', { sessionId }, signal)\r\n}\r\n\r\n/** Clear the request log for one session. */\r\nexport function clearRequestLog(sessionId: string, signal?: AbortSignal): Promise<{ ok: boolean }> {\r\n return call<{ ok: boolean }>('logs.clear', { sessionId }, signal)\r\n}\r\n\r\n// ── Cost tracking (per docs/product/04-ux-reliability.md §5) ─────────────\r\n\r\n/** Per-session cost breakdown. */\r\nexport interface SessionCost {\r\n total: number\r\n byProvider: Record<string, number>\r\n byCapability: Record<string, number>\r\n callCount: number\r\n}\r\n\r\n/** Fetch the per-session cost summary (for the canvas header). */\r\nexport function fetchSessionCost(sessionId: string, signal?: AbortSignal): Promise<SessionCost> {\r\n return call<SessionCost>('cost.get', { sessionId }, signal)\r\n}\r\n\r\n// ── Asset library (per docs/product/04-ux-reliability.md §6) ─────────────\r\n\r\n/** Asset category (matches the host AssetCategory enum). */\r\nexport type AssetCategory =\r\n | 'style-reference'\r\n | 'subject-reference'\r\n | 'prompt-template'\r\n | 'voice-sample'\r\n | 'final-product'\r\n\r\n/** Asset file type. */\r\nexport type AssetType = 'image' | 'prompt' | 'audio' | 'video'\r\n\r\n/** One asset in the cross-session library (client view). */\r\nexport interface LibraryAsset {\r\n id: string\r\n type: AssetType\r\n filePath: string\r\n title: string\r\n tags: string[]\r\n category: AssetCategory\r\n originalPrompt?: string\r\n sourceSessionId?: string\r\n sourceElementPath?: string\r\n createdAt: number\r\n metadata?: Record<string, unknown>\r\n}\r\n\r\n/** Optional filters for {@link fetchLibraryAssets}. */\r\nexport interface LibraryAssetFilter {\r\n type?: AssetType\r\n category?: AssetCategory\r\n tags?: string[]\r\n search?: string\r\n}\r\n\r\n/** List assets in the cross-session library (with optional filters). */\r\nexport function fetchLibraryAssets(filter?: LibraryAssetFilter, signal?: AbortSignal): Promise<{ assets: LibraryAsset[] }> {\r\n return call<{ assets: LibraryAsset[] }>('library.list', { ...(filter ?? {}) } as Record<string, unknown>, signal)\r\n}\r\n\r\n/** Promote one canvas element (by uuid) to the asset library. */\r\nexport function promoteAsset(sessionId: string, uuid: string, opts: { category: AssetCategory; title?: string; tags?: string[] }, signal?: AbortSignal): Promise<{ asset: LibraryAsset }> {\r\n return call<{ asset: LibraryAsset }>('library.promote', { sessionId, uuid, ...opts }, signal)\r\n}\r\n\r\n/** Remove one asset from the library (by id). Idempotent. */\r\nexport function removeAsset(assetId: string, signal?: AbortSignal): Promise<{ removed: boolean; asset_id: string }> {\r\n return call<{ removed: boolean; asset_id: string }>('library.remove', { asset_id: assetId }, signal)\r\n}\r\n","/**\n * Canvas view store: subscribes to the host push WebSocket for one session\n * and exposes a synchronous snapshot through useSyncExternalStore. Replays\n * the latest snapshot on reconnect; falls back to a one-shot HTTP fetch\n * when the WS is unavailable so a deployment without the upgrade route\n * still renders the canvas (with manual refresh).\n *\n * The store is per-session: the better-sidebar tab instantiates one per\n * scope.sessionId, and disposes it on tab close (the WS closes with it).\n */\nimport { deleteCanvasElement, fetchCanvas, moveCanvasElement, uploadCanvasFile, canvasWsUrl, type AigcCanvasState } from './api.js'\n\n/** Empty canvas state used as the pre-load placeholder. */\nfunction emptyState(sessionId: string): AigcCanvasState {\n return { sessionId, elements: [], edges: [] }\n}\n\ninterface StoreOptions {\n sessionId: string\n}\n\n/** One store instance per tab activation. */\nexport class CanvasStore {\n /** The session id this store is bound to. */\n readonly sessionId: string\n private state: AigcCanvasState\n private listeners = new Set<() => void>()\n private ws: WebSocket | undefined\n private reconnectTimer: number | undefined\n private disposed = false\n private fetchAbort: AbortController | undefined\n\n constructor(private readonly opts: StoreOptions) {\n this.sessionId = opts.sessionId\n this.state = emptyState(opts.sessionId)\n // Kick off the initial HTTP fetch (gives a snapshot before the WS opens)\n // and the WS subscription (drives live updates).\n void this.refresh()\n this.openWs()\n }\n\n /** Snapshot reader for useSyncExternalStore. */\n getSnapshot = (): AigcCanvasState => this.state\n\n /** Subscribe listener; returns disposer. */\n subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n /** Force a refresh (e.g. user clicked a refresh button). */\n async refresh(): Promise<void> {\n if (this.disposed) return\n this.fetchAbort?.abort()\n const ac = new AbortController()\n this.fetchAbort = ac\n try {\n const next = await fetchCanvas(this.opts.sessionId, ac.signal)\n if (!this.disposed) this.setState(next)\n } catch {\n // WS will catch up; the fetch is a best-effort priming read.\n }\n }\n\n /**\n * Persist a dragged element's new position. The authoritative snapshot\n * arrives over the WS push (the host notifies after persisting), so no\n * local state update is applied here.\n */\n async move(uuid: string, x: number, y: number): Promise<void> {\n if (this.disposed) return\n try {\n await moveCanvasElement(this.opts.sessionId, uuid, x, y)\n } catch {\n // Best-effort: the next WS snapshot carries the host's authoritative state.\n }\n }\n\n /** Delete an element (right-click → Delete). Best-effort; WS push catches up. */\n async deleteElement(uuid: string): Promise<void> {\n if (this.disposed) return\n try {\n await deleteCanvasElement(this.opts.sessionId, uuid)\n } catch {\n // Best-effort: the next WS snapshot carries the host's authoritative state.\n }\n }\n\n /** Upload a drag-dropped file and place it on the canvas. */\n async uploadFile(fileName: string, mediaBase64: string, opts?: { x?: number; y?: number }): Promise<void> {\n if (this.disposed) return\n try {\n await uploadCanvasFile(this.opts.sessionId, fileName, mediaBase64, opts)\n } catch {\n // Best-effort: the next WS snapshot carries the host's authoritative state.\n }\n }\n\n /** Tear down: close WS, abort any in-flight fetch, drop listeners. */\n dispose(): void {\n this.disposed = true\n this.fetchAbort?.abort()\n if (this.reconnectTimer !== undefined) {\n window.clearTimeout(this.reconnectTimer)\n this.reconnectTimer = undefined\n }\n if (this.ws !== undefined) {\n try { this.ws.close() } catch { /* ignore */ }\n this.ws = undefined\n }\n this.listeners.clear()\n }\n\n private setState(next: AigcCanvasState): void {\n this.state = next\n for (const fn of [...this.listeners]) fn()\n }\n\n private openWs(): void {\n if (this.disposed) return\n let ws: WebSocket\n try {\n ws = new WebSocket(canvasWsUrl(this.opts.sessionId))\n } catch {\n this.scheduleReconnect()\n return\n }\n this.ws = ws\n ws.onmessage = (event) => {\n try {\n const parsed = JSON.parse(event.data as string) as AigcCanvasState\n if (parsed && typeof parsed.sessionId === 'string') this.setState(parsed)\n } catch {\n // Ignore malformed frames — the host only sends valid JSON snapshots.\n }\n }\n ws.onclose = () => {\n if (this.disposed) return\n this.ws = undefined\n this.scheduleReconnect()\n }\n ws.onerror = () => {\n try { ws.close() } catch { /* close handler will run */ }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.disposed) return\n if (this.reconnectTimer !== undefined) return\n this.reconnectTimer = window.setTimeout(() => {\n this.reconnectTimer = undefined\n this.openWs()\n }, 2000)\n }\n}\n","/**\r\n * One canvas node: renders the element's media (image / video / audio) or\r\n * its prompt text, plus a small header row with kind dot + label and the\r\n * creation time. Rendered inside the infinite-canvas world layer at its\r\n * (x, y) position; dragging is handled by the parent view (the node div\r\n * carries the drag pointer handlers). Double-click opens the detail panel.\r\n *\r\n * ZOOM / BLUR FIX\r\n * ---------------\r\n * The world layer is scaled via `transform: scale(s)`. Browsers decode\r\n * `<img>`/`<video>` at their CSS layout size (the card's 220px content\r\n * width), NOT the post-transform screen size — so zooming in upscales a\r\n * small decoded bitmap and the media looks blurry.\r\n *\r\n * To get crisp media at every zoom level, each img/video sets its CSS\r\n * width to `100% * scale` (the on-screen pixel width) and then applies\r\n * `transform: scale(1/scale)` to visually shrink back to the 220px layout\r\n * box. The browser then decodes at the larger size and the world\r\n * transform produces a 1:1 (or downscaled) screen image — sharp.\r\n *\r\n * The layout box still grows to `220*scale` wide, which would push\r\n * siblings and inflate the card. Negative `margin-right` / `margin-bottom`\r\n * (expressed as `%` of the container width = 220px) cancel the excess so\r\n * the effective layout footprint is unchanged. The bottom margin needs\r\n * the media's aspect ratio (h/w), captured from `onLoad`/`onLoadedMetadata`.\r\n */\r\nimport { createElement, useState, type CSSProperties, type ReactNode, type SyntheticEvent } from 'react'\r\nimport type { AigcElement } from './api.js'\r\nimport { mediaUrlOf } from './api.js'\r\nimport css from './canvas.module.css'\r\n\r\n/** Translation function type (from the DSH locale system). */\r\ntype Translate = (key: string) => string\r\n\r\n/** Short label for one element kind. */\r\nfunction kindLabel(kind: AigcElement['kind'], t: Translate): string {\r\n switch (kind) {\r\n case 'prompt': return t('prompt')\r\n case 'image': return t('image')\r\n case 'video': return t('video')\r\n case 'audio': return t('audio')\r\n }\r\n}\r\n\r\n/** Format the createdAt timestamp as a short HH:MM:SS. */\r\nfunction formatTime(ms: number): string {\r\n const d = new Date(ms)\r\n const pad = (n: number): string => n < 10 ? `0${n}` : String(n)\r\n return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\r\n}\r\n\r\n/** Default aspect ratio (h/w) used before media metadata loads. 4:3 → 0.75. */\r\nconst DEFAULT_RATIO = 0.75\r\n\r\n/**\r\n * One image element. Captures its natural aspect ratio on load so the\r\n * negative bottom margin (which cancels the layout-box inflation from the\r\n * counter-scale trick) can be computed from CSS variables alone.\r\n */\r\nfunction MediaImage({ url, alt }: { url: string; alt: string }): ReactNode {\r\n const [ratio, setRatio] = useState(DEFAULT_RATIO)\r\n const onLoad = (e: SyntheticEvent<HTMLImageElement>): void => {\r\n const img = e.currentTarget\r\n if (img.naturalWidth > 0) {\r\n setRatio(img.naturalHeight / img.naturalWidth)\r\n }\r\n }\r\n return createElement('img', {\r\n className: css.mediaImage,\r\n src: url,\r\n alt,\r\n loading: 'lazy',\r\n draggable: false,\r\n onLoad,\r\n style: { ['--media-ratio' as string]: ratio } as CSSProperties,\r\n })\r\n}\r\n\r\n/**\r\n * One video element. Same counter-scale trick as MediaImage; the aspect\r\n * ratio comes from `loadedmetadata` (videoWidth / videoHeight).\r\n */\r\nfunction MediaVideo({ url }: { url: string }): ReactNode {\r\n const [ratio, setRatio] = useState(DEFAULT_RATIO)\r\n const onLoadedMetadata = (e: SyntheticEvent<HTMLVideoElement>): void => {\r\n const v = e.currentTarget\r\n if (v.videoWidth > 0) {\r\n setRatio(v.videoHeight / v.videoWidth)\r\n }\r\n }\r\n return createElement('video', {\r\n className: css.mediaVideo,\r\n src: url,\r\n controls: true,\r\n preload: 'metadata',\r\n onLoadedMetadata,\r\n style: { ['--media-ratio' as string]: ratio } as CSSProperties,\r\n })\r\n}\r\n\r\n/** Render one element's media (or prompt text) based on its kind. */\r\nfunction renderMedia(el: AigcElement): ReactNode {\r\n if (el.kind === 'prompt') {\r\n return createElement('pre', { className: css.promptText }, el.promptText ?? '')\r\n }\r\n // Media route needs the uuid (the host resolves uuid → filePath internally).\r\n // The uuid is present on every element the WS push delivers.\r\n if (el.uuid === undefined) return null\r\n const url = mediaUrlOf(el.sessionId ?? '', el.uuid)\r\n if (el.kind === 'image') {\r\n return createElement(MediaImage, { url, alt: el.title })\r\n }\r\n if (el.kind === 'video') {\r\n return createElement(MediaVideo, { url })\r\n }\r\n // audio — native control, no bitmap to sharpen\r\n return createElement('audio', {\r\n className: css.mediaAudio,\r\n src: url,\r\n controls: true,\r\n preload: 'metadata',\r\n })\r\n}\r\n\r\nexport interface CanvasNodeProps {\r\n element: AigcElement\r\n t: Translate\r\n}\r\n\r\n/** One canvas node (fixed-width card; height follows content). */\r\nexport function CanvasNode({ element, t }: CanvasNodeProps): ReactNode {\r\n const kindDotClass = `${css.kindDot} ${css[`kindDot_${element.kind}`] ?? ''}`\r\n const statusClass = element.status !== undefined && element.status !== 'ready' ? ` ${css[`nodeStatus_${element.status}`] ?? ''}` : ''\r\n const winnerBadge = element.winner === true\r\n return createElement(\r\n 'div',\r\n {\r\n className: `${css.node}${statusClass}`,\r\n 'data-uuid': element.uuid ?? '',\r\n 'data-filepath': element.filePath,\r\n },\r\n createElement(\r\n 'div',\r\n { className: css.nodeHeader },\r\n createElement('span', { className: kindDotClass, 'aria-hidden': true }),\r\n createElement('span', { className: css.kindLabel }, kindLabel(element.kind, t)),\r\n winnerBadge ? createElement('span', { className: css.winnerBadge, title: t('winner') }, '★') : null,\r\n createElement('span', { className: css.nodeTime }, formatTime(element.createdAt)),\r\n ),\r\n createElement('div', { className: css.nodeTitle }, element.title),\r\n element.description !== undefined && element.description !== ''\r\n ? createElement('div', { className: css.nodeDescription }, element.description)\r\n : null,\r\n createElement('div', { className: css.nodeMedia }, renderMedia(element)),\r\n )\r\n}\r\n","/**\r\n * Floating request log panel: shows every aigc_http_request + aigc_media_edit\r\n * call (success or failure) so the user can debug failed generations from the\r\n * canvas UI. Per docs/product/04-ux-reliability.md §3.\r\n *\r\n * Features:\r\n * - Toggle button in the canvas header (shows the entry count badge)\r\n * - Floating panel (right side, like the detail panel) with the entry list\r\n * - Each entry: timestamp + type icon + provider/path + status + duration + size\r\n * - Click an entry to expand details (request headers/body + response preview;\r\n * apiKey is already redacted on the host side)\r\n * - \"Clear\" button wipes the session log\r\n * - Failed entries (status >= 400) are highlighted in red\r\n * - \"Locate on canvas\" button pans to the element produced by the request\r\n * (when elementPath is set) — wired through a callback prop\r\n *\r\n * The panel polls /aigc-canvas/api/logs.list every 2s when open (lightweight;\r\n * avoids WS protocol changes). The host caps at 200 entries per session.\r\n */\r\nimport { Component, createElement, useEffect, useState, type ReactNode, type ErrorInfo } from 'react'\r\nimport type { RequestLogEntry } from './api.js'\r\nimport { fetchRequestLog, clearRequestLog } from './api.js'\r\nimport css from './canvas.module.css'\r\n\r\n/** Translate function type (from the DSH locale system). */\r\ntype Translate = (key: string) => string\r\n\r\n/** Props for the log panel. */\r\nexport interface RequestLogPanelProps {\r\n /** Session id (used for the API calls). */\r\n sessionId: string\r\n /** Locale translate function. */\r\n t: Translate\r\n /** Callback to pan the canvas to one element (by filePath). */\r\n locateElement: (filePath: string) => void\r\n}\r\n\r\n/** Format a timestamp as HH:MM:SS.mmm. */\r\nfunction formatTime(ms: number): string {\r\n const d = new Date(ms)\r\n const h = String(d.getHours()).padStart(2, '0')\r\n const m = String(d.getMinutes()).padStart(2, '0')\r\n const s = String(d.getSeconds()).padStart(2, '0')\r\n const millis = String(d.getMilliseconds()).padStart(3, '0')\r\n return `${h}:${m}:${s}.${millis}`\r\n}\r\n\r\n/** Format a byte size human-readably. */\r\nfunction formatSize(bytes: number | undefined): string {\r\n if (bytes === undefined) return '-'\r\n if (bytes < 1024) return `${bytes}B`\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`\r\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`\r\n}\r\n\r\n/** Format a duration in ms. */\r\nfunction formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms}ms`\r\n return `${(ms / 1000).toFixed(1)}s`\r\n}\r\n\r\n/** One collapsible log entry row. */\r\nclass LogEntryRow extends Component<{\r\n entry: RequestLogEntry\r\n t: Translate\r\n locateElement: (filePath: string) => void\r\n}, { expanded: boolean }> {\r\n override state = { expanded: false }\r\n\r\n override render(): ReactNode {\r\n const { entry, t, locateElement } = this.props\r\n const failed = entry.status >= 400 || entry.error !== undefined\r\n const label = entry.type === 'http'\r\n ? `${entry.method ?? '?'} ${entry.path ?? '?'}`\r\n : `ffmpeg: ${entry.operation ?? '?'}`\r\n const provider = entry.providerId !== undefined ? ` ${entry.providerId}` : ''\r\n return createElement('div', { className: css.logRow },\r\n createElement('button', {\r\n type: 'button',\r\n className: `${css.logRowHeader} ${failed ? css.logRowFailed : ''}`,\r\n onClick: () => this.setState({ expanded: !this.state.expanded }),\r\n },\r\n createElement('span', { className: css.logTime }, formatTime(entry.timestamp)),\r\n createElement('span', { className: css.logLabel }, `${label}${provider}`),\r\n createElement('span', { className: css.logStatus }, String(entry.status)),\r\n createElement('span', { className: css.logDuration }, formatDuration(entry.durationMs)),\r\n createElement('span', { className: css.logSize }, formatSize(entry.size)),\r\n createElement('span', { className: css.logExpand }, this.state.expanded ? '▼' : '▶'),\r\n ),\r\n this.state.expanded && createElement('div', { className: css.logDetail },\r\n entry.error !== undefined && createElement('div', { className: css.logError }, `${t('logError')}: ${entry.error}`),\r\n entry.requestBodyPreview !== undefined && createElement('div', { className: css.logDetailBlock },\r\n createElement('span', { className: css.logDetailLabel }, t('logRequestBody')),\r\n createElement('pre', { className: css.logDetailPre }, entry.requestBodyPreview),\r\n ),\r\n entry.requestHeaders !== undefined && createElement('div', { className: css.logDetailBlock },\r\n createElement('span', { className: css.logDetailLabel }, t('logRequestHeaders')),\r\n createElement('pre', { className: css.logDetailPre }, JSON.stringify(entry.requestHeaders, null, 2)),\r\n ),\r\n entry.responseBodyPreview !== undefined && createElement('div', { className: css.logDetailBlock },\r\n createElement('span', { className: css.logDetailLabel }, t('logResponseBody')),\r\n createElement('pre', { className: css.logDetailPre }, entry.responseBodyPreview),\r\n ),\r\n entry.elementPath !== undefined && createElement('div', { className: css.logDetailBlock },\r\n createElement('span', { className: css.logDetailLabel }, t('logProducedFile')),\r\n createElement('code', { className: css.logFilePath }, entry.elementPath),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.logLocateButton,\r\n onClick: () => locateElement(entry.elementPath!),\r\n }, t('logLocate')),\r\n ),\r\n ),\r\n )\r\n }\r\n}\r\n\r\n/** Error boundary so a render failure in the panel doesn't blank the canvas. */\r\nclass LogBoundary extends Component<{ children: ReactNode }, { error: string | null }> {\r\n override state = { error: null as string | null }\r\n static getDerivedStateFromError(error: unknown): { error: string } {\r\n return { error: error instanceof Error ? error.message : String(error) }\r\n }\r\n override componentDidCatch(error: Error, info: ErrorInfo): void {\r\n console.error('[dsh-aigc-canvas] log panel error:', error, info.componentStack)\r\n }\r\n override render(): ReactNode {\r\n if (this.state.error !== null) {\r\n return createElement('div', { className: css.boundaryError }, `log panel: ${this.state.error}`)\r\n }\r\n return this.props.children\r\n }\r\n}\r\n\r\n/**\r\n * The request log panel. Renders as a floating panel on the right side of\r\n * the canvas. Polls the host every 2s for new entries while open.\r\n */\r\nexport function RequestLogPanel({ sessionId, t, locateElement }: RequestLogPanelProps): ReactNode {\r\n const [entries, setEntries] = useState<RequestLogEntry[]>([])\r\n const [loading, setLoading] = useState(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n useEffect(() => {\r\n let cancelled = false\r\n const poll = async (): Promise<void> => {\r\n try {\r\n const result = await fetchRequestLog(sessionId)\r\n if (!cancelled) {\r\n setEntries([...result.entries])\r\n setError(null)\r\n }\r\n } catch (e) {\r\n if (!cancelled) setError(e instanceof Error ? e.message : String(e))\r\n } finally {\r\n if (!cancelled) setLoading(false)\r\n }\r\n }\r\n void poll()\r\n const timer = setInterval(poll, 2000)\r\n return () => { cancelled = true; clearInterval(timer) }\r\n }, [sessionId])\r\n\r\n const onClear = async (): Promise<void> => {\r\n try {\r\n await clearRequestLog(sessionId)\r\n setEntries([])\r\n } catch (e) {\r\n setError(e instanceof Error ? e.message : String(e))\r\n }\r\n }\r\n\r\n return createElement(LogBoundary, null,\r\n createElement('div', { className: css.logPanel },\r\n createElement('div', { className: css.logPanelHeader },\r\n createElement('span', { className: css.logPanelTitle }, `${t('logTitle')} (${entries.length})`),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.logPanelClear,\r\n onClick: () => { void onClear() },\r\n disabled: entries.length === 0,\r\n }, t('logClear')),\r\n ),\r\n error !== null && createElement('div', { className: css.boundaryError }, `${t('logError')}: ${error}`),\r\n loading && entries.length === 0\r\n ? createElement('div', { className: css.empty }, t('logLoading'))\r\n : entries.length === 0\r\n ? createElement('div', { className: css.empty }, t('logEmpty'))\r\n : createElement('div', { className: css.logList },\r\n ...[...entries].reverse().map(entry =>\r\n createElement(LogEntryRow, {\r\n key: entry.id,\r\n entry,\r\n t,\r\n locateElement,\r\n }),\r\n ),\r\n ),\r\n ),\r\n )\r\n}\r\n","/**\r\n * Pure helpers for the compare view (per docs/product/04-ux-reliability.md §2).\r\n *\r\n * The canvas element's `meta` is a free-form JSON object the agent writes\r\n * when placing a generated asset. Common keys seen in the wild:\r\n * - `seed` — the generation seed (integer)\r\n * - `size` — image/video size string (e.g. \"1024x1024\")\r\n * - `durationSeconds`— video/audio length (number; host-written)\r\n * - `cost` — USD cost of the call (number; host-written when\r\n * cost tracking is wired into the placement path)\r\n * - `costUsd` — alternate key some agents use\r\n * - `durationMs` — wall-clock duration of the provider call (number)\r\n *\r\n * These helpers tolerate missing keys, wrong types, and `meta` being\r\n * absent entirely — they return `undefined` so the UI can render \"—\".\r\n *\r\n * @module @huanlin/dsh-plugin-aigc-canvas/client/compare-helpers\r\n */\r\nimport type { AigcElement } from './api.js'\r\n\r\n/**\r\n * Read a numeric field from a free-form meta object, tolerating:\r\n * - missing key\r\n * - non-numeric value (string-encoded numbers are accepted; everything\r\n * else returns undefined)\r\n * - `null` / `undefined`\r\n *\r\n * Strings are accepted because the agent sometimes writes `\"seed\": \"42\"`\r\n * (JSON-object values sneak through as strings when the model wraps them\r\n * in quotes).\r\n */\r\nexport function readNumber(meta: Record<string, unknown> | undefined, key: string): number | undefined {\r\n if (meta === undefined) return undefined\r\n const v = meta[key]\r\n if (v === null || v === undefined) return undefined\r\n if (typeof v === 'number' && Number.isFinite(v)) return v\r\n if (typeof v === 'string') {\r\n const n = Number(v)\r\n if (Number.isFinite(n) && v.trim() !== '') return n\r\n }\r\n return undefined\r\n}\r\n\r\n/**\r\n * Extract the generation seed from an element's meta.\r\n *\r\n * Looks at `seed` (the canonical key) and falls back to `random_seed`\r\n * (some providers use that name). Returns undefined when neither is a\r\n * finite number.\r\n */\r\nexport function getElementSeed(el: AigcElement): number | undefined {\r\n const m = el.meta\r\n if (m === undefined) return undefined\r\n return readNumber(m, 'seed') ?? readNumber(m, 'random_seed')\r\n}\r\n\r\n/**\r\n * Extract the USD cost of producing one element from its meta.\r\n *\r\n * Looks at `cost`, then `costUsd`. Returns undefined when neither is a\r\n * finite number (the agent doesn't always set this — the host's\r\n * cost-tracker is the source of truth, but it isn't yet written back\r\n * into meta on placement).\r\n */\r\nexport function getElementCost(el: AigcElement): number | undefined {\r\n const m = el.meta\r\n if (m === undefined) return undefined\r\n return readNumber(m, 'cost') ?? readNumber(m, 'costUsd')\r\n}\r\n\r\n/**\r\n * Extract the wall-clock duration (in ms) of producing one element.\r\n *\r\n * Looks at `durationMs` (host convention) and falls back to\r\n * `durationSeconds` × 1000 (some agents write the duration in seconds).\r\n * Returns undefined when neither is set.\r\n */\r\nexport function getElementDurationMs(el: AigcElement): number | undefined {\r\n const m = el.meta\r\n if (m === undefined) return undefined\r\n const ms = readNumber(m, 'durationMs')\r\n if (ms !== undefined) return ms\r\n const seconds = readNumber(m, 'durationSeconds')\r\n if (seconds !== undefined) return seconds * 1000\r\n // Some agents write just `duration` and expect the unit to be inferred\r\n // from the kind (video → seconds, audio → seconds, image → ms). Treat\r\n // `duration` as ms for images and seconds for video/audio (matches the\r\n // doc 04 §2 mock-up which shows \"3.4s\" for image generations — that\r\n // is actually the wall-clock time, not the media length, so ms is\r\n // correct for images).\r\n const raw = readNumber(m, 'duration')\r\n if (raw === undefined) return undefined\r\n if (el.kind === 'video' || el.kind === 'audio') return raw * 1000\r\n return raw\r\n}\r\n\r\n/** Format a USD cost as a short `$X.XX` string, or \"—\" when unknown. */\r\nexport function formatCost(usd: number | undefined): string {\r\n if (usd === undefined) return '—'\r\n // 0 is a real value (free call) — render as $0.00, not a tiny cost.\r\n if (usd === 0) return '$0.00'\r\n if (usd > 0 && usd < 0.01) return `$${usd.toFixed(4)}`\r\n return `$${usd.toFixed(2)}`\r\n}\r\n\r\n/** Format a duration in ms as `X.Xs` (or `XXXms` when < 1s). Returns \"—\" when undefined. */\r\nexport function formatDurationShort(ms: number | undefined): string {\r\n if (ms === undefined) return '—'\r\n if (ms < 1000) return `${Math.round(ms)}ms`\r\n return `${(ms / 1000).toFixed(1)}s`\r\n}\r\n\r\n/** Format a seed value (integer) as a string, or \"—\" when undefined. */\r\nexport function formatSeed(seed: number | undefined): string {\r\n if (seed === undefined) return '—'\r\n return String(seed)\r\n}\r\n","/**\r\n * CompareView — floating overlay that lets the user compare 2-4 selected\r\n * canvas elements side by side and pick a winner.\r\n *\r\n * Per docs/product/04-ux-reliability.md §2:\r\n * - All selected elements shown at the same scale, side by side\r\n * - Each element shows: image/video, prompt, seed, cost, duration (from meta)\r\n * - \"Select as winner\" button under each → calls setElementStatus(uuid,\r\n * 'ready', true) + archives the others\r\n * - \"Reject all\" button → calls setElementStatus(uuid, 'rejected') for all\r\n * - \"Close\" button → unmounts the overlay (handled by parent)\r\n *\r\n * The overlay is rendered as a fixed-position layer above the canvas\r\n * surface (z-index above the detail panel + log panel + toolbar). It\r\n * does NOT intercept canvas pointer events outside its own bounds.\r\n *\r\n * @module @huanlin/dsh-plugin-aigc-canvas/client/CompareView\r\n */\r\nimport { Component, createElement, useEffect, useState, type CSSProperties, type ErrorInfo, type ReactNode } from 'react'\r\nimport type { AigcElement, ElementStatus } from './api.js'\r\nimport { mediaUrlOf, setElementStatus } from './api.js'\r\nimport {\r\n formatCost,\r\n formatDurationShort,\r\n formatSeed,\r\n getElementCost,\r\n getElementDurationMs,\r\n getElementSeed,\r\n} from './compare-helpers.js'\r\nimport css from './canvas.module.css'\r\n\r\n/** Translation function type (from the DSH locale system). */\r\ntype Translate = (key: string) => string\r\n\r\n/** Props for the compare view overlay. */\r\nexport interface CompareViewProps {\r\n /** Session id (used for the API calls + media URL construction). */\r\n sessionId: string\r\n /** Selected elements to compare (already validated to be 2-4 by the parent). */\r\n elements: readonly AigcElement[]\r\n /** Locale translate function. */\r\n t: Translate\r\n /** Called when the user clicks \"Close\" or presses Escape. */\r\n onClose: () => void\r\n}\r\n\r\n/**\r\n * The compare view overlay. Renders as a fixed-position layer above the\r\n * canvas. Winner/reject actions fire `setElementStatus` calls; the WS\r\n * push carries the authoritative state back into the canvas snapshot.\r\n */\r\nexport function CompareView({ sessionId, elements, t, onClose }: CompareViewProps): ReactNode {\r\n return createElement(CompareBoundary, { t, children: createElement(CompareViewInner, { sessionId, elements, t, onClose }) })\r\n}\r\n\r\n/** Inner component (wrapped by the boundary so a render error doesn't blank the canvas). */\r\nfunction CompareViewInner({ sessionId, elements, t, onClose }: CompareViewProps): ReactNode {\r\n // Track which element (if any) the user just picked as winner, so we\r\n // can show a brief \"archiving others…\" state and disable buttons while\r\n // the WS push is in flight. Best-effort: failures are swallowed (the\r\n // next WS snapshot carries the authoritative state regardless).\r\n const [pendingWinner, setPendingWinner] = useState<string | undefined>(undefined)\r\n const [pendingReject, setPendingReject] = useState<boolean>(false)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Close on Escape (per the doc's \"Close\" affordance — also lets keyboard\r\n // users dismiss the overlay).\r\n useEffect(() => {\r\n const onKey = (e: KeyboardEvent): void => { if (e.key === 'Escape') onClose() }\r\n window.addEventListener('keydown', onKey)\r\n return () => window.removeEventListener('keydown', onKey)\r\n }, [onClose])\r\n\r\n /**\r\n * Pick one element as the winner: keep it as `ready` with the winner\r\n * flag, archive the others. Per doc 04 §2: \"选 winner 后其他自动归档\r\n * (status = archived)\".\r\n */\r\n const onPickWinner = async (winner: AigcElement): Promise<void> => {\r\n if (winner.uuid === undefined) return\r\n const winnerUuid = winner.uuid\r\n const losers = elements.filter(e => e.uuid !== undefined && e.uuid !== winnerUuid)\r\n setPendingWinner(winnerUuid)\r\n setError(null)\r\n try {\r\n // 1. Mark the winner: status stays 'ready', winner flag = true.\r\n await setElementStatus(sessionId, winnerUuid, 'ready', true)\r\n // 2. Archive the others. Fire-and-forget the parallel calls — the\r\n // WS push carries the final state; we don't need to wait.\r\n await Promise.all(\r\n losers.map(e => setElementStatus(sessionId, e.uuid!, 'archived' as ElementStatus)),\r\n )\r\n } catch (e) {\r\n setError(e instanceof Error ? e.message : String(e))\r\n } finally {\r\n setPendingWinner(undefined)\r\n }\r\n }\r\n\r\n /**\r\n * Reject all: mark every selected element as `rejected`. Per doc 04 §2:\r\n * \"全部否决 → 所有标 rejected\".\r\n */\r\n const onRejectAll = async (): Promise<void> => {\r\n setPendingReject(true)\r\n setError(null)\r\n try {\r\n await Promise.all(\r\n elements.map(e => e.uuid !== undefined\r\n ? setElementStatus(sessionId, e.uuid, 'rejected')\r\n : Promise.resolve()),\r\n )\r\n } catch (e) {\r\n setError(e instanceof Error ? e.message : String(e))\r\n } finally {\r\n setPendingReject(false)\r\n }\r\n }\r\n\r\n // Header count: \"已选 N 个\" — the doc shows this on the canvas toolbar,\r\n // but it's also useful inside the overlay title for context.\r\n const count = elements.length\r\n\r\n return createElement(\r\n 'div',\r\n {\r\n className: css.compareOverlay,\r\n // Stop wheel events from propagating to the canvas surface below\r\n // (the canvas zoom-on-wheel handler would otherwise zoom the canvas\r\n // while the user scrolls inside the compare view).\r\n onWheel: (e: React.WheelEvent<HTMLDivElement>) => e.stopPropagation(),\r\n // Stop pointer events from reaching the canvas surface (so dragging\r\n // inside the overlay doesn't pan the canvas).\r\n onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => e.stopPropagation(),\r\n },\r\n createElement(\r\n 'div',\r\n { className: css.compareHeader },\r\n createElement('span', { className: css.compareTitle }, `${t('compareTitle')} (${count})`),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.compareCloseButton,\r\n onClick: onClose,\r\n 'aria-label': t('compareClose'),\r\n }, '×'),\r\n ),\r\n error !== null && createElement('div', { className: css.boundaryError }, error),\r\n createElement(\r\n 'div',\r\n { className: css.compareGrid },\r\n ...elements.map(el => createElement(CompareCard, {\r\n key: el.uuid ?? el.filePath,\r\n element: el,\r\n sessionId,\r\n t,\r\n pending: pendingWinner === el.uuid || pendingReject,\r\n onPickWinner: () => { void onPickWinner(el) },\r\n })),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.compareFooter },\r\n createElement('button', {\r\n type: 'button',\r\n className: `${css.compareButtonDanger}`,\r\n onClick: () => { void onRejectAll() },\r\n disabled: pendingReject || pendingWinner !== undefined,\r\n }, t('compareRejectAll')),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.compareButtonSecondary,\r\n onClick: onClose,\r\n }, t('compareClose')),\r\n ),\r\n )\r\n}\r\n\r\n/** One element card in the compare grid. */\r\nfunction CompareCard(props: {\r\n element: AigcElement\r\n sessionId: string\r\n t: Translate\r\n pending: boolean\r\n onPickWinner: () => void\r\n}): ReactNode {\r\n const { element: el, sessionId, t, pending, onPickWinner } = props\r\n const seed = getElementSeed(el)\r\n const cost = getElementCost(el)\r\n const durationMs = getElementDurationMs(el)\r\n // The card body height is determined by the tallest card in the row.\r\n // We use a fixed target media box so all cards line up — the media is\r\n // `object-fit: contain` so different aspect ratios still render fully.\r\n return createElement(\r\n 'div',\r\n { className: css.compareCard },\r\n createElement(\r\n 'div',\r\n { className: css.compareCardMedia },\r\n createElement(CompareMedia, { element: el, sessionId, t }),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.compareCardBody },\r\n el.promptText !== undefined && el.promptText !== ''\r\n ? createElement('pre', { className: css.comparePrompt }, el.promptText)\r\n : createElement('div', { className: css.comparePromptEmpty }, t('comparePrompt')),\r\n createElement(\r\n 'div',\r\n { className: css.compareMetaRow },\r\n createElement('span', { className: css.compareMetaLabel }, `${t('compareSeed')}:`),\r\n createElement('span', { className: css.compareMetaValue }, formatSeed(seed)),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.compareMetaRow },\r\n createElement('span', { className: css.compareMetaLabel }, `${t('compareCost')}:`),\r\n createElement('span', { className: css.compareMetaValue }, formatCost(cost)),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.compareMetaRow },\r\n createElement('span', { className: css.compareMetaLabel }, `${t('compareDuration')}:`),\r\n createElement('span', { className: css.compareMetaValue }, formatDurationShort(durationMs)),\r\n ),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.compareCardFooter },\r\n createElement('button', {\r\n type: 'button',\r\n className: css.compareButtonPrimary,\r\n onClick: onPickWinner,\r\n disabled: pending || el.uuid === undefined,\r\n title: el.title,\r\n }, t('compareSelectWinner')),\r\n ),\r\n )\r\n}\r\n\r\n/** Renders the element's media (image / video / audio) at a fixed target size. */\r\nfunction CompareMedia(props: { element: AigcElement; sessionId: string; t: Translate }): ReactNode {\r\n const { element: el, sessionId, t } = props\r\n if (el.kind === 'prompt') {\r\n // Prompts have no media; show the title as a centered text block so\r\n // the card still has visual presence in the compare row.\r\n return createElement('div', { className: css.compareMediaEmpty }, el.title)\r\n }\r\n if (el.uuid === undefined) {\r\n return createElement('div', { className: css.compareMediaEmpty }, t('compareNoMedia'))\r\n }\r\n const url = mediaUrlOf(sessionId, el.uuid)\r\n if (el.kind === 'image') {\r\n return createElement('img', {\r\n className: css.compareMediaImage,\r\n src: url,\r\n alt: el.title,\r\n loading: 'lazy',\r\n draggable: false,\r\n })\r\n }\r\n if (el.kind === 'video') {\r\n return createElement('video', {\r\n className: css.compareMediaVideo,\r\n src: url,\r\n controls: true,\r\n preload: 'metadata',\r\n })\r\n }\r\n // audio — native control inside the fixed-size media box\r\n return createElement('div', { className: css.compareMediaAudioWrap },\r\n createElement('audio', {\r\n className: css.compareMediaAudio,\r\n src: url,\r\n controls: true,\r\n preload: 'metadata',\r\n }),\r\n )\r\n}\r\n\r\n/** Error boundary so a render failure shows a strip instead of blanking the overlay. */\r\nclass CompareBoundary extends Component<{ children: ReactNode; t: Translate }, { error: string | null }> {\r\n override state = { error: null as string | null }\r\n static getDerivedStateFromError(error: unknown): { error: string } {\r\n return { error: error instanceof Error ? error.message : String(error) }\r\n }\r\n override componentDidCatch(error: Error, info: ErrorInfo): void {\r\n console.error('[dsh-aigc-canvas] compare view error:', error, info.componentStack)\r\n }\r\n override render(): ReactNode {\r\n if (this.state.error !== null) {\r\n return createElement('div', { className: css.boundaryError, style: { margin: '8px' as unknown as CSSProperties['margin'] } }, `${this.props.t('loadError')}: ${this.state.error}`)\r\n }\r\n return this.props.children\r\n }\r\n}\r\n","/**\r\n * The infinite canvas view: a free, pannable + zoomable surface where\r\n * elements live at arbitrary world positions (x, y) and edges render as\r\n * smooth curves between right/left ports.\r\n *\r\n * Interactions:\r\n * - drag an element: moves it (persisted via the canvas.move API on release)\r\n * - drag the background: pans the viewport\r\n * - wheel: zooms around the cursor (clamped 0.2×–4×)\r\n * - zoom slider / +/- buttons in the header: zoom from center\r\n * - minimap (bottom-right): click/drag to pan; shows element outlines + viewport frame\r\n * - double-click an element: opens the detail panel (prompt + params + path)\r\n *\r\n * The WS push delivers authoritative snapshots; dragged positions are\r\n * applied locally as drafts during the gesture and confirmed by the push\r\n * (the host notifies after persisting the move).\r\n */\r\nimport { Component, createElement, useEffect, useRef, useState, useSyncExternalStore, type CSSProperties, type ErrorInfo, type ReactNode, type PointerEvent as ReactPointerEvent, type MouseEvent as ReactMouseEvent, type ChangeEvent as ReactChangeEvent } from 'react'\r\nimport type { AigcCanvasState, AigcEdge, AigcElement, EdgeRelation, ElementStatus, SessionCost } from './api.js'\r\nimport { CanvasStore } from './store.js'\r\nimport { CanvasNode } from './CanvasNode.js'\r\nimport { RequestLogPanel } from './RequestLogPanel.js'\r\nimport { CompareView } from './CompareView.js'\r\nimport { fetchSessionCost, mediaUrlOf, notifyAgent, promoteAsset, setElementStatus } from './api.js'\r\nimport css from './canvas.module.css'\r\n\r\n/** Translation function type (from the DSH locale system). */\r\ntype Translate = (key: string) => string\r\n\r\n/** Error boundary so a render failure shows a strip instead of blanking. */\r\nclass CanvasBoundary extends Component<{ children: ReactNode; t: Translate }, { error: string | null }> {\r\n override state = { error: null as string | null }\r\n static getDerivedStateFromError(error: unknown): { error: string } {\r\n return { error: error instanceof Error ? error.message : String(error) }\r\n }\r\n override componentDidCatch(error: Error, info: ErrorInfo): void {\r\n console.error('[dsh-aigc-canvas] render error:', error, info.componentStack)\r\n }\r\n override render(): ReactNode {\r\n if (this.state.error !== null) {\r\n return createElement('div', { className: css.boundaryError }, `${this.props.t('loadError')}: ${this.state.error}`)\r\n }\r\n return this.props.children\r\n }\r\n}\r\n\r\n/** Viewport state: world→screen is `screen = world * scale + (x, y)`. */\r\ninterface Viewport {\r\n x: number\r\n y: number\r\n scale: number\r\n}\r\n\r\nconst MIN_SCALE = 0.2\r\nconst MAX_SCALE = 4\r\n\r\n/** Fixed node box for edge anchoring (world units). Must match CSS .nodeBox width. */\r\nconst NODE_W = 240\r\nconst NODE_H = 110\r\n\r\n/** Zoom at the cursor position, keeping the world point under the cursor fixed. */\r\nfunction zoomAt(viewport: Viewport, cx: number, cy: number, factor: number): Viewport {\r\n const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, viewport.scale * factor))\r\n const worldX = (cx - viewport.x) / viewport.scale\r\n const worldY = (cy - viewport.y) / viewport.scale\r\n return { scale, x: cx - worldX * scale, y: cy - worldY * scale }\r\n}\r\n\r\n/** Build a uuid → element map. */\r\nfunction elementMap(elements: readonly AigcElement[]): Map<string, AigcElement> {\r\n const map = new Map<string, AigcElement>()\r\n for (const el of elements) {\r\n if (el.uuid !== undefined) map.set(el.uuid, el)\r\n }\r\n return map\r\n}\r\n\r\n/** Position resolver: returns draft position if dragging, else the element's own. */\r\ntype PosResolver = (uuid: string) => { x: number; y: number } | undefined\r\n\r\n/** Port radius (the small circle drawn at each connection point). */\r\nconst PORT_R = 5\r\n\r\n/**\r\n * Line-style group for one EdgeRelation. Drives the SVG path's stroke\r\n * pattern + width. The label (short human-readable text rendered at the\r\n * curve's midpoint) is looked up separately in `EDGE_RELATION_LABEL`.\r\n *\r\n * Group mapping (per docs/product/01-agent-autonomy.md §1):\r\n * - solid: direct inputs (input / first_frame / last_frame / audio_track)\r\n * - dashed: references (reference / style / mask)\r\n * - dotted: variations / candidates (variation_of / remix_of / alternative_of)\r\n * - bold: ffmpeg edit chain (edited_from)\r\n */\r\ntype EdgeLineStyle = 'solid' | 'dashed' | 'dotted' | 'bold'\r\n\r\nfunction lineStyleOf(relation: EdgeRelation | undefined): EdgeLineStyle {\r\n switch (relation) {\r\n case 'reference':\r\n case 'style':\r\n case 'mask':\r\n return 'dashed'\r\n case 'variation_of':\r\n case 'remix_of':\r\n case 'alternative_of':\r\n return 'dotted'\r\n case 'edited_from':\r\n return 'bold'\r\n case 'input':\r\n case 'first_frame':\r\n case 'last_frame':\r\n case 'audio_track':\r\n case undefined:\r\n default:\r\n return 'solid'\r\n }\r\n}\r\n\r\n/** Short human-readable label for one EdgeRelation (rendered at the curve midpoint). */\r\nconst EDGE_RELATION_LABEL: Record<EdgeRelation, string> = {\r\n input: '',\r\n first_frame: '首帧',\r\n last_frame: '尾帧',\r\n audio_track: '音轨',\r\n reference: '参考',\r\n style: '风格',\r\n mask: '蒙版',\r\n variation_of: '变体',\r\n remix_of: '再创作',\r\n alternative_of: '候选',\r\n edited_from: '编辑自',\r\n}\r\n\r\n/** CSS class suffix for one EdgeLineStyle (appended to `edgeLine` / `edgeArrow`). */\r\nfunction edgeLineClass(style: EdgeLineStyle): string {\r\n switch (style) {\r\n case 'dashed': return css.edgeLineDashed ?? ''\r\n case 'dotted': return css.edgeLineDotted ?? ''\r\n case 'bold': return css.edgeLineBold ?? ''\r\n case 'solid':\r\n default: return css.edgeLineSolid ?? ''\r\n }\r\n}\r\n\r\n/**\r\n * One smooth-curve edge: exits the source's right-center port, curves\r\n * through two control points, enters the target's left-center port.\r\n * Drawn as an SVG cubic-bezier path + two port circles + an arrowhead,\r\n * with line style + label driven by the edge's `relation`.\r\n *\r\n * Line styles per relation group:\r\n * - solid (default): input / first_frame / last_frame / audio_track\r\n * - dashed: reference / style / mask\r\n * - dotted: variation_of / remix_of / alternative_of\r\n * - bold: edited_from (ffmpeg edit chain)\r\n *\r\n * Uses the position resolver so the edge follows live drag positions\r\n * (drafts) in real time, not just the persisted snapshot.\r\n */\r\nfunction renderEdge(edge: AigcEdge, resolvePos: PosResolver): ReactNode {\r\n const srcPos = resolvePos(edge.source)\r\n const tgtPos = resolvePos(edge.target)\r\n if (srcPos === undefined || tgtPos === undefined) return null\r\n // Source port: right-center of the source card.\r\n const sx = srcPos.x + NODE_W\r\n const sy = srcPos.y + NODE_H / 2\r\n // Target port: left-center of the target card.\r\n const tx = tgtPos.x\r\n const ty = tgtPos.y + NODE_H / 2\r\n // Control-point offset: half the horizontal gap, clamped so short\r\n // gaps still bow nicely and very long gaps don't over-extend.\r\n const dx = Math.abs(tx - sx)\r\n const offset = Math.max(40, Math.min(dx * 0.5, 160))\r\n // Cubic bezier: C1 to the right of source, C2 to the left of target.\r\n const c1x = sx + offset\r\n const c1y = sy\r\n const c2x = tx - offset\r\n const c2y = ty\r\n const d = `M ${sx} ${sy} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${tx} ${ty}`\r\n // Arrowhead pointing right (into the target port).\r\n const arrow = 9\r\n const wing = arrow * 0.55\r\n const baseX = tx - arrow\r\n const ly = ty - wing\r\n const ry = ty + wing\r\n const arrowPath = `M ${tx} ${ty} L ${baseX} ${ly} L ${baseX} ${ry} Z`\r\n const style = lineStyleOf(edge.relation)\r\n const lineClass = edgeLineClass(style)\r\n const label = edge.relation !== undefined ? EDGE_RELATION_LABEL[edge.relation] : ''\r\n // Label position: midpoint of the cubic bezier curve ( De Casteljau's\r\n // algorithm at t=0.5). The label sits on a small filled chip so it\r\n // stays readable over the canvas grid.\r\n const mx = 0.125 * sx + 0.375 * c1x + 0.375 * c2x + 0.125 * tx\r\n const my = 0.125 * sy + 0.375 * c1y + 0.375 * c2y + 0.125 * ty\r\n return createElement('g', { key: `${edge.source}:${edge.target}` },\r\n createElement('path', { d, className: `${css.edgeLine} ${lineClass}`, fill: 'none' }),\r\n createElement('path', { d: arrowPath, className: `${css.edgeArrow} ${lineClass}` }),\r\n createElement('circle', { cx: sx, cy: sy, r: PORT_R, className: css.edgePort }),\r\n createElement('circle', { cx: tx, cy: ty, r: PORT_R, className: css.edgePort }),\r\n ...(label !== '' ? [\r\n createElement('rect', {\r\n key: 'label-bg',\r\n x: mx - 24, y: my - 9, width: 48, height: 18, rx: 9,\r\n className: css.edgeLabelBg,\r\n }),\r\n createElement('text', {\r\n key: 'label-text',\r\n x: mx, y: my + 4, textAnchor: 'middle',\r\n className: css.edgeLabel,\r\n }, label),\r\n ] : []),\r\n )\r\n}\r\n\r\nexport interface CanvasViewProps {\r\n store: CanvasStore\r\n t: Translate\r\n}\r\n\r\n/**\r\n * The infinite canvas view.\r\n * @param props - store + locale translate.\r\n * @returns the canvas element.\r\n */\r\nexport function CanvasView({ store, t }: CanvasViewProps): ReactNode {\r\n const state: AigcCanvasState = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\r\n const [viewport, setViewport] = useState<Viewport>({ x: 0, y: 0, scale: 1 })\r\n const [drafts, setDrafts] = useState<ReadonlyMap<string, { x: number; y: number }>>(new Map())\r\n const [selected, setSelected] = useState<AigcElement | undefined>(undefined)\r\n /**\r\n * Multi-select set for the compare view (per docs/product/04-ux-reliability.md §2).\r\n *\r\n * Holds 0-4 element uuids. Shift+click on a node toggles its uuid in\r\n * this set; click on the empty surface clears it. When the set has\r\n * 2-4 entries, the canvas header shows a \"Compare\" button that opens\r\n * the CompareView overlay.\r\n */\r\n const [multiSelected, setMultiSelected] = useState<ReadonlySet<string>>(new Set())\r\n /** Whether the CompareView overlay is currently mounted. */\r\n const [showCompare, setShowCompare] = useState(false)\r\n const [contextMenu, setContextMenu] = useState<{ x: number; y: number; uuid: string } | undefined>(undefined)\r\n const [dropTarget, setDropTarget] = useState<{ x: number; y: number } | undefined>(undefined)\r\n const [uploading, setUploading] = useState(false)\r\n const [showLog, setShowLog] = useState(false)\r\n const [statusFilter, setStatusFilter] = useState<Set<string>>(new Set(['ready']))\r\n const [sessionCost, setSessionCost] = useState<SessionCost | null>(null)\r\n const surfaceRef = useRef<HTMLElement | null>(null)\r\n\r\n // Poll session cost every 3s (lightweight; cost changes only on provider calls).\r\n useEffect(() => {\r\n if (state.sessionId === '') return\r\n let cancelled = false\r\n const poll = async (): Promise<void> => {\r\n try {\r\n const cost = await fetchSessionCost(state.sessionId)\r\n if (!cancelled) setSessionCost(cost)\r\n } catch { /* ignore — non-critical */ }\r\n }\r\n void poll()\r\n const timer = setInterval(poll, 3000)\r\n return () => { cancelled = true; clearInterval(timer) }\r\n }, [state.sessionId])\r\n\r\n // Track the previous snapshot's element uuids so we can detect when new\r\n // elements appear (model just placed something) and pan the viewport to\r\n // bring the newest one into view at \"center-left\" of the visible area.\r\n const prevUuidsRef = useRef<Set<string>>(new Set())\r\n\r\n /** Toggle one status in the filter set (checkbox handler). */\r\n const toggleStatus = (status: string): void => {\r\n setStatusFilter(prev => {\r\n const next = new Set(prev)\r\n if (next.has(status)) next.delete(status)\r\n else next.add(status)\r\n // Never allow an empty filter — fall back to 'ready'.\r\n if (next.size === 0) next.add('ready')\r\n return next\r\n })\r\n }\r\n\r\n /** Filtered elements based on the status filter checkboxes. */\r\n const filteredElements = state.elements.filter(el => {\r\n const status = el.status ?? 'ready'\r\n return statusFilter.has(status)\r\n })\r\n /** Filtered edges: only those whose source AND target are in the filtered set. */\r\n const filteredElementPaths = new Set(filteredElements.map(e => e.filePath))\r\n const filteredEdges = state.edges.filter(e =>\r\n filteredElementPaths.has(e.source) && filteredElementPaths.has(e.target),\r\n )\r\n\r\n // Pan gesture (drag on empty background).\r\n const panRef = useRef<{ pointerId: number; startX: number; startY: number; orig: Viewport } | null>(null)\r\n // Element drag gesture.\r\n const dragRef = useRef<{ pointerId: number; uuid: string; startX: number; startY: number; origX: number; origY: number } | null>(null)\r\n\r\n // Wheel: zooms around the cursor (clamped 0.2×–4×). Pan is via\r\n // dragging the background. Needs a non-passive listener.\r\n useEffect(() => {\r\n const surface = surfaceRef.current\r\n if (surface === null) return\r\n const onWheel = (event: WheelEvent): void => {\r\n event.preventDefault()\r\n const rect = surface.getBoundingClientRect()\r\n const cx = event.clientX - rect.left\r\n const cy = event.clientY - rect.top\r\n const factor = event.deltaY < 0 ? 1.12 : 1 / 1.12\r\n setViewport(prev => zoomAt(prev, cx, cy, factor))\r\n }\r\n surface.addEventListener('wheel', onWheel, { passive: false })\r\n return () => surface.removeEventListener('wheel', onWheel)\r\n }, [])\r\n\r\n // Clean up stale drafts: once the persisted snapshot confirms an\r\n // element's position matches its draft, the draft is no longer needed\r\n // (posOf will return the persisted position, which is the same). This\r\n // prevents drafts from accumulating indefinitely and ensures that a\r\n // subsequent drag of the same element starts from the right position.\r\n useEffect(() => {\r\n if (drafts.size === 0) return\r\n const lookup = elementMap(state.elements)\r\n const stale: string[] = []\r\n for (const [uuid, draftPos] of drafts) {\r\n const el = lookup.get(uuid)\r\n if (el !== undefined && el.x === draftPos.x && el.y === draftPos.y) {\r\n stale.push(uuid)\r\n }\r\n }\r\n if (stale.length > 0) {\r\n setDrafts(prev => {\r\n const next = new Map(prev)\r\n for (const uuid of stale) next.delete(uuid)\r\n return next\r\n })\r\n }\r\n }, [state, drafts])\r\n\r\n // Auto-pan to newly placed elements. When the snapshot gains an element\r\n // the model just placed it; if it isn't visible in the current viewport,\r\n // pan JUST ENOUGH to bring it into view (with a margin). Unlike the old\r\n // center-at-25%/40% approach, this keeps existing elements visible when\r\n // a vertical column grows downward — only the minimal offset is applied.\r\n useEffect(() => {\r\n if (panRef.current !== null || dragRef.current !== null) return\r\n const surface = surfaceRef.current\r\n if (surface === null) return\r\n const prev = prevUuidsRef.current\r\n let newest: AigcElement | undefined\r\n for (const el of state.elements) {\r\n if (el.uuid !== undefined && !prev.has(el.uuid)) {\r\n newest = el\r\n }\r\n }\r\n const nextUuids = new Set<string>()\r\n for (const el of state.elements) {\r\n if (el.uuid !== undefined) nextUuids.add(el.uuid)\r\n }\r\n prevUuidsRef.current = nextUuids\r\n if (newest === undefined) return\r\n const rect = surface.getBoundingClientRect()\r\n const margin = 32\r\n const screenX = newest.x * viewport.scale + viewport.x\r\n const screenY = newest.y * viewport.scale + viewport.y\r\n const elemW = NODE_W * viewport.scale\r\n const elemH = NODE_H * viewport.scale\r\n let panX = 0\r\n let panY = 0\r\n // Below visible area → pan down just enough.\r\n if (screenY + elemH > rect.height - margin) {\r\n panY = (screenY + elemH) - (rect.height - margin)\r\n }\r\n // Above visible area → pan up just enough.\r\n if (screenY < margin) {\r\n panY = screenY - margin\r\n }\r\n // Right of visible area → pan right just enough.\r\n if (screenX + elemW > rect.width - margin) {\r\n panX = (screenX + elemW) - (rect.width - margin)\r\n }\r\n // Left of visible area → pan left just enough.\r\n if (screenX < margin) {\r\n panX = screenX - margin\r\n }\r\n if (panX !== 0 || panY !== 0) {\r\n setViewport(prev => ({ ...prev, x: prev.x - panX, y: prev.y - panY }))\r\n }\r\n }, [state, viewport.scale])\r\n\r\n // Track the surface dimensions for the minimap viewport frame.\r\n const [surfaceSize, setSurfaceSize] = useState({ width: 0, height: 0 })\r\n useEffect(() => {\r\n const surface = surfaceRef.current\r\n if (surface === null) return\r\n const update = (): void => {\r\n const rect = surface.getBoundingClientRect()\r\n setSurfaceSize({ width: rect.width, height: rect.height })\r\n }\r\n update()\r\n const observer = new ResizeObserver(update)\r\n observer.observe(surface)\r\n return () => observer.disconnect()\r\n }, [])\r\n\r\n /** Zoom to a target scale, keeping the center of the viewport fixed. */\r\n const zoomToCenter = (newScale: number): void => {\r\n const surface = surfaceRef.current\r\n if (surface === null) return\r\n const rect = surface.getBoundingClientRect()\r\n const cx = rect.width / 2\r\n const cy = rect.height / 2\r\n setViewport(prev => {\r\n const s = Math.min(MAX_SCALE, Math.max(MIN_SCALE, newScale))\r\n const worldX = (cx - prev.x) / prev.scale\r\n const worldY = (cy - prev.y) / prev.scale\r\n return { scale: s, x: cx - worldX * s, y: cy - worldY * s }\r\n })\r\n }\r\n\r\n const onSurfacePointerDown = (event: ReactPointerEvent<HTMLElement>): void => {\r\n if (dragRef.current !== null) return\r\n panRef.current = {\r\n pointerId: event.pointerId,\r\n startX: event.clientX,\r\n startY: event.clientY,\r\n orig: viewport,\r\n }\r\n event.currentTarget.setPointerCapture(event.pointerId)\r\n }\r\n\r\n const onSurfacePointerMove = (event: ReactPointerEvent<HTMLElement>): void => {\r\n const pan = panRef.current\r\n if (pan !== null && pan.pointerId === event.pointerId) {\r\n setViewport({\r\n ...pan.orig,\r\n x: pan.orig.x + (event.clientX - pan.startX),\r\n y: pan.orig.y + (event.clientY - pan.startY),\r\n })\r\n return\r\n }\r\n const drag = dragRef.current\r\n if (drag !== null && drag.pointerId === event.pointerId) {\r\n setDrafts(prev => {\r\n const next = new Map(prev)\r\n next.set(drag.uuid, {\r\n x: drag.origX + (event.clientX - drag.startX) / viewport.scale,\r\n y: drag.origY + (event.clientY - drag.startY) / viewport.scale,\r\n })\r\n return next\r\n })\r\n }\r\n }\r\n\r\n const onSurfacePointerUp = (event: ReactPointerEvent<HTMLElement>): void => {\r\n const pan = panRef.current\r\n if (pan !== null && pan.pointerId === event.pointerId) {\r\n panRef.current = null\r\n return\r\n }\r\n const drag = dragRef.current\r\n if (drag !== null && drag.pointerId === event.pointerId) {\r\n dragRef.current = null\r\n const pos = drafts.get(drag.uuid)\r\n if (pos !== undefined && (pos.x !== drag.origX || pos.y !== drag.origY)) {\r\n void store.move(drag.uuid, pos.x, pos.y)\r\n // Intentionally do NOT delete the draft here. The draft keeps the\r\n // element pinned at the drop position until the WS push arrives\r\n // with the persisted snapshot. Deleting now would snap the element\r\n // back to its old position, then forward again when the push lands\r\n // — visible as a two-frame jitter. A cleanup effect below removes\r\n // the draft once the snapshot confirms the new position.\r\n }\r\n }\r\n }\r\n\r\n const onNodePointerDown = (event: ReactPointerEvent<HTMLElement>, el: AigcElement): void => {\r\n if (el.uuid === undefined) return\r\n event.stopPropagation()\r\n // Shift+click toggles the element in the multi-select set (for the\r\n // compare view). Per docs/product/04-ux-reliability.md §2. Doesn't\r\n // start a drag — the gesture is a selection toggle, not a move.\r\n if (event.shiftKey) {\r\n setMultiSelected(prev => {\r\n const next = new Set(prev)\r\n if (next.has(el.uuid!)) next.delete(el.uuid!)\r\n else if (next.size < 4) next.add(el.uuid!)\r\n return next\r\n })\r\n return\r\n }\r\n event.currentTarget.setPointerCapture(event.pointerId)\r\n dragRef.current = {\r\n pointerId: event.pointerId,\r\n uuid: el.uuid,\r\n startX: event.clientX,\r\n startY: event.clientY,\r\n origX: el.x,\r\n origY: el.y,\r\n }\r\n }\r\n\r\n // Right-click on a node → context menu with Delete.\r\n const onNodeContextMenu = (event: ReactMouseEvent<HTMLElement>, el: AigcElement): void => {\r\n if (el.uuid === undefined) return\r\n event.preventDefault()\r\n event.stopPropagation()\r\n setContextMenu({ x: event.clientX, y: event.clientY, uuid: el.uuid })\r\n }\r\n\r\n // Click anywhere → close the context menu + clear the multi-select set\r\n // (per docs/product/04-ux-reliability.md §2: clicking the empty canvas\r\n // background dismisses the selection).\r\n const onSurfaceClick = (event: ReactMouseEvent<HTMLElement>): void => {\r\n if (contextMenu !== undefined) {\r\n event.stopPropagation()\r\n setContextMenu(undefined)\r\n }\r\n if (multiSelected.size > 0) {\r\n setMultiSelected(new Set())\r\n }\r\n }\r\n\r\n // Delete the element from the context menu.\r\n const onDeleteElement = (uuid: string): void => {\r\n setContextMenu(undefined)\r\n if (selected?.uuid === uuid) setSelected(undefined)\r\n void store.deleteElement(uuid)\r\n }\r\n\r\n // ── Right-click action handlers (per docs/product/04-ux-reliability.md §1) ─\r\n\r\n /**\r\n * Resolve the element for one context-menu uuid. The menu is only\r\n * shown for elements with a uuid (see onNodeContextMenu), so this\r\n * always finds a match — but be defensive in case the WS push\r\n * removed the element between the right-click and the action.\r\n */\r\n const elementForMenu = (uuid: string): AigcElement | undefined => {\r\n return state.elements.find(e => e.uuid === uuid)\r\n }\r\n\r\n /**\r\n * Send a user-role notice to the agent (non-waking). The host's\r\n * `canvas.notify` endpoint wraps `agent.inject` so the client does\r\n * not need direct access to the agent registry. Best-effort: a\r\n * network failure is swallowed (the next WS push carries the\r\n * agent's response, which the user will see in the conversation).\r\n */\r\n const sendNotice = (uuid: string, message: string, summary: string): void => {\r\n setContextMenu(undefined)\r\n if (state.sessionId === '') return\r\n void notifyAgent(state.sessionId, message, summary).catch(() => { /* best-effort */ })\r\n }\r\n\r\n /** Replace `{filePath}` / `{kind}` / `{title}` placeholders in a notice template. */\r\n const fillTemplate = (template: string, el: AigcElement): string => {\r\n return template\r\n .replaceAll('{filePath}', el.filePath)\r\n .replaceAll('{kind}', el.kind)\r\n .replaceAll('{title}', el.title)\r\n }\r\n\r\n /** 重新生成... → ask the agent to reroll the element with aigc_reroll. */\r\n const onRegenerate = (el: AigcElement): void => {\r\n sendNotice(\r\n el.uuid ?? '',\r\n fillTemplate(t('noticeRegenerate'), el),\r\n `regenerate ${el.kind} \"${el.title}\"`,\r\n )\r\n }\r\n\r\n /**\r\n * 用作参考... → copy the filePath to the clipboard AND send a notice\r\n * to the agent. The doc also describes a relation-picker dialog\r\n * (first_frame / last_frame / style / mask / reference); for the\r\n * initial implementation we send a generic \"use as reference\"\r\n * notice and let the agent pick the relation based on context.\r\n * The clipboard copy is the user-facing half (so the user can also\r\n * paste the path into a manual prompt).\r\n */\r\n const onUseAsReference = (el: AigcElement): void => {\r\n setContextMenu(undefined)\r\n // Clipboard write is async + may reject (e.g. no focus); don't block\r\n // the agent notice on it.\r\n void navigator.clipboard?.writeText(el.filePath).catch(() => { /* best-effort */ })\r\n if (state.sessionId !== '') {\r\n void notifyAgent(\r\n state.sessionId,\r\n fillTemplate(t('noticeUseAsReference'), el),\r\n `use ${el.kind} \"${el.title}\" as reference`,\r\n ).catch(() => { /* best-effort */ })\r\n }\r\n }\r\n\r\n /** 发到对话 → send the element's filePath + kind + title to the agent. */\r\n const onSendToChat = (el: AigcElement): void => {\r\n sendNotice(\r\n el.uuid ?? '',\r\n fillTemplate(t('noticeSendToChat'), el),\r\n `use ${el.kind} \"${el.title}\" as reference`,\r\n )\r\n }\r\n\r\n /** 下载 → open the media URL in a new tab with download=1. */\r\n const onDownload = (el: AigcElement): void => {\r\n setContextMenu(undefined)\r\n if (el.uuid === undefined || (state.sessionId === '' && el.sessionId === undefined)) return\r\n const sid = el.sessionId ?? state.sessionId\r\n if (sid === '') return\r\n const url = mediaUrlOf(sid, el.uuid, true)\r\n // window.open with download=1 lets the browser handle the download\r\n // (the host sets Content-Disposition: attachment when download=1).\r\n window.open(url, '_blank', 'noopener')\r\n }\r\n\r\n /**\r\n * 提升到资产库... → call library.promote. The doc describes a\r\n * category-picker dialog; for the initial implementation we\r\n * promote with the default `final-product` category and let the\r\n * user re-tag from the asset library UI later.\r\n */\r\n const onPromoteToLibrary = (el: AigcElement): void => {\r\n setContextMenu(undefined)\r\n if (el.uuid === undefined || state.sessionId === '') return\r\n void promoteAsset(state.sessionId, el.uuid, {\r\n category: 'final-product',\r\n title: el.title,\r\n }).catch(() => { /* best-effort; surface in a future toast */ })\r\n }\r\n\r\n /**\r\n * Update an element's lifecycle status via `canvas.set_status`.\r\n * Best-effort: the WS push carries the authoritative state, so\r\n * we don't optimistically patch the local snapshot.\r\n */\r\n const onSetStatus = (uuid: string, status: ElementStatus, winner?: boolean): void => {\r\n setContextMenu(undefined)\r\n if (state.sessionId === '') return\r\n void setElementStatus(state.sessionId, uuid, status, winner).catch(() => { /* best-effort */ })\r\n }\r\n\r\n // ── Quick action toolbar handlers (per docs/product/04-ux-reliability.md §7) ─\r\n\r\n /**\r\n * + 生成 → ask the agent to generate a new asset (provider info →\r\n * http_request → canvas_place). The doc describes a t2i/t2v/tts\r\n * picker dialog; for the initial implementation we send a generic\r\n * \"please generate something\" notice and let the agent ask the\r\n * user for the specifics (prompt, kind).\r\n */\r\n const onToolbarGenerate = (): void => {\r\n if (state.sessionId === '') return\r\n void notifyAgent(\r\n state.sessionId,\r\n t('noticeGenerate'),\r\n 'user requested generation',\r\n ).catch(() => { /* best-effort */ })\r\n }\r\n\r\n /**\r\n * ✂ 编辑选中 → ask the agent to run aigc_media_edit (ffmpeg) on\r\n * the currently-selected element. Disabled when nothing is selected.\r\n */\r\n const onToolbarEditSelected = (): void => {\r\n if (state.sessionId === '' || selected === undefined) return\r\n void notifyAgent(\r\n state.sessionId,\r\n fillTemplate(t('noticeEditSelected'), selected),\r\n `edit ${selected.kind} \"${selected.title}\"`,\r\n ).catch(() => { /* best-effort */ })\r\n }\r\n\r\n /**\r\n * ▶ 运行工作流 → ask the agent to list + run a pipeline template.\r\n * (Per docs/product/02-pipeline.md; the template picker UI is a\r\n * future enhancement — for now the agent lists templates in the\r\n * conversation and the user picks one.)\r\n */\r\n const onToolbarRunWorkflow = (): void => {\r\n if (state.sessionId === '') return\r\n void notifyAgent(\r\n state.sessionId,\r\n t('noticeRunWorkflow'),\r\n 'user requested workflow run',\r\n ).catch(() => { /* best-effort */ })\r\n }\r\n\r\n /**\r\n * Build the right-click context menu items for one element uuid.\r\n * Per docs/product/04-ux-reliability.md §1: 5 action items, a\r\n * separator, 3 status items, a separator, and Delete (in the\r\n * destructive style).\r\n *\r\n * The element is resolved from the current snapshot. If it was\r\n * removed between the right-click and the menu render (race with\r\n * the WS push), every item except Delete is disabled — Delete is\r\n * kept enabled because store.deleteElement is idempotent.\r\n */\r\n const buildContextMenuItems = (uuid: string): ContextMenuItem[] => {\r\n const el = elementForMenu(uuid)\r\n const missing = el === undefined\r\n return [\r\n {\r\n label: t('menuRegenerate'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onRegenerate(el) : undefined,\r\n },\r\n {\r\n label: t('menuUseAsReference'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onUseAsReference(el) : undefined,\r\n },\r\n {\r\n label: t('menuSendToChat'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onSendToChat(el) : undefined,\r\n },\r\n {\r\n label: t('menuDownload'),\r\n // Download needs a uuid (the media route resolves uuid → file).\r\n disabled: missing || el?.uuid === undefined,\r\n onClick: el !== undefined ? () => onDownload(el) : undefined,\r\n },\r\n {\r\n label: t('menuPromoteToLibrary'),\r\n disabled: missing || el?.uuid === undefined,\r\n onClick: el !== undefined ? () => onPromoteToLibrary(el) : undefined,\r\n },\r\n { separator: true },\r\n {\r\n label: t('menuMarkWinner'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onSetStatus(uuid, 'ready', true) : undefined,\r\n },\r\n {\r\n label: t('menuMarkRejected'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onSetStatus(uuid, 'rejected') : undefined,\r\n },\r\n {\r\n label: t('menuArchive'),\r\n disabled: missing,\r\n onClick: el !== undefined ? () => onSetStatus(uuid, 'archived') : undefined,\r\n },\r\n { separator: true },\r\n {\r\n label: t('delete'),\r\n danger: true,\r\n onClick: () => onDeleteElement(uuid),\r\n },\r\n ]\r\n }\r\n\r\n // Drag-drop files onto the canvas surface.\r\n // stopPropagation() is critical: the canvas lives inside better-sidebar's\r\n // LeafView, whose onDragOver unconditionally calls preventDefault() and\r\n // shows a 5-zone layout overlay (without checking dataTransfer.types).\r\n // Without stopPropagation, file drags trigger that overlay and the drop\r\n // gets swallowed by the parent's onDrop.\r\n const onSurfaceDragOver = (event: React.DragEvent<HTMLElement>): void => {\r\n if (event.dataTransfer.types.includes('Files')) {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n event.dataTransfer.dropEffect = 'copy'\r\n const rect = surfaceRef.current?.getBoundingClientRect()\r\n if (rect !== undefined) {\r\n const sx = event.clientX - rect.left\r\n const sy = event.clientY - rect.top\r\n // Convert screen → world coords.\r\n const wx = (sx - viewport.x) / viewport.scale\r\n const wy = (sy - viewport.y) / viewport.scale\r\n setDropTarget({ x: wx, y: wy })\r\n }\r\n }\r\n }\r\n\r\n const onSurfaceDragLeave = (event: React.DragEvent<HTMLElement>): void => {\r\n // Only clear if leaving the surface itself (not a child).\r\n if (event.currentTarget === event.target) {\r\n event.stopPropagation()\r\n setDropTarget(undefined)\r\n }\r\n }\r\n\r\n const onSurfaceDrop = async (event: React.DragEvent<HTMLElement>): Promise<void> => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n setDropTarget(undefined)\r\n const files = event.dataTransfer.files\r\n if (files.length === 0) return\r\n const rect = surfaceRef.current?.getBoundingClientRect()\r\n const sx = event.clientX - (rect?.left ?? 0)\r\n const sy = event.clientY - (rect?.top ?? 0)\r\n const wx = (sx - viewport.x) / viewport.scale\r\n const wy = (sy - viewport.y) / viewport.scale\r\n setUploading(true)\r\n try {\r\n for (const file of Array.from(files)) {\r\n const buf = await file.arrayBuffer()\r\n // Convert ArrayBuffer → base64 in chunks to avoid stack overflow\r\n // (String.fromCharCode(...spread) blows the call stack for large files).\r\n const bytes = new Uint8Array(buf)\r\n let binary = ''\r\n const chunk = 0x8000\r\n for (let i = 0; i < bytes.length; i += chunk) {\r\n binary += String.fromCharCode(...bytes.subarray(i, i + chunk))\r\n }\r\n const mediaBase64 = btoa(binary)\r\n await store.uploadFile(file.name, mediaBase64, { x: wx, y: wy })\r\n }\r\n } finally {\r\n setUploading(false)\r\n }\r\n }\r\n\r\n const lookup = elementMap(state.elements)\r\n // Position resolver that checks drafts first (live drag position) then\r\n // falls back to the element's persisted position. Used by both the node\r\n // boxes and the edge renderer so connections follow dragged nodes in\r\n // real time — not only after the drag ends.\r\n const resolvePos: PosResolver = (uuid: string) => {\r\n const draft = drafts.get(uuid)\r\n if (draft !== undefined) return draft\r\n const el = lookup.get(uuid)\r\n if (el !== undefined) return { x: el.x, y: el.y }\r\n return undefined\r\n }\r\n const posOf = (el: AigcElement): { x: number; y: number } => {\r\n if (el.uuid !== undefined) {\r\n const draft = drafts.get(el.uuid)\r\n if (draft !== undefined) return draft\r\n }\r\n return { x: el.x, y: el.y }\r\n }\r\n\r\n return createElement(\r\n 'div',\r\n { className: css.canvas },\r\n createElement(\r\n 'div',\r\n { className: css.header },\r\n createElement('span', { className: css.title }, t('title')),\r\n createElement('span', { className: css.count }, `${state.elements.length} ${t('elementCount')}`),\r\n createElement('span', { className: css.count }, `${state.edges.length} ${t('edgeCount')}`),\r\n sessionCost !== null && sessionCost.total > 0\r\n ? createElement('span', { className: css.costDisplay }, `$${sessionCost.total.toFixed(2)}`)\r\n : null,\r\n createElement('span', { className: css.zoom }, `${Math.round(viewport.scale * 100)}%`),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.iconButton,\r\n onClick: () => zoomToCenter(viewport.scale * 0.8),\r\n title: t('zoomOut'),\r\n 'aria-label': t('zoomOut'),\r\n }, '−'),\r\n createElement('input', {\r\n type: 'range',\r\n className: css.zoomSlider,\r\n min: Math.round(MIN_SCALE * 100),\r\n max: Math.round(MAX_SCALE * 100),\r\n value: Math.round(viewport.scale * 100),\r\n onChange: (e: ReactChangeEvent<HTMLInputElement>) => zoomToCenter(Number(e.target.value) / 100),\r\n 'aria-label': t('zoom'),\r\n }),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.iconButton,\r\n onClick: () => zoomToCenter(viewport.scale * 1.25),\r\n title: t('zoomIn'),\r\n 'aria-label': t('zoomIn'),\r\n }, '+'),\r\n createElement(\r\n 'button',\r\n {\r\n type: 'button',\r\n className: css.iconButton,\r\n onClick: () => { void store.refresh() },\r\n title: t('refresh'),\r\n 'aria-label': t('refresh'),\r\n },\r\n '↻',\r\n ),\r\n createElement(\r\n 'button',\r\n {\r\n type: 'button',\r\n className: css.iconButton,\r\n onClick: () => setViewport({ x: 0, y: 0, scale: 1 }),\r\n title: t('resetView'),\r\n 'aria-label': t('resetView'),\r\n },\r\n '⤢',\r\n ),\r\n createElement(\r\n 'button',\r\n {\r\n type: 'button',\r\n className: `${css.iconButton} ${showLog ? css.iconButtonActive : ''}`,\r\n onClick: () => setShowLog(!showLog),\r\n title: t('logButton'),\r\n 'aria-label': t('logButton'),\r\n },\r\n '📊',\r\n ),\r\n // Status filter checkboxes (per docs/product/01-agent-autonomy.md §5).\r\n createElement('span', { className: css.statusFilter },\r\n createElement('label', { className: css.statusFilterLabel },\r\n createElement('input', {\r\n type: 'checkbox',\r\n checked: statusFilter.has('ready'),\r\n onChange: () => toggleStatus('ready'),\r\n }),\r\n t('statusReady'),\r\n ),\r\n createElement('label', { className: css.statusFilterLabel },\r\n createElement('input', {\r\n type: 'checkbox',\r\n checked: statusFilter.has('draft'),\r\n onChange: () => toggleStatus('draft'),\r\n }),\r\n t('statusDraft'),\r\n ),\r\n createElement('label', { className: css.statusFilterLabel },\r\n createElement('input', {\r\n type: 'checkbox',\r\n checked: statusFilter.has('rejected'),\r\n onChange: () => toggleStatus('rejected'),\r\n }),\r\n t('statusRejected'),\r\n ),\r\n createElement('label', { className: css.statusFilterLabel },\r\n createElement('input', {\r\n type: 'checkbox',\r\n checked: statusFilter.has('archived'),\r\n onChange: () => toggleStatus('archived'),\r\n }),\r\n t('statusArchived'),\r\n ),\r\n ),\r\n ),\r\n createElement(\r\n 'div',\r\n {\r\n className: css.surface,\r\n ref: surfaceRef,\r\n onPointerDown: onSurfacePointerDown,\r\n onPointerMove: onSurfacePointerMove,\r\n onPointerUp: onSurfacePointerUp,\r\n onPointerCancel: onSurfacePointerUp,\r\n onDoubleClick: () => setSelected(undefined),\r\n onClick: onSurfaceClick,\r\n onContextMenu: (event: ReactMouseEvent<HTMLElement>) => {\r\n // Right-click on empty background → prevent default browser menu.\r\n event.preventDefault()\r\n },\r\n onDragOver: onSurfaceDragOver,\r\n onDragLeave: onSurfaceDragLeave,\r\n onDrop: (event: React.DragEvent<HTMLElement>) => { void onSurfaceDrop(event) },\r\n },\r\n state.elements.length === 0\r\n ? createElement('div', { className: css.empty }, createElement('span', null, t('empty')), createElement('span', { className: css.emptyHint }, t('emptyHint')))\r\n : createElement(\r\n 'div',\r\n {\r\n className: css.world,\r\n style: {\r\n transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.scale})`,\r\n // Expose the current zoom to descendants so media elements\r\n // (img/video) can counter-scale: they set their CSS width to\r\n // `100% * scale` (so the browser decodes at the larger screen\r\n // resolution instead of the layout width), then transform\r\n // `scale(1/scale)` to visually shrink back to the layout box.\r\n // Without this, zooming in shows blurry media because the\r\n // browser decodes the image at the small layout size and the\r\n // world transform upscales the bitmap.\r\n ['--canvas-scale' as string]: viewport.scale,\r\n } as CSSProperties,\r\n },\r\n createElement(\r\n 'svg',\r\n {\r\n className: css.edgeLayer,\r\n 'aria-hidden': true,\r\n },\r\n ...filteredEdges.map(edge => renderEdge(edge, resolvePos)),\r\n ),\r\n ...filteredElements.map(el => {\r\n const pos = posOf(el)\r\n const selectedClass = el.uuid !== undefined && multiSelected.has(el.uuid) ? ` ${css.nodeBoxMultiSelected ?? ''}` : ''\r\n return createElement(\r\n 'div',\r\n {\r\n key: el.uuid ?? el.filePath,\r\n className: `${css.nodeBox} ${el.uuid !== undefined ? css.nodeBoxDraggable : ''}${selectedClass}`,\r\n style: { transform: `translate(${pos.x}px, ${pos.y}px)` },\r\n onPointerDown: event => onNodePointerDown(event, el),\r\n onDoubleClick: (event: ReactMouseEvent<HTMLElement>) => {\r\n event.stopPropagation()\r\n setSelected(el)\r\n },\r\n onContextMenu: event => onNodeContextMenu(event, el),\r\n },\r\n createElement(CanvasNode, { element: el, t }),\r\n )\r\n }),\r\n ),\r\n // Drop indicator: shows where the dropped file will land (world coords).\r\n dropTarget !== undefined\r\n ? createElement('div', {\r\n className: css.dropIndicator,\r\n style: {\r\n transform: `translate(${dropTarget.x * viewport.scale + viewport.x}px, ${dropTarget.y * viewport.scale + viewport.y}px) scale(${viewport.scale})`,\r\n },\r\n })\r\n : null,\r\n // Upload overlay\r\n uploading\r\n ? createElement('div', { className: css.uploadOverlay }, t('uploading'))\r\n : null,\r\n ),\r\n selected !== undefined\r\n ? createElement(DetailPanel, { element: selected, t, onClose: () => setSelected(undefined) })\r\n : null,\r\n // Request log panel (toggled by the 📊 button in the header).\r\n showLog && state.sessionId !== ''\r\n ? createElement(RequestLogPanel, {\r\n sessionId: state.sessionId,\r\n t,\r\n locateElement: (filePath: string) => {\r\n // Find the element by filePath and pan the viewport to center on it.\r\n const el = state.elements.find(e => e.filePath === filePath)\r\n if (el !== undefined) {\r\n const cx = el.x + 120 // half node width\r\n const cy = el.y + 55 // half node height\r\n setViewport({\r\n x: (surfaceRef.current?.clientWidth ?? 800) / 2 - cx * viewport.scale,\r\n y: (surfaceRef.current?.clientHeight ?? 600) / 2 - cy * viewport.scale,\r\n scale: viewport.scale,\r\n })\r\n setSelected(el)\r\n }\r\n },\r\n })\r\n : null,\r\n // Right-click context menu (per docs/product/04-ux-reliability.md §1)\r\n contextMenu !== undefined\r\n ? createElement(ContextMenu, {\r\n x: contextMenu.x,\r\n y: contextMenu.y,\r\n items: buildContextMenuItems(contextMenu.uuid),\r\n onClose: () => setContextMenu(undefined),\r\n })\r\n : null,\r\n // Quick action toolbar (left side of the canvas, per doc 04 §7).\r\n // \"+ 生成\" / \"✂ 编辑选中\" / \"▶ 运行工作流\" — all send a notice to the\r\n // agent via canvas.notify. \"编辑选中\" is disabled when nothing is\r\n // selected.\r\n state.sessionId !== ''\r\n ? createElement(\r\n 'div',\r\n { className: css.toolbar },\r\n createElement('button', {\r\n type: 'button',\r\n className: css.toolbarButton,\r\n onClick: onToolbarGenerate,\r\n title: t('toolbarGenerateTitle'),\r\n }, t('toolbarGenerate')),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.toolbarButton,\r\n onClick: onToolbarEditSelected,\r\n disabled: selected === undefined,\r\n title: selected === undefined ? t('toolbarNoSelection') : t('toolbarEditSelectedTitle'),\r\n }, t('toolbarEditSelected')),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.toolbarButton,\r\n onClick: onToolbarRunWorkflow,\r\n title: t('toolbarRunWorkflowTitle'),\r\n }, t('toolbarRunWorkflow')),\r\n )\r\n : null,\r\n // Multi-select toolbar (per docs/product/04-ux-reliability.md §2).\r\n // When 2-4 elements are in the multi-select set, show a small floating\r\n // bar above the canvas with the count + a \"Compare\" button + a\r\n // \"Clear\" button. Clicking \"Compare\" opens the CompareView overlay.\r\n multiSelected.size >= 2\r\n ? createElement(\r\n 'div',\r\n { className: css.multiSelectBar },\r\n createElement('span', { className: css.multiSelectCount }, t('compareNSelected').replace('{n}', String(multiSelected.size))),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.multiSelectCompareButton,\r\n onClick: () => setShowCompare(true),\r\n disabled: multiSelected.size < 2 || multiSelected.size > 4,\r\n title: multiSelected.size > 4 ? t('compareTooMany') : t('compareButton'),\r\n }, t('compareButton')),\r\n createElement('button', {\r\n type: 'button',\r\n className: css.multiSelectClearButton,\r\n onClick: () => setMultiSelected(new Set()),\r\n }, t('compareClearSelection')),\r\n )\r\n : null,\r\n // CompareView overlay (per docs/product/04-ux-reliability.md §2).\r\n // Mounted only when showCompare is true AND the multi-select still\r\n // holds 2-4 elements (in case the WS push removed one between opening\r\n // the overlay and rendering — we re-resolve the elements from the\r\n // latest snapshot here).\r\n showCompare && state.sessionId !== ''\r\n ? createElement(CompareView, {\r\n sessionId: state.sessionId,\r\n elements: state.elements.filter(e => e.uuid !== undefined && multiSelected.has(e.uuid)),\r\n t,\r\n onClose: () => setShowCompare(false),\r\n })\r\n : null,\r\n // Minimap: bottom-right overview showing element outlines + viewport frame.\r\n state.elements.length > 0\r\n ? createElement(Minimap, {\r\n elements: state.elements,\r\n viewport,\r\n surfaceSize,\r\n setViewport,\r\n })\r\n : null,\r\n )\r\n}\r\n\r\n/** One entry in the right-click context menu. */\r\ninterface ContextMenuItem {\r\n /** Visible label (omitted for separator entries). */\r\n label?: string\r\n /** Click handler. Called only when `disabled` is false. */\r\n onClick?: () => void\r\n /** Render as a non-clickable horizontal rule. */\r\n separator?: boolean\r\n /** Greyed out + non-clickable. */\r\n disabled?: boolean\r\n /** Use the destructive (red) hover style — for Delete. */\r\n danger?: boolean\r\n}\r\n\r\n/** A minimal fixed-position context menu (right-click). */\r\nfunction ContextMenu(props: {\r\n x: number\r\n y: number\r\n items: readonly ContextMenuItem[]\r\n onClose: () => void\r\n}): ReactNode {\r\n // Close on any outside click or Escape.\r\n useEffect(() => {\r\n const onDown = (): void => props.onClose()\r\n const onKey = (e: KeyboardEvent): void => { if (e.key === 'Escape') props.onClose() }\r\n window.addEventListener('pointerdown', onDown, { once: true })\r\n window.addEventListener('keydown', onKey, { once: true })\r\n return () => {\r\n window.removeEventListener('pointerdown', onDown)\r\n window.removeEventListener('keydown', onKey)\r\n }\r\n }, [props])\r\n // Clamp the menu to the viewport so a right-click near the right/bottom\r\n // edge doesn't push it off-screen.\r\n const style: CSSProperties = { left: props.x, top: props.y }\r\n return createElement(\r\n 'div',\r\n {\r\n className: css.contextMenu,\r\n style,\r\n // Stop the outside-click handler from firing on the menu itself.\r\n onPointerDown: (e: ReactPointerEvent<HTMLElement>) => e.stopPropagation(),\r\n },\r\n ...props.items.map((item, i) => {\r\n if (item.separator === true) {\r\n return createElement('hr', { key: `sep-${i}`, className: css.contextMenuSeparator })\r\n }\r\n const className = [\r\n css.contextMenuItem,\r\n item.danger === true ? css.contextMenuItemDanger ?? '' : '',\r\n item.disabled === true ? css.contextMenuItemDisabled ?? '' : '',\r\n ].filter(s => s !== '').join(' ')\r\n return createElement('button', {\r\n key: i,\r\n type: 'button',\r\n className,\r\n disabled: item.disabled === true,\r\n onClick: () => { if (item.disabled !== true) item.onClick?.() },\r\n }, item.label)\r\n }),\r\n )\r\n}\r\n\r\n/** The double-click detail panel: prompt + generation params + path. */\r\nfunction DetailPanel({ element, t, onClose }: { element: AigcElement; t: Translate; onClose: () => void }): ReactNode {\r\n // Defensive: meta may have been persisted as a string by an older build\r\n // or sneak through the schema as a non-object. Only render entries when\r\n // we have a real plain object; otherwise show the raw value (if primitive)\r\n // or skip the section entirely.\r\n const meta = element.meta\r\n const metaEntries: Array<[string, unknown]> = Array.isArray(meta) || meta === null || typeof meta !== 'object'\r\n ? []\r\n : Object.entries(meta as Record<string, unknown>)\r\n return createElement(\r\n 'div',\r\n { className: css.detailPanel },\r\n createElement(\r\n 'div',\r\n { className: css.detailHeader },\r\n createElement('span', { className: css.detailTitle }, element.title),\r\n createElement('button', { type: 'button', className: css.detailClose, onClick: onClose, 'aria-label': t('detailClose') }, '×'),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.detailBody },\r\n element.promptText !== undefined\r\n ? createElement(\r\n 'div',\r\n { className: css.detailBlock },\r\n createElement('span', { className: css.detailLabel }, t('detailPrompt')),\r\n createElement('pre', { className: css.detailPrompt }, element.promptText),\r\n )\r\n : null,\r\n metaEntries.length > 0\r\n ? createElement(\r\n 'div',\r\n { className: css.detailBlock },\r\n createElement('span', { className: css.detailLabel }, t('detailParams')),\r\n createElement(\r\n 'dl',\r\n { className: css.metaList },\r\n ...metaEntries.flatMap(([k, v]) => [\r\n createElement('dt', { key: `${k}-k`, className: css.metaKey }, k),\r\n createElement('dd', { key: `${k}-v`, className: css.metaValue }, formatMetaValue(v)),\r\n ]),\r\n ),\r\n )\r\n : null,\r\n createElement(\r\n 'div',\r\n { className: css.detailBlock },\r\n createElement('span', { className: css.detailLabel }, t('generatedBy')),\r\n createElement('span', { className: css.detailValue }, element.producedBy),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.detailBlock },\r\n createElement('span', { className: css.detailLabel }, t('detailPosition')),\r\n createElement('span', { className: css.detailValue }, `(${Math.round(element.x)}, ${Math.round(element.y)})`),\r\n ),\r\n createElement(\r\n 'div',\r\n { className: css.detailBlock },\r\n createElement('span', { className: css.detailLabel }, t('detailPath')),\r\n createElement('code', { className: css.filePath }, element.filePath),\r\n ),\r\n ),\r\n )\r\n}\r\n\r\nfunction formatMetaValue(v: unknown): string {\r\n if (typeof v === 'string') return v\r\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\r\n if (v === null || v === undefined) return ''\r\n try { return JSON.stringify(v) } catch { return String(v) }\r\n}\r\n\r\n// ── Minimap ──────────────────────────────────────────────────────────────\r\n\r\nconst MINIMAP_W = 168\r\nconst MINIMAP_H = 120\r\nconst MINIMAP_PAD = 6\r\n\r\n/** Color dot per element kind in the minimap. */\r\nconst KIND_COLOR: Record<AigcElement['kind'], string> = {\r\n image: '#4caf50',\r\n video: '#ff9800',\r\n audio: '#ab47bc',\r\n prompt: '#6b8cff',\r\n}\r\n\r\n/**\r\n * Bottom-right minimap: shows all elements as small colored rectangles and\r\n * the current viewport as a frame. Click/drag to pan the viewport.\r\n */\r\nfunction Minimap(props: {\r\n elements: readonly AigcElement[]\r\n viewport: Viewport\r\n surfaceSize: { width: number; height: number }\r\n setViewport: (fn: (prev: Viewport) => Viewport) => void\r\n}): ReactNode {\r\n const { elements, viewport, surfaceSize, setViewport } = props\r\n const minimapRef = useRef<HTMLDivElement | null>(null)\r\n\r\n // Compute world bounding box: union of all elements + the current viewport.\r\n let minX = Infinity\r\n let minY = Infinity\r\n let maxX = -Infinity\r\n let maxY = -Infinity\r\n for (const el of elements) {\r\n minX = Math.min(minX, el.x)\r\n minY = Math.min(minY, el.y)\r\n maxX = Math.max(maxX, el.x + NODE_W)\r\n maxY = Math.max(maxY, el.y + NODE_H)\r\n }\r\n if (surfaceSize.width > 0 && surfaceSize.height > 0) {\r\n const vpMinX = -viewport.x / viewport.scale\r\n const vpMinY = -viewport.y / viewport.scale\r\n const vpMaxX = vpMinX + surfaceSize.width / viewport.scale\r\n const vpMaxY = vpMinY + surfaceSize.height / viewport.scale\r\n minX = Math.min(minX, vpMinX)\r\n minY = Math.min(minY, vpMinY)\r\n maxX = Math.max(maxX, vpMaxX)\r\n maxY = Math.max(maxY, vpMaxY)\r\n }\r\n // Guard against empty (shouldn't happen — caller checks, but be safe).\r\n if (!Number.isFinite(minX) || !Number.isFinite(maxX)) return null\r\n // Add a small padding around the content.\r\n minX -= 40\r\n minY -= 40\r\n maxX += 40\r\n maxY += 40\r\n const worldW = maxX - minX\r\n const worldH = maxY - minY\r\n const miniScale = Math.min(\r\n (MINIMAP_W - MINIMAP_PAD * 2) / worldW,\r\n (MINIMAP_H - MINIMAP_PAD * 2) / worldH,\r\n )\r\n const offsetX = (MINIMAP_W - worldW * miniScale) / 2\r\n const offsetY = (MINIMAP_H - worldH * miniScale) / 2\r\n const toMiniX = (wx: number): number => offsetX + (wx - minX) * miniScale\r\n const toMiniY = (wy: number): number => offsetY + (wy - minY) * miniScale\r\n\r\n // Viewport frame in minimap coords.\r\n const vpX = toMiniX(-viewport.x / viewport.scale)\r\n const vpY = toMiniY(-viewport.y / viewport.scale)\r\n const vpW = (surfaceSize.width / viewport.scale) * miniScale\r\n const vpH = (surfaceSize.height / viewport.scale) * miniScale\r\n\r\n // Click/drag on minimap → center the viewport on the clicked world point.\r\n const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>): void => {\r\n event.stopPropagation()\r\n event.currentTarget.setPointerCapture(event.pointerId)\r\n const pan = (clientX: number, clientY: number): void => {\r\n const rect = minimapRef.current?.getBoundingClientRect()\r\n if (rect === undefined) return\r\n const mx = clientX - rect.left\r\n const my = clientY - rect.top\r\n // Convert minimap coords → world coords.\r\n const worldX = (mx - offsetX) / miniScale + minX\r\n const worldY = (my - offsetY) / miniScale + minY\r\n // Center viewport on this world point.\r\n setViewport(prev => ({\r\n ...prev,\r\n x: surfaceSize.width / 2 - worldX * prev.scale,\r\n y: surfaceSize.height / 2 - worldY * prev.scale,\r\n }))\r\n }\r\n pan(event.clientX, event.clientY)\r\n const onMove = (e: PointerEvent): void => pan(e.clientX, e.clientY)\r\n const onUp = (): void => {\r\n window.removeEventListener('pointermove', onMove)\r\n window.removeEventListener('pointerup', onUp)\r\n }\r\n window.addEventListener('pointermove', onMove)\r\n window.addEventListener('pointerup', onUp)\r\n }\r\n\r\n return createElement(\r\n 'div',\r\n {\r\n className: css.minimap,\r\n ref: minimapRef,\r\n onPointerDown,\r\n },\r\n createElement(\r\n 'svg',\r\n { width: MINIMAP_W, height: MINIMAP_H, className: css.minimapSvg },\r\n // Element rectangles.\r\n ...elements.map(el =>\r\n createElement('rect', {\r\n key: el.uuid ?? el.filePath,\r\n x: toMiniX(el.x),\r\n y: toMiniY(el.y),\r\n width: Math.max(2, NODE_W * miniScale),\r\n height: Math.max(2, NODE_H * miniScale),\r\n rx: 2,\r\n fill: KIND_COLOR[el.kind],\r\n fillOpacity: 0.35,\r\n stroke: KIND_COLOR[el.kind],\r\n strokeOpacity: 0.7,\r\n strokeWidth: 1,\r\n }),\r\n ),\r\n // Viewport frame: a semi-transparent fill + solid border so it's\r\n // clearly visible against the element rectangles.\r\n createElement('rect', {\r\n x: vpX,\r\n y: vpY,\r\n width: vpW,\r\n height: vpH,\r\n fill: 'var(--dsw-alias-label-primary)',\r\n fillOpacity: 0.08,\r\n stroke: 'var(--dsw-alias-label-primary)',\r\n strokeOpacity: 0.8,\r\n strokeWidth: 2,\r\n rx: 2,\r\n }),\r\n ),\r\n )\r\n}\r\n\r\n/** Wrapped export so the tab component can mount the boundary once. */\r\nexport function CanvasViewWithBoundary(props: CanvasViewProps): ReactNode {\r\n return createElement(CanvasBoundary, { t: props.t, children: createElement(CanvasView, props) })\r\n}\r\n","/**\r\n * SettingsPage — the AIGC canvas settings section: provider list CRUD.\r\n *\r\n * Visual language: matches ModelsSection / GeneralSection / yet-another-subagent —\r\n * outlined rowCard per provider (border-l2, r12, p12/14), filled editor surface\r\n * (bg-module-platform, r12, p14/16), capsule controls (h36 r18 primary,\r\n * h28 r14 secondary), 32px fields with border-l2 / bg-layer-1, 12/18 caption\r\n * labels. Every color resolves through --dsw-alias-* tokens.\r\n *\r\n * Each provider card is collapsible (chevron in the row head); the editor\r\n * surface is hidden when collapsed. Builtin providers (cordis.yml seed) carry\r\n * a `builtin`/`内置` badge next to the title. The \"+ Add provider\" button at\r\n * the bottom reveals an inline draft card with all fields editable (including\r\n * id) and Create / Cancel actions.\r\n *\r\n * Real providers carry an \"initialize\" (初始化) action: it sends a prepared\r\n * message to the current conversation so the agent probes the API with\r\n * aigc_http_request and records the usage instructions via\r\n * aigc_provider_set_instructions. The editor also exposes the auth scheme\r\n * (bearer / custom header / query param) the aigc_http_request tool uses to\r\n * attach the apiKey.\r\n *\r\n * @module @huanlin/dsh-plugin-aigc-canvas/client/SettingsPage\r\n */\r\n\r\nimport { useCallback, useEffect, useState } from 'react'\r\nimport { Modal, Pill } from '@deepseek-ai/dsh-client-ui-primitives'\r\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type { PropsLocale } from '@deepseek-ai/dsh-client-ui-slots'\r\nimport {\r\n addProvider,\r\n fetchConfig,\r\n removeProvider,\r\n updateProvider,\r\n RUNTIME_CAPABILITIES,\r\n RUNTIME_HTTP_METHODS,\r\n RUNTIME_PARAM_TYPES,\r\n RUNTIME_QUALITY_HINTS,\r\n RUNTIME_RESPONSE_KINDS,\r\n type RuntimeCapability,\r\n type RuntimeEndpointSpec,\r\n type RuntimeHttpMethod,\r\n type RuntimeParamSpec,\r\n type RuntimeProvider,\r\n type RuntimeQualityHint,\r\n type RuntimeResponseKind,\r\n} from './api.js'\r\nimport css from './SettingsPage.module.css'\r\n\r\n/** Inject face: locale translate + conversation send (for the init + auto-detect actions). */\r\nexport interface AigcSettingsInjected {\r\n readonly t: (key: string) => string\r\n /** Send a prompt into the current conversation scope (queued turn). */\r\n readonly send: (text: string) => Promise<void>\r\n}\r\n\r\n/** Full props: settings.section runtime share + locale seat + inject. */\r\ntype SettingsPageProps = PropsRuntime<'settings.section'> & PropsLocale<'dsh-aigc-canvas'> & AigcSettingsInjected\r\n\r\n/**\r\n * Default shape for a brand-new draft (before the user fills in id/name).\r\n * The structured-catalog fields default to sane values so the endpoints\r\n * editor starts empty (the agent's \"Initialize\" / \"Auto-detect\" buttons\r\n * populate it after probing the API).\r\n */\r\nfunction emptyDraft(): RuntimeProvider {\r\n return {\r\n id: '',\r\n name: '',\r\n endpoint: 'stub://aigc-backend',\r\n apiKey: '',\r\n instructions: '',\r\n auth: { scheme: 'bearer', name: '' },\r\n builtin: false,\r\n endpoints: [],\r\n priority: 100,\r\n costPerCall: 0,\r\n costPerKiloToken: 0,\r\n costPerSecond: 0,\r\n avgLatencyMs: 0,\r\n qualityHint: 'balanced',\r\n }\r\n}\r\n\r\n/** Build a fresh blank endpoint (for the \"+ Add endpoint\" button). */\r\nfunction emptyEndpoint(): RuntimeEndpointSpec {\r\n return {\r\n path: '',\r\n method: 'POST',\r\n capability: 't2i',\r\n params: [],\r\n response: { kind: 'json_text', path: '' },\r\n acceptsCanvasRef: false,\r\n notes: '',\r\n }\r\n}\r\n\r\n/** Build a fresh blank parameter (for the \"+ Add parameter\" button). */\r\nfunction emptyParam(): RuntimeParamSpec {\r\n return { name: '', type: 'string', required: false, default: '', description: '' }\r\n}\r\n\r\n/** Coerce a possibly-undefined value to a number (default 0 when invalid). */\r\nfunction toNumber(v: unknown, fallback = 0): number {\r\n if (typeof v === 'number' && Number.isFinite(v)) return v\r\n if (typeof v === 'string') {\r\n const n = Number(v)\r\n if (Number.isFinite(n) && v.trim() !== '') return n\r\n }\r\n return fallback\r\n}\r\n\r\n/** Coerce a possibly-undefined value to a string (default ''). */\r\nfunction toStr(v: unknown): string {\r\n if (typeof v === 'string') return v\r\n if (typeof v === 'number' || typeof v === 'boolean') return String(v)\r\n return ''\r\n}\r\n\r\n/**\r\n * Render the AIGC provider settings page.\r\n * @param props - settings.section runtime share + locale + inject.\r\n * @returns the page element.\r\n */\r\nexport function SettingsPage({ t, send }: SettingsPageProps) {\r\n const [providers, setProviders] = useState<readonly RuntimeProvider[]>([])\r\n const [drafts, setDrafts] = useState<readonly RuntimeProvider[]>([])\r\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(new Set())\r\n const [addingNew, setAddingNew] = useState(false)\r\n const [newDraft, setNewDraft] = useState<RuntimeProvider>(emptyDraft())\r\n const [loading, setLoading] = useState(true)\r\n const [error, setError] = useState<string | undefined>(undefined)\r\n const [confirmDelete, setConfirmDelete] = useState<string | undefined>(undefined)\r\n\r\n const refresh = useCallback(async () => {\r\n setLoading(true)\r\n setError(undefined)\r\n try {\r\n const result = await fetchConfig()\r\n setProviders(result.providers)\r\n setDrafts(result.providers.map(p => ({ ...p, auth: { ...p.auth } })))\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n } finally {\r\n setLoading(false)\r\n }\r\n }, [])\r\n\r\n useEffect(() => { void refresh() }, [refresh])\r\n\r\n const add = useCallback(async () => {\r\n if (newDraft.id === '') return\r\n try {\r\n const result = await addProvider(newDraft)\r\n setProviders(result.providers)\r\n setDrafts(result.providers.map(p => ({ ...p, auth: { ...p.auth } })))\r\n setExpanded(new Set([...expanded, newDraft.id]))\r\n setAddingNew(false)\r\n setNewDraft(emptyDraft())\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n }\r\n }, [expanded, newDraft])\r\n\r\n const update = useCallback(async (draft: RuntimeProvider) => {\r\n try {\r\n const result = await updateProvider(draft)\r\n setProviders(result.providers)\r\n setDrafts(result.providers.map(p => ({ ...p, auth: { ...p.auth } })))\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n }\r\n }, [])\r\n\r\n const remove = useCallback(async (id: string) => {\r\n try {\r\n const result = await removeProvider(id)\r\n setProviders(result.providers)\r\n setDrafts(result.providers.map(p => ({ ...p, auth: { ...p.auth } })))\r\n const next = new Set(expanded)\r\n next.delete(id)\r\n setExpanded(next)\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n }\r\n }, [expanded])\r\n\r\n const init = useCallback(async (provider: RuntimeProvider) => {\r\n const label = provider.name === '' ? provider.id : provider.name\r\n const text = t('row.initPrompt').replace('{name}', label).replace('{id}', provider.id)\r\n try {\r\n await send(text)\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n }\r\n }, [send, t])\r\n\r\n /**\r\n * Auto-detect (per docs/product/03-provider-catalog.md §5): send a\r\n * prepared message into the current conversation asking the agent to\r\n * call `aigc_probe_endpoint` for each endpoint whose response.kind is\r\n * not yet set, then save the detected shapes via\r\n * `aigc_provider_set_endpoints`. The agent handles the actual probing\r\n * + persistence; the client just sends the prompt (same pattern as\r\n * the \"Initialize\" action).\r\n */\r\n const autoDetect = useCallback(async (provider: RuntimeProvider) => {\r\n const label = provider.name === '' ? provider.id : provider.name\r\n const text = t('row.autoDetectPrompt').replace('{name}', label).replace('{id}', provider.id)\r\n try {\r\n await send(text)\r\n } catch (err) {\r\n setError(err instanceof Error ? err.message : String(err))\r\n }\r\n }, [send, t])\r\n\r\n const patchDraft = (id: string, patch: Partial<RuntimeProvider>): void => {\r\n setDrafts(prev => prev.map(d => (d.id === id ? { ...d, ...patch } : d)))\r\n }\r\n\r\n const toggleExpand = (id: string): void => {\r\n const next = new Set(expanded)\r\n if (next.has(id)) next.delete(id)\r\n else next.add(id)\r\n setExpanded(next)\r\n }\r\n\r\n const cancelNew = (): void => {\r\n setAddingNew(false)\r\n setNewDraft(emptyDraft())\r\n }\r\n\r\n const defaultId = providers.length > 0 ? providers[0]?.id : undefined\r\n\r\n return (\r\n <section className={css.section}>\r\n <h2 className={css.title}>{t('settingsTitle')}</h2>\r\n <p className={css.intro}>{t('settingsIntro')}</p>\r\n {error !== undefined && (\r\n <div className={css.error}>\r\n {error}\r\n <button type=\"button\" className={css.errorDismiss} onClick={() => setError(undefined)}>×</button>\r\n </div>\r\n )}\r\n {loading ? (\r\n <div className={css.loading}>{t('settingsLoading')}</div>\r\n ) : providers.length === 0 && !addingNew ? (\r\n <p className={css.empty}>{t('settingsEmpty')}</p>\r\n ) : (\r\n <ul className={css.rows}>\r\n {drafts.map(draft => (\r\n <ProviderCard\r\n key={draft.id}\r\n draft={draft}\r\n expanded={expanded.has(draft.id)}\r\n isDefault={draft.id === defaultId}\r\n t={t}\r\n onToggle={() => toggleExpand(draft.id)}\r\n onPatch={patch => patchDraft(draft.id, patch)}\r\n onSave={() => void update(draft)}\r\n onDelete={() => setConfirmDelete(draft.id)}\r\n onInit={() => void init(draft)}\r\n onAutoDetect={() => void autoDetect(draft)}\r\n />\r\n ))}\r\n {addingNew && (\r\n <ProviderCard\r\n key=\"__new__\"\r\n draft={newDraft}\r\n expanded={true}\r\n isNew={true}\r\n isDefault={false}\r\n t={t}\r\n onPatch={patch => setNewDraft(prev => ({ ...prev, ...patch }))}\r\n onCreate={() => void add()}\r\n onCancel={cancelNew}\r\n />\r\n )}\r\n </ul>\r\n )}\r\n {!loading && !addingNew && (\r\n <button type=\"button\" className={css.addBlockButton} onClick={() => setAddingNew(true)}>\r\n {t('settingsAdd')}\r\n </button>\r\n )}\r\n <Modal\r\n open={confirmDelete !== undefined}\r\n onClose={() => { setConfirmDelete(undefined) }}\r\n title={t('row.deleteConfirm')}\r\n footer={(\r\n <>\r\n <button type=\"button\" className={css.secondaryButton} onClick={() => { setConfirmDelete(undefined) }}>\r\n {t('row.cancel')}\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={css.dangerButton}\r\n onClick={() => {\r\n if (confirmDelete !== undefined) void remove(confirmDelete)\r\n setConfirmDelete(undefined)\r\n }}\r\n >\r\n {t('row.delete')}\r\n </button>\r\n </>\r\n )}\r\n >\r\n <p className={css.confirmText}>{t('row.deleteConfirm')}</p>\r\n </Modal>\r\n </section>\r\n )\r\n}\r\n\r\n// ─── ProviderCard ─────────────────────────────────────────────────────────────\r\n\r\ninterface ProviderCardProps {\r\n readonly draft: RuntimeProvider\r\n readonly expanded: boolean\r\n readonly isNew?: boolean\r\n readonly isDefault: boolean\r\n readonly t: (key: string) => string\r\n readonly onToggle?: () => void\r\n readonly onPatch: (patch: Partial<RuntimeProvider>) => void\r\n readonly onSave?: () => void\r\n readonly onDelete?: () => void\r\n readonly onCreate?: () => void\r\n readonly onCancel?: () => void\r\n readonly onInit?: () => void\r\n readonly onAutoDetect?: () => void\r\n}\r\n\r\nfunction ProviderCard({ draft, expanded, isNew, isDefault, t, onToggle, onPatch, onSave, onDelete, onCreate, onCancel, onInit, onAutoDetect }: ProviderCardProps) {\r\n const isStub = draft.endpoint === '' || draft.endpoint === 'stub://aigc-backend'\r\n const patchAuth = (patch: Partial<{ scheme: 'bearer' | 'header' | 'query'; name: string }>): void => {\r\n onPatch({ auth: { ...draft.auth, ...patch } })\r\n }\r\n /**\r\n * Patch one endpoint in the draft's endpoints array (by index).\r\n * Replaces the whole array so React sees a new reference and re-renders.\r\n */\r\n const patchEndpoint = (index: number, patch: Partial<RuntimeEndpointSpec>): void => {\r\n const next = [...(draft.endpoints ?? [])]\r\n const existing = next[index]\r\n if (existing === undefined) return\r\n next[index] = { ...existing, ...patch }\r\n onPatch({ endpoints: next })\r\n }\r\n /** Append a fresh blank endpoint to the endpoints array. */\r\n const addEndpoint = (): void => {\r\n const next = [...(draft.endpoints ?? []), emptyEndpoint()]\r\n onPatch({ endpoints: next })\r\n }\r\n /** Remove the endpoint at one index. */\r\n const removeEndpoint = (index: number): void => {\r\n const next = [...(draft.endpoints ?? [])]\r\n next.splice(index, 1)\r\n onPatch({ endpoints: next })\r\n }\r\n /**\r\n * Patch one parameter on one endpoint (by endpoint index + param index).\r\n */\r\n const patchParam = (epIndex: number, paramIndex: number, patch: Partial<RuntimeParamSpec>): void => {\r\n const ep = (draft.endpoints ?? [])[epIndex]\r\n if (ep === undefined) return\r\n const params = [...(ep.params ?? [])]\r\n const existing = params[paramIndex]\r\n if (existing === undefined) return\r\n params[paramIndex] = { ...existing, ...patch }\r\n patchEndpoint(epIndex, { params })\r\n }\r\n /** Append a fresh blank parameter to one endpoint. */\r\n const addParam = (epIndex: number): void => {\r\n const ep = (draft.endpoints ?? [])[epIndex]\r\n if (ep === undefined) return\r\n const params = [...(ep.params ?? []), emptyParam()]\r\n patchEndpoint(epIndex, { params })\r\n }\r\n /** Remove the parameter at one index on one endpoint. */\r\n const removeParam = (epIndex: number, paramIndex: number): void => {\r\n const ep = (draft.endpoints ?? [])[epIndex]\r\n if (ep === undefined) return\r\n const params = [...(ep.params ?? [])]\r\n params.splice(paramIndex, 1)\r\n patchEndpoint(epIndex, { params })\r\n }\r\n return (\r\n <li className={css.rowCard}>\r\n <div className={css.rowHead}>\r\n {!isNew && onToggle !== undefined && (\r\n <button type=\"button\" className={css.chevronButton} onClick={onToggle} aria-label={expanded ? t('row.collapse') : t('row.expand')}>\r\n <span className={expanded ? `${css.chevron} ${css.chevronExpanded}` : css.chevron} aria-hidden=\"true\" />\r\n </button>\r\n )}\r\n {isNew && <span className={css.chevronSpacer} aria-hidden=\"true\" />}\r\n <div className={css.rowIdentity}>\r\n {isNew ? (\r\n <span className={css.rowNamePlaceholder}>{t('settingsAdd')}</span>\r\n ) : (\r\n <span className={css.rowName}>{draft.name === '' ? draft.id : draft.name}</span>\r\n )}\r\n {draft.builtin && <Pill className={css.builtinBadge}>{t('badge.builtin')}</Pill>}\r\n {isDefault && !isNew && <Pill className={css.defaultBadge}>{t('badge.default')}</Pill>}\r\n <Pill className={isStub ? css.stubBadge : css.realBadge}>\r\n {isStub ? t('badge.stub') : t('badge.real')}\r\n </Pill>\r\n {!isNew && <code className={css.rowId}>{draft.id}</code>}\r\n </div>\r\n <div className={css.rowActions}>\r\n {isNew ? (\r\n <>\r\n <button type=\"button\" className={css.primaryButton} onClick={onCreate} disabled={draft.id === ''}>\r\n {t('row.create')}\r\n </button>\r\n <button type=\"button\" className={css.secondaryButton} onClick={onCancel}>\r\n {t('row.cancel')}\r\n </button>\r\n </>\r\n ) : (\r\n <>\r\n {!isStub && onInit !== undefined && (\r\n <button type=\"button\" className={css.secondaryButton} onClick={onInit}>\r\n {t('row.init')}\r\n </button>\r\n )}\r\n {!isStub && onAutoDetect !== undefined && (\r\n <button type=\"button\" className={css.secondaryButton} onClick={onAutoDetect} title={t('row.autoDetectTitle')}>\r\n {t('row.autoDetect')}\r\n </button>\r\n )}\r\n <button type=\"button\" className={css.secondaryButton} onClick={onSave}>\r\n {t('row.save')}\r\n </button>\r\n <button type=\"button\" className={css.dangerButton} onClick={onDelete}>\r\n {t('row.delete')}\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n {expanded && (\r\n <div className={css.editor}>\r\n {isNew && (\r\n <>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.id')}</span>\r\n <input\r\n className={css.input}\r\n value={draft.id}\r\n placeholder={t('row.idPlaceholder')}\r\n onChange={e => onPatch({ id: e.target.value })}\r\n />\r\n <span className={css.hint}>{t('row.idHint')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.name')}</span>\r\n <input\r\n className={css.input}\r\n value={draft.name}\r\n placeholder={t('row.namePlaceholder')}\r\n onChange={e => onPatch({ name: e.target.value })}\r\n />\r\n </label>\r\n </>\r\n )}\r\n {!isNew && (\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.name')}</span>\r\n <input\r\n className={css.input}\r\n value={draft.name}\r\n placeholder={t('row.namePlaceholder')}\r\n onChange={e => onPatch({ name: e.target.value })}\r\n />\r\n </label>\r\n )}\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpoint')}</span>\r\n <input\r\n className={css.input}\r\n value={draft.endpoint}\r\n placeholder={t('row.endpointPlaceholder')}\r\n onChange={e => onPatch({ endpoint: e.target.value })}\r\n />\r\n <span className={css.desc}>{t('row.endpointDesc')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.apiKey')}</span>\r\n <input\r\n className={css.input}\r\n type=\"password\"\r\n autoComplete=\"off\"\r\n value={draft.apiKey}\r\n placeholder={t('row.apiKeyPlaceholder')}\r\n onChange={e => onPatch({ apiKey: e.target.value })}\r\n />\r\n <span className={css.desc}>{t('row.apiKeyDesc')}</span>\r\n </label>\r\n <div className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.auth')}</span>\r\n <div className={css.authRow}>\r\n <select\r\n className={css.select}\r\n value={draft.auth.scheme}\r\n onChange={e => patchAuth({ scheme: e.target.value as 'bearer' | 'header' | 'query' })}\r\n >\r\n <option value=\"bearer\">{t('row.authBearer')}</option>\r\n <option value=\"header\">{t('row.authHeader')}</option>\r\n <option value=\"query\">{t('row.authQuery')}</option>\r\n </select>\r\n {draft.auth.scheme !== 'bearer' && (\r\n <input\r\n className={css.input}\r\n value={draft.auth.name}\r\n placeholder={draft.auth.scheme === 'header' ? 'x-api-key' : 'api_key'}\r\n onChange={e => patchAuth({ name: e.target.value })}\r\n />\r\n )}\r\n </div>\r\n <span className={css.desc}>{t('row.authDesc')}</span>\r\n </div>\r\n {/* ── Selection policy fields (per docs/product/03-provider-catalog.md §4) ─ */}\r\n <div className={css.fieldRow}>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.priority')}</span>\r\n <input\r\n className={css.input}\r\n type=\"number\"\r\n min={0}\r\n step={1}\r\n value={toNumber(draft.priority, 100)}\r\n onChange={e => onPatch({ priority: toNumber(e.target.value, 100) })}\r\n />\r\n <span className={css.desc}>{t('row.priorityDesc')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.qualityHint')}</span>\r\n <select\r\n className={css.select}\r\n value={draft.qualityHint ?? 'balanced'}\r\n onChange={e => onPatch({ qualityHint: e.target.value as RuntimeQualityHint })}\r\n >\r\n {RUNTIME_QUALITY_HINTS.map(q => (\r\n <option key={q} value={q}>{q}</option>\r\n ))}\r\n </select>\r\n <span className={css.desc}>{t('row.qualityHintDesc')}</span>\r\n </label>\r\n </div>\r\n <div className={css.fieldRow}>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.costPerCall')}</span>\r\n <input\r\n className={css.input}\r\n type=\"number\"\r\n min={0}\r\n step={0.0001}\r\n value={toNumber(draft.costPerCall, 0)}\r\n onChange={e => onPatch({ costPerCall: toNumber(e.target.value, 0) })}\r\n />\r\n <span className={css.desc}>{t('row.costPerCallDesc')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.costPerKiloToken')}</span>\r\n <input\r\n className={css.input}\r\n type=\"number\"\r\n min={0}\r\n step={0.0001}\r\n value={toNumber(draft.costPerKiloToken, 0)}\r\n onChange={e => onPatch({ costPerKiloToken: toNumber(e.target.value, 0) })}\r\n />\r\n <span className={css.desc}>{t('row.costPerKiloTokenDesc')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.costPerSecond')}</span>\r\n <input\r\n className={css.input}\r\n type=\"number\"\r\n min={0}\r\n step={0.0001}\r\n value={toNumber(draft.costPerSecond, 0)}\r\n onChange={e => onPatch({ costPerSecond: toNumber(e.target.value, 0) })}\r\n />\r\n <span className={css.desc}>{t('row.costPerSecondDesc')}</span>\r\n </label>\r\n </div>\r\n {/* ── Endpoints catalog editor (per docs/product/03-provider-catalog.md §5) ─ */}\r\n <div className={css.field}>\r\n <div className={css.fieldLabelRow}>\r\n <span className={css.fieldLabel}>{t('row.endpoints')}</span>\r\n {!isStub && onAutoDetect !== undefined && (\r\n <button type=\"button\" className={css.endpointsAutoDetectButton} onClick={onAutoDetect} title={t('row.autoDetectTitle')}>\r\n {t('row.autoDetect')}\r\n </button>\r\n )}\r\n </div>\r\n <span className={css.desc}>{t('row.endpointsDesc')}</span>\r\n {(draft.endpoints ?? []).length === 0 ? (\r\n <div className={css.endpointsEmpty}>{t('row.endpointsEmpty')}</div>\r\n ) : (\r\n <div className={css.endpointsList}>\r\n {(draft.endpoints ?? []).map((ep, epIndex) => (\r\n <EndpointCard\r\n key={epIndex}\r\n endpoint={ep}\r\n t={t}\r\n onPatch={(patch) => patchEndpoint(epIndex, patch)}\r\n onRemove={() => removeEndpoint(epIndex)}\r\n onAddParam={() => addParam(epIndex)}\r\n onPatchParam={(paramIndex, patch) => patchParam(epIndex, paramIndex, patch)}\r\n onRemoveParam={(paramIndex) => removeParam(epIndex, paramIndex)}\r\n />\r\n ))}\r\n </div>\r\n )}\r\n <button type=\"button\" className={css.addEndpointButton} onClick={addEndpoint}>\r\n {t('row.addEndpoint')}\r\n </button>\r\n </div>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.instructions')}</span>\r\n <textarea\r\n className={css.textarea}\r\n value={draft.instructions}\r\n placeholder={t('row.instructionsPlaceholder')}\r\n rows={8}\r\n onChange={e => onPatch({ instructions: e.target.value })}\r\n />\r\n <span className={css.desc}>{t('row.instructionsDesc')}</span>\r\n <span className={css.hint}>{t('row.instructionsHint')}</span>\r\n </label>\r\n </div>\r\n )}\r\n </li>\r\n )\r\n}\r\n\r\n// ─── EndpointCard ─────────────────────────────────────────────────────────────\r\n\r\ninterface EndpointCardProps {\r\n readonly endpoint: RuntimeEndpointSpec\r\n readonly t: (key: string) => string\r\n readonly onPatch: (patch: Partial<RuntimeEndpointSpec>) => void\r\n readonly onRemove: () => void\r\n readonly onAddParam: () => void\r\n readonly onPatchParam: (paramIndex: number, patch: Partial<RuntimeParamSpec>) => void\r\n readonly onRemoveParam: (paramIndex: number) => void\r\n}\r\n\r\n/**\r\n * One endpoint in the catalog editor: path / method / capability /\r\n * response.kind / response.path + acceptsCanvasRef + notes + parameter\r\n * list. Per docs/product/03-provider-catalog.md §5.\r\n *\r\n * No collapsible state — the card is always expanded so the user can\r\n * see all fields. The parameter list is a simple grid (name / type /\r\n * required / default) with add/remove buttons.\r\n */\r\nfunction EndpointCard({ endpoint, t, onPatch, onRemove, onAddParam, onPatchParam, onRemoveParam }: EndpointCardProps) {\r\n const response = endpoint.response ?? { kind: 'json_text' as RuntimeResponseKind, path: '' }\r\n return (\r\n <div className={css.endpointCard}>\r\n <div className={css.endpointHead}>\r\n <span className={css.endpointHeadLabel}>\r\n {endpoint.method} {endpoint.path === '' ? '<path>' : endpoint.path}\r\n {endpoint.capability !== undefined && (\r\n <Pill className={css.endpointCapabilityBadge}>{endpoint.capability}</Pill>\r\n )}\r\n </span>\r\n <button type=\"button\" className={css.endpointRemoveButton} onClick={onRemove} aria-label={t('row.removeEndpoint')}>\r\n ×\r\n </button>\r\n </div>\r\n <div className={css.fieldRow}>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointPath')}</span>\r\n <input\r\n className={css.input}\r\n value={endpoint.path}\r\n placeholder=\"/v1/images/generations\"\r\n onChange={e => onPatch({ path: e.target.value })}\r\n />\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointMethod')}</span>\r\n <select\r\n className={css.select}\r\n value={endpoint.method}\r\n onChange={e => onPatch({ method: e.target.value as RuntimeHttpMethod })}\r\n >\r\n {RUNTIME_HTTP_METHODS.map(m => (\r\n <option key={m} value={m}>{m}</option>\r\n ))}\r\n </select>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointCapability')}</span>\r\n <select\r\n className={css.select}\r\n value={endpoint.capability}\r\n onChange={e => onPatch({ capability: e.target.value as RuntimeCapability })}\r\n >\r\n {RUNTIME_CAPABILITIES.map(c => (\r\n <option key={c} value={c}>{c}</option>\r\n ))}\r\n </select>\r\n </label>\r\n </div>\r\n <div className={css.fieldRow}>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointResponseKind')}</span>\r\n <select\r\n className={css.select}\r\n value={response.kind}\r\n onChange={e => onPatch({ response: { kind: e.target.value as RuntimeResponseKind, path: response.path } })}\r\n >\r\n {RUNTIME_RESPONSE_KINDS.map(k => (\r\n <option key={k} value={k}>{k}</option>\r\n ))}\r\n </select>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointResponsePath')}</span>\r\n <input\r\n className={css.input}\r\n value={toStr(response.path)}\r\n placeholder=\"data[0].b64_json\"\r\n onChange={e => onPatch({ response: { kind: response.kind, path: e.target.value } })}\r\n />\r\n </label>\r\n </div>\r\n <label className={css.fieldRow}>\r\n <input\r\n type=\"checkbox\"\r\n checked={endpoint.acceptsCanvasRef === true}\r\n onChange={e => onPatch({ acceptsCanvasRef: e.target.checked })}\r\n />\r\n <span className={css.desc}>{t('row.endpointAcceptsCanvasRef')}</span>\r\n </label>\r\n <label className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointNotes')}</span>\r\n <input\r\n className={css.input}\r\n value={toStr(endpoint.notes)}\r\n placeholder=\"size must be 1024x1024 or 1792x1024\"\r\n onChange={e => onPatch({ notes: e.target.value })}\r\n />\r\n </label>\r\n <div className={css.field}>\r\n <span className={css.fieldLabel}>{t('row.endpointParams')}</span>\r\n {(endpoint.params ?? []).length === 0 ? (\r\n <div className={css.endpointsEmpty}>{t('row.endpointParamsEmpty')}</div>\r\n ) : (\r\n <div className={css.paramsTable}>\r\n {(endpoint.params ?? []).map((param, paramIndex) => (\r\n <div key={paramIndex} className={css.paramRow}>\r\n <input\r\n className={css.input}\r\n value={param.name}\r\n placeholder={t('row.endpointParamName')}\r\n onChange={e => onPatchParam(paramIndex, { name: e.target.value })}\r\n />\r\n <select\r\n className={css.select}\r\n value={param.type}\r\n onChange={e => onPatchParam(paramIndex, { type: e.target.value as RuntimeParamSpec['type'] })}\r\n >\r\n {RUNTIME_PARAM_TYPES.map(tp => (\r\n <option key={tp} value={tp}>{tp}</option>\r\n ))}\r\n </select>\r\n <label className={css.paramRequired}>\r\n <input\r\n type=\"checkbox\"\r\n checked={param.required}\r\n onChange={e => onPatchParam(paramIndex, { required: e.target.checked })}\r\n />\r\n <span>{t('row.endpointParamRequired')}</span>\r\n </label>\r\n <input\r\n className={css.input}\r\n value={toStr(param.default)}\r\n placeholder={t('row.endpointParamDefault')}\r\n onChange={e => onPatchParam(paramIndex, { default: e.target.value })}\r\n />\r\n <button type=\"button\" className={css.paramRemoveButton} onClick={() => onRemoveParam(paramIndex)} aria-label={t('row.endpointRemoveParam')}>\r\n ×\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n <button type=\"button\" className={css.addEndpointButton} onClick={onAddParam}>\r\n {t('row.endpointAddParam')}\r\n </button>\r\n </div>\r\n </div>\r\n )\r\n}\r\n","/**\r\n * i18n dictionaries for the AIGC canvas plugin.\r\n *\r\n * @module @huanlin/dsh-plugin-aigc-canvas/client/locales\r\n */\r\n\r\nexport const NS = 'dsh-aigc-canvas' as const\r\n\r\nexport type AigcKey =\r\n // Canvas view\r\n | 'tabTitle'\r\n | 'title'\r\n | 'empty'\r\n | 'emptyHint'\r\n | 'prompt'\r\n | 'image'\r\n | 'video'\r\n | 'audio'\r\n | 'meta'\r\n | 'generatedBy'\r\n | 'edgeCount'\r\n | 'elementCount'\r\n | 'loadError'\r\n | 'disconnected'\r\n | 'reconnecting'\r\n | 'refresh'\r\n | 'resetView'\r\n | 'zoom'\r\n | 'zoomIn'\r\n | 'zoomOut'\r\n | 'detailClose'\r\n | 'detailPrompt'\r\n | 'detailParams'\r\n | 'detailPosition'\r\n | 'detailPath'\r\n | 'delete'\r\n | 'deleteElement'\r\n | 'dropHint'\r\n | 'uploading'\r\n // Right-click context menu items (per docs/product/04-ux-reliability.md §1)\r\n | 'menuRegenerate'\r\n | 'menuUseAsReference'\r\n | 'menuSendToChat'\r\n | 'menuDownload'\r\n | 'menuPromoteToLibrary'\r\n | 'menuMarkWinner'\r\n | 'menuMarkRejected'\r\n | 'menuArchive'\r\n | 'menuSeparator'\r\n // Quick action toolbar (per docs/product/04-ux-reliability.md §7)\r\n | 'toolbarGenerate'\r\n | 'toolbarEditSelected'\r\n | 'toolbarRunWorkflow'\r\n | 'toolbarGenerateTitle'\r\n | 'toolbarEditSelectedTitle'\r\n | 'toolbarRunWorkflowTitle'\r\n | 'toolbarNoSelection'\r\n // Status update notices (sent to the agent via canvas.notify)\r\n | 'noticeRegenerate'\r\n | 'noticeUseAsReference'\r\n | 'noticeSendToChat'\r\n | 'noticeGenerate'\r\n | 'noticeEditSelected'\r\n | 'noticeRunWorkflow'\r\n // Settings — page chrome\r\n | 'settingsNav'\r\n | 'settingsTitle'\r\n | 'settingsIntro'\r\n | 'settingsEmpty'\r\n | 'settingsAdd'\r\n | 'settingsLoading'\r\n | 'settingsError'\r\n // Settings — provider card\r\n | 'row.id'\r\n | 'row.name'\r\n | 'row.endpoint'\r\n | 'row.apiKey'\r\n | 'row.instructions'\r\n | 'row.idPlaceholder'\r\n | 'row.namePlaceholder'\r\n | 'row.endpointPlaceholder'\r\n | 'row.apiKeyPlaceholder'\r\n | 'row.instructionsPlaceholder'\r\n | 'row.idHint'\r\n | 'row.endpointDesc'\r\n | 'row.apiKeyDesc'\r\n | 'row.instructionsDesc'\r\n | 'row.instructionsHint'\r\n | 'row.save'\r\n | 'row.delete'\r\n | 'row.deleteConfirm'\r\n | 'row.expand'\r\n | 'row.collapse'\r\n | 'row.create'\r\n | 'row.cancel'\r\n | 'row.init'\r\n | 'row.initPrompt'\r\n | 'row.auth'\r\n | 'row.authBearer'\r\n | 'row.authHeader'\r\n | 'row.authQuery'\r\n | 'row.authDesc'\r\n | 'badge.builtin'\r\n | 'badge.stub'\r\n | 'badge.real'\r\n | 'badge.default'\r\n // Request log panel\r\n | 'logButton'\r\n | 'logTitle'\r\n | 'logClear'\r\n | 'logEmpty'\r\n | 'logLoading'\r\n | 'logError'\r\n | 'logRequestBody'\r\n | 'logRequestHeaders'\r\n | 'logResponseBody'\r\n | 'logProducedFile'\r\n | 'logLocate'\r\n // Element lifecycle (per docs/product/01-agent-autonomy.md §5)\r\n | 'winner'\r\n | 'statusFilter'\r\n | 'statusReady'\r\n | 'statusDraft'\r\n | 'statusRejected'\r\n | 'statusArchived'\r\n // Compare view (per docs/product/04-ux-reliability.md §2)\r\n | 'compareButton'\r\n | 'compareTitle'\r\n | 'compareClose'\r\n | 'compareSelectWinner'\r\n | 'compareRejectAll'\r\n | 'compareCancelSelection'\r\n | 'compareSeed'\r\n | 'compareCost'\r\n | 'compareDuration'\r\n | 'comparePrompt'\r\n | 'compareNoMedia'\r\n | 'compareNotEnough'\r\n | 'compareTooMany'\r\n | 'compareClearSelection'\r\n | 'compareNSelected'\r\n // Provider settings — endpoint catalog editor (per docs/product/03-provider-catalog.md §5)\r\n | 'row.priority'\r\n | 'row.qualityHint'\r\n | 'row.costPerCall'\r\n | 'row.costPerKiloToken'\r\n | 'row.costPerSecond'\r\n | 'row.priorityDesc'\r\n | 'row.qualityHintDesc'\r\n | 'row.costPerCallDesc'\r\n | 'row.costPerKiloTokenDesc'\r\n | 'row.costPerSecondDesc'\r\n | 'row.endpoints'\r\n | 'row.endpointsDesc'\r\n | 'row.endpointsEmpty'\r\n | 'row.addEndpoint'\r\n | 'row.editEndpoint'\r\n | 'row.removeEndpoint'\r\n | 'row.endpointPath'\r\n | 'row.endpointMethod'\r\n | 'row.endpointCapability'\r\n | 'row.endpointResponseKind'\r\n | 'row.endpointResponsePath'\r\n | 'row.endpointAcceptsCanvasRef'\r\n | 'row.endpointNotes'\r\n | 'row.endpointParams'\r\n | 'row.endpointParamsEmpty'\r\n | 'row.endpointParamName'\r\n | 'row.endpointParamType'\r\n | 'row.endpointParamRequired'\r\n | 'row.endpointParamDefault'\r\n | 'row.endpointAddParam'\r\n | 'row.endpointRemoveParam'\r\n | 'row.endpointCancel'\r\n | 'row.endpointSave'\r\n | 'row.autoDetect'\r\n | 'row.autoDetectTitle'\r\n | 'row.autoDetectPrompt'\r\n\r\nexport const zh: Record<AigcKey, string> = {\r\n tabTitle: 'AIGC 画布',\r\n title: 'AIGC 画布',\r\n empty: '画布是空的。模型通过 aigc_http_request 调用供应商 API 生成素材,再用 aigc_canvas_place 把文件放到画布的任意位置。',\r\n emptyHint: '可在右侧设置页配置供应商,然后让模型开始生成。',\r\n prompt: '提示词',\r\n image: '图片',\r\n video: '视频',\r\n audio: '音频',\r\n meta: '元信息',\r\n generatedBy: '生成方式',\r\n edgeCount: '条连线',\r\n elementCount: '个元素',\r\n loadError: '加载画布失败',\r\n disconnected: '已断开,正在重连…',\r\n reconnecting: '正在重连…',\r\n refresh: '刷新',\r\n resetView: '重置视图',\r\n zoom: '缩放',\r\n zoomIn: '放大',\r\n zoomOut: '缩小',\r\n detailClose: '关闭',\r\n detailPrompt: '提示词',\r\n detailParams: '生成参数',\r\n detailPosition: '位置',\r\n detailPath: '文件路径',\r\n delete: '删除',\r\n deleteElement: '删除元素',\r\n dropHint: '拖放文件到画布',\r\n uploading: '上传中…',\r\n menuRegenerate: '重新生成...',\r\n menuUseAsReference: '用作参考...',\r\n menuSendToChat: '发到对话',\r\n menuDownload: '下载',\r\n menuPromoteToLibrary: '提升到资产库...',\r\n menuMarkWinner: '标记为 winner',\r\n menuMarkRejected: '标记为否决',\r\n menuArchive: '归档',\r\n menuSeparator: '─────────────',\r\n toolbarGenerate: '+ 生成',\r\n toolbarEditSelected: '✂ 编辑选中',\r\n toolbarRunWorkflow: '▶ 运行工作流',\r\n toolbarGenerateTitle: '打开快速生成弹窗(t2i/t2v/tts)',\r\n toolbarEditSelectedTitle: '对选中元素执行 ffmpeg 操作',\r\n toolbarRunWorkflowTitle: '打开 pipeline 模板选择器',\r\n toolbarNoSelection: '请先在画布上选中一个元素',\r\n noticeRegenerate: '请用 aigc_reroll 重新生成元素 {filePath}',\r\n noticeUseAsReference: '请把以下元素用作后续生成的参考: {filePath}',\r\n noticeSendToChat: '请使用这个元素作为参考: [filePath: {filePath}, kind: {kind}, title: {title}]',\r\n noticeGenerate: '请帮我生成一个新的 AIGC 素材(先调用 aigc_get_provider_info 查看可用供应商,再调用 aigc_http_request 发起生成,最后用 aigc_canvas_place 把产物放到画布上)。',\r\n noticeEditSelected: '请用 aigc_media_edit(ffmpeg)对选中元素进行编辑: {filePath}(kind: {kind}, title: {title})',\r\n noticeRunWorkflow: '请列出可用的 pipeline 模板并运行其中一个(如果只有一个模板就直接运行它)。',\r\n settingsNav: 'AIGC 画布',\r\n settingsTitle: 'AIGC 供应商',\r\n settingsIntro: '配置一个或多个 AIGC 供应商。每个供应商可独立设置名称、API 地址、密钥、鉴权方式和调用说明。模型通过 aigc_get_provider_info 读取供应商列表,用 aigc_http_request 调用 API(自动携带 endpoint 和 apiKey),生成的文件用 aigc_canvas_place 放到画布上。',\r\n settingsEmpty: '暂无供应商,请在下方添加。',\r\n settingsAdd: '+ 添加供应商',\r\n settingsLoading: '加载中…',\r\n settingsError: '错误',\r\n 'row.id': 'ID',\r\n 'row.name': '名称',\r\n 'row.endpoint': 'API 地址',\r\n 'row.apiKey': 'API Key',\r\n 'row.instructions': '调用说明',\r\n 'row.idPlaceholder': 'volcano / jimeng / minimax',\r\n 'row.namePlaceholder': '显示名(如\"火山引擎\")',\r\n 'row.endpointPlaceholder': 'stub://aigc-backend',\r\n 'row.apiKeyPlaceholder': 'sk-...',\r\n 'row.instructionsPlaceholder': '调用说明由 Agent 初始化供应商时自动撰写(点击卡片上的\"初始化\"按钮)...',\r\n 'row.idHint': '小写字母、数字、连字符;必须以字母开头。作为 provider_id 传给 aigc_http_request',\r\n 'row.endpointDesc': '供应商 API 地址。填 stub://aigc-backend 使用内置 stub(合成测试媒体,不调真实 API)',\r\n 'row.apiKeyDesc': '供应商 API 密钥。stub 后端不需要。模型看不到密钥,由 aigc_http_request 自动附加',\r\n 'row.instructionsDesc': 'Agent 通过 aigc_get_provider_info 工具读取此字段,决定如何调用该供应商的 API',\r\n 'row.instructionsHint': '💡 点击卡片上的\"初始化\"按钮,Agent 会用 aigc_http_request 探测 API 并自动撰写调用说明',\r\n 'row.save': '保存',\r\n 'row.delete': '删除',\r\n 'row.deleteConfirm': '确定删除此供应商?',\r\n 'row.expand': '展开',\r\n 'row.collapse': '收起',\r\n 'row.create': '创建',\r\n 'row.cancel': '取消',\r\n 'row.init': '初始化',\r\n 'row.initPrompt': '请帮我初始化 AIGC 供应商「{name}」(id: {id}):先用 aigc_get_provider_info 查看配置,再用 aigc_http_request 探测它的 API(apiKey 会自动附加,无需手动传入),最后调用 aigc_provider_set_instructions 把调用说明保存下来,方便以后直接使用。',\r\n 'row.auth': '鉴权方式',\r\n 'row.authBearer': 'Bearer 头',\r\n 'row.authHeader': '自定义 Header',\r\n 'row.authQuery': 'URL 参数',\r\n 'row.authDesc': 'aigc_http_request 自动附加 apiKey 的方式。默认 Authorization: Bearer <key>;选择自定义 Header 或 URL 参数时需填写名称',\r\n 'badge.builtin': '内置',\r\n 'badge.stub': 'stub 模式',\r\n 'badge.real': '真实 API',\r\n 'badge.default': '默认',\r\n logButton: '日志',\r\n logTitle: '请求日志',\r\n logClear: '清空',\r\n logEmpty: '暂无请求记录。',\r\n logLoading: '加载中…',\r\n logError: '错误',\r\n logRequestBody: '请求体',\r\n logRequestHeaders: '请求头',\r\n logResponseBody: '响应预览',\r\n logProducedFile: '产物文件',\r\n logLocate: '在画布上定位',\r\n winner: '优胜',\r\n statusFilter: '状态',\r\n statusReady: '就绪',\r\n statusDraft: '草稿',\r\n statusRejected: '否决',\r\n statusArchived: '归档',\r\n compareButton: '对比',\r\n compareTitle: '对比视图',\r\n compareClose: '关闭',\r\n compareSelectWinner: '选为 winner',\r\n compareRejectAll: '全部否决',\r\n compareCancelSelection: '取消选择',\r\n compareSeed: 'seed',\r\n compareCost: '成本',\r\n compareDuration: '耗时',\r\n comparePrompt: '提示词',\r\n compareNoMedia: '该元素无可显示的媒体',\r\n compareNotEnough: '请选择 2-4 个元素进行对比',\r\n compareTooMany: '最多只能同时对比 4 个元素',\r\n compareClearSelection: '清除选择',\r\n compareNSelected: '已选 {n} 个',\r\n 'row.priority': '优先级',\r\n 'row.qualityHint': '质量',\r\n 'row.costPerCall': '单次成本 ($)',\r\n 'row.costPerKiloToken': '千 token 成本 ($)',\r\n 'row.costPerSecond': '每秒成本 ($)',\r\n 'row.priorityDesc': '数字越小优先级越高(默认 100)。多 provider 同 capability 时按此排序',\r\n 'row.qualityHintDesc': 'fast / balanced / quality,供 Agent 选择快速或高质量 provider',\r\n 'row.costPerCallDesc': '单次调用成本(美元),用于成本追踪',\r\n 'row.costPerKiloTokenDesc': '按 token 计费时(chat / transcribe)的千 token 成本',\r\n 'row.costPerSecondDesc': '按秒计费时(t2v / tts)的每秒成本',\r\n 'row.endpoints': 'Endpoints',\r\n 'row.endpointsDesc': '结构化能力表。Agent 通过 aigc_get_provider_info 读取,无需解析自然语言',\r\n 'row.endpointsEmpty': '暂无 endpoint。点击下方\"自动探测\"或\"+ 添加 endpoint\"',\r\n 'row.addEndpoint': '+ 添加 endpoint',\r\n 'row.editEndpoint': '编辑 endpoint',\r\n 'row.removeEndpoint': '删除',\r\n 'row.endpointPath': 'Path',\r\n 'row.endpointMethod': 'Method',\r\n 'row.endpointCapability': 'Capability',\r\n 'row.endpointResponseKind': '响应类型',\r\n 'row.endpointResponsePath': '响应字段路径',\r\n 'row.endpointAcceptsCanvasRef': '支持 $base64 占位符',\r\n 'row.endpointNotes': '备注',\r\n 'row.endpointParams': '参数',\r\n 'row.endpointParamsEmpty': '暂无参数',\r\n 'row.endpointParamName': '名称',\r\n 'row.endpointParamType': '类型',\r\n 'row.endpointParamRequired': '必填',\r\n 'row.endpointParamDefault': '默认值',\r\n 'row.endpointAddParam': '+ 添加参数',\r\n 'row.endpointRemoveParam': '删除参数',\r\n 'row.endpointCancel': '取消',\r\n 'row.endpointSave': '保存',\r\n 'row.autoDetect': '自动探测',\r\n 'row.autoDetectTitle': '让 Agent 用 aigc_probe_endpoint 自动探测响应格式',\r\n 'row.autoDetectPrompt': '请帮我自动探测 AIGC 供应商「{name}」(id: {id}) 的 endpoint 响应格式:对每个未配置响应类型的 endpoint 调用 aigc_probe_endpoint(会发送一次最小测试请求,apiKey 自动附加),把探测到的 response.kind + response.path 通过 aigc_provider_set_endpoints 保存到 EndpointSpec。如果该 provider 还没有任何 endpoint,请先用 aigc_http_request 探测常见的 endpoint(如 /v1/images/generations、/v1/videos/generations、/v1/audio/speech),再用 aigc_probe_endpoint 探测响应格式。',\r\n}\r\n\r\nexport const en: Record<AigcKey, string> = {\r\n tabTitle: 'AIGC Canvas',\r\n title: 'AIGC Canvas',\r\n empty: 'Canvas is empty. The agent calls provider APIs via aigc_http_request and places the generated files anywhere on the canvas with aigc_canvas_place.',\r\n emptyHint: 'Configure a provider in the settings tab on the right, then ask the agent to generate something.',\r\n prompt: 'Prompt',\r\n image: 'Image',\r\n video: 'Video',\r\n audio: 'Audio',\r\n meta: 'Metadata',\r\n generatedBy: 'Generated by',\r\n edgeCount: 'edges',\r\n elementCount: 'elements',\r\n loadError: 'Failed to load canvas',\r\n disconnected: 'Disconnected, reconnecting…',\r\n reconnecting: 'Reconnecting…',\r\n refresh: 'Refresh',\r\n resetView: 'Reset view',\r\n zoom: 'Zoom',\r\n zoomIn: 'Zoom in',\r\n zoomOut: 'Zoom out',\r\n detailClose: 'Close',\r\n detailPrompt: 'Prompt',\r\n detailParams: 'Generation params',\r\n detailPosition: 'Position',\r\n detailPath: 'File path',\r\n delete: 'Delete',\r\n deleteElement: 'Delete element',\r\n dropHint: 'Drop files onto canvas',\r\n uploading: 'Uploading…',\r\n menuRegenerate: 'Regenerate...',\r\n menuUseAsReference: 'Use as reference...',\r\n menuSendToChat: 'Send to chat',\r\n menuDownload: 'Download',\r\n menuPromoteToLibrary: 'Promote to library...',\r\n menuMarkWinner: 'Mark as winner',\r\n menuMarkRejected: 'Mark as rejected',\r\n menuArchive: 'Archive',\r\n menuSeparator: '─────────────',\r\n toolbarGenerate: '+ Generate',\r\n toolbarEditSelected: '✂ Edit selected',\r\n toolbarRunWorkflow: '▶ Run workflow',\r\n toolbarGenerateTitle: 'Open the quick-generate dialog (t2i/t2v/tts)',\r\n toolbarEditSelectedTitle: 'Run an ffmpeg operation on the selected element',\r\n toolbarRunWorkflowTitle: 'Open the pipeline template picker',\r\n toolbarNoSelection: 'Select an element on the canvas first',\r\n noticeRegenerate: 'Please regenerate the element {filePath} using aigc_reroll',\r\n noticeUseAsReference: 'Please use the following element as a reference for the next generation: {filePath}',\r\n noticeSendToChat: 'Please use this element as a reference: [filePath: {filePath}, kind: {kind}, title: {title}]',\r\n noticeGenerate: 'Please generate a new AIGC asset (call aigc_get_provider_info to list available providers, then aigc_http_request to generate, and finally aigc_canvas_place to put the result on the canvas).',\r\n noticeEditSelected: 'Please edit the selected element with aigc_media_edit (ffmpeg): {filePath} (kind: {kind}, title: {title})',\r\n noticeRunWorkflow: 'Please list the available pipeline templates and run one (if there is only one, run it directly).',\r\n settingsNav: 'AIGC Canvas',\r\n settingsTitle: 'AIGC Providers',\r\n settingsIntro: 'Configure one or more AIGC providers. Each provider has its own name, API endpoint, key, auth scheme, and usage instructions. The agent reads the provider list via aigc_get_provider_info, calls the API via aigc_http_request (endpoint + apiKey attached automatically), and places generated files onto the canvas with aigc_canvas_place.',\r\n settingsEmpty: 'No providers configured. Add one below.',\r\n settingsAdd: '+ Add provider',\r\n settingsLoading: 'Loading…',\r\n settingsError: 'Error',\r\n 'row.id': 'ID',\r\n 'row.name': 'Name',\r\n 'row.endpoint': 'Endpoint',\r\n 'row.apiKey': 'API Key',\r\n 'row.instructions': 'Instructions',\r\n 'row.idPlaceholder': 'volcano / jimeng / minimax',\r\n 'row.namePlaceholder': 'Display name (e.g. \"Volcano Engine\")',\r\n 'row.endpointPlaceholder': 'stub://aigc-backend',\r\n 'row.apiKeyPlaceholder': 'sk-...',\r\n 'row.instructionsPlaceholder': 'The agent writes these when you initialize the provider (click \"Initialize\" on the card)...',\r\n 'row.idHint': 'Lowercase letters, digits, hyphens; must start with a letter. Used as the provider_id parameter to aigc_http_request',\r\n 'row.endpointDesc': 'Provider API URL. Use stub://aigc-backend for the built-in stub (synthetic test media, no real API calls)',\r\n 'row.apiKeyDesc': 'Provider API key. Not needed for the stub backend. The agent never sees it — aigc_http_request attaches it automatically',\r\n 'row.instructionsDesc': 'The agent reads this field via the aigc_get_provider_info tool to decide how to call the provider API',\r\n 'row.instructionsHint': '💡 Click \"Initialize\" on the card: the agent probes the API with aigc_http_request and writes the instructions itself',\r\n 'row.save': 'Save',\r\n 'row.delete': 'Delete',\r\n 'row.deleteConfirm': 'Delete this provider?',\r\n 'row.expand': 'Expand',\r\n 'row.collapse': 'Collapse',\r\n 'row.create': 'Create',\r\n 'row.cancel': 'Cancel',\r\n 'row.init': 'Initialize',\r\n 'row.initPrompt': 'Please initialize the AIGC provider \"{name}\" (id: {id}): first call aigc_get_provider_info to see its config, then probe its API with aigc_http_request (the apiKey is attached automatically — do not pass it yourself), and finally call aigc_provider_set_instructions to save the usage instructions so it can be used directly later.',\r\n 'row.auth': 'Auth scheme',\r\n 'row.authBearer': 'Bearer header',\r\n 'row.authHeader': 'Custom header',\r\n 'row.authQuery': 'URL query param',\r\n 'row.authDesc': 'How aigc_http_request attaches the apiKey. Default: Authorization: Bearer <key>. For custom header or URL query param, fill in the name',\r\n 'badge.builtin': 'builtin',\r\n 'badge.stub': 'stub mode',\r\n 'badge.real': 'real API',\r\n 'badge.default': 'default',\r\n logButton: 'Logs',\r\n logTitle: 'Request Log',\r\n logClear: 'Clear',\r\n logEmpty: 'No requests logged yet.',\r\n logLoading: 'Loading…',\r\n logError: 'Error',\r\n logRequestBody: 'Request body',\r\n logRequestHeaders: 'Request headers',\r\n logResponseBody: 'Response preview',\r\n logProducedFile: 'Produced file',\r\n logLocate: 'Locate on canvas',\r\n winner: 'Winner',\r\n statusFilter: 'Status',\r\n statusReady: 'Ready',\r\n statusDraft: 'Draft',\r\n statusRejected: 'Rejected',\r\n statusArchived: 'Archived',\r\n compareButton: 'Compare',\r\n compareTitle: 'Compare view',\r\n compareClose: 'Close',\r\n compareSelectWinner: 'Select as winner',\r\n compareRejectAll: 'Reject all',\r\n compareCancelSelection: 'Cancel selection',\r\n compareSeed: 'seed',\r\n compareCost: 'cost',\r\n compareDuration: 'duration',\r\n comparePrompt: 'Prompt',\r\n compareNoMedia: 'No media to display for this element',\r\n compareNotEnough: 'Select 2-4 elements to compare',\r\n compareTooMany: 'You can compare at most 4 elements at once',\r\n compareClearSelection: 'Clear selection',\r\n compareNSelected: '{n} selected',\r\n 'row.priority': 'Priority',\r\n 'row.qualityHint': 'Quality',\r\n 'row.costPerCall': 'Cost per call ($)',\r\n 'row.costPerKiloToken': 'Cost per 1k tokens ($)',\r\n 'row.costPerSecond': 'Cost per second ($)',\r\n 'row.priorityDesc': 'Smaller = higher priority (default 100). When multiple providers serve the same capability, they are sorted by this',\r\n 'row.qualityHintDesc': 'fast / balanced / quality — lets the agent pick fast vs. quality providers',\r\n 'row.costPerCallDesc': 'Cost per call in USD (for cost tracking)',\r\n 'row.costPerKiloTokenDesc': 'Per-1k-token cost in USD (for chat / transcribe cost tracking)',\r\n 'row.costPerSecondDesc': 'Per-second cost in USD (for t2v / tts cost tracking)',\r\n 'row.endpoints': 'Endpoints',\r\n 'row.endpointsDesc': 'Structured capability catalog. The agent reads it via aigc_get_provider_info — no natural-language parsing needed',\r\n 'row.endpointsEmpty': 'No endpoints yet. Click \"Auto-detect\" or \"+ Add endpoint\" below',\r\n 'row.addEndpoint': '+ Add endpoint',\r\n 'row.editEndpoint': 'Edit endpoint',\r\n 'row.removeEndpoint': 'Remove',\r\n 'row.endpointPath': 'Path',\r\n 'row.endpointMethod': 'Method',\r\n 'row.endpointCapability': 'Capability',\r\n 'row.endpointResponseKind': 'Response kind',\r\n 'row.endpointResponsePath': 'Response field path',\r\n 'row.endpointAcceptsCanvasRef': 'Accepts $base64 placeholder',\r\n 'row.endpointNotes': 'Notes',\r\n 'row.endpointParams': 'Parameters',\r\n 'row.endpointParamsEmpty': 'No parameters',\r\n 'row.endpointParamName': 'Name',\r\n 'row.endpointParamType': 'Type',\r\n 'row.endpointParamRequired': 'Required',\r\n 'row.endpointParamDefault': 'Default',\r\n 'row.endpointAddParam': '+ Add parameter',\r\n 'row.endpointRemoveParam': 'Remove parameter',\r\n 'row.endpointCancel': 'Cancel',\r\n 'row.endpointSave': 'Save',\r\n 'row.autoDetect': 'Auto-detect',\r\n 'row.autoDetectTitle': 'Ask the agent to auto-detect the response shape via aigc_probe_endpoint',\r\n 'row.autoDetectPrompt': 'Please auto-detect the response shape for the AIGC provider \"{name}\" (id: {id}): for every endpoint whose response.kind is not yet set, call aigc_probe_endpoint (it sends ONE minimal test request — apiKey is attached automatically) and save the detected response.kind + response.path into the EndpointSpec via aigc_provider_set_endpoints. If this provider has no endpoints at all yet, first probe common endpoints with aigc_http_request (e.g. /v1/images/generations, /v1/videos/generations, /v1/audio/speech), then probe the response shape with aigc_probe_endpoint.',\r\n}\r\n","/**\r\n * Client half of @huanlin/dsh-plugin-aigc-canvas: registers\r\n * (1) a better-sidebar tab (`aigc-canvas:main`) rendering the canvas view, and\r\n * (2) a settings.section slot for the provider config page.\r\n *\r\n * i18n: registers the `dsh-aigc-canvas` locale namespace (zh + en) and binds\r\n * a translate function passed to both the canvas view and the settings page\r\n * via inject — so the UI respects the DSH locale toggle (no hardcoded text).\r\n *\r\n * The settings page's \"initialize\" action sends a prepared prompt into the\r\n * current conversation via the `conversation` service (ui-conversation).\r\n */\r\nimport type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'\r\n// Type-only: pulls the locale plugin's Context merge (ctx.locale).\r\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\r\n// Type-only: pulls the settings shell's SlotMap merge (settings.section).\r\nimport type {} from '@deepseek-ai/dsh-client-ui-settings/client'\r\n// Type-only: pulls the conversation service merge (ctx.conversation.send).\r\nimport type {} from '@deepseek-ai/dsh-client-ui-conversation/client'\r\n// Type-only: pulls the ui-slots LocaleNamespaceMap + ctx.slots.\r\nimport type {} from '@deepseek-ai/dsh-client-ui-slots'\r\nimport type {} from 'dsh-better-sidebar/client'\r\nimport { createElement, useEffect, useRef, type ReactNode } from 'react'\r\nimport { CanvasStore } from './store.js'\r\nimport { CanvasViewWithBoundary } from './CanvasView.js'\r\nimport { SettingsPage, type AigcSettingsInjected } from './SettingsPage.js'\r\nimport { en, zh, NS, type AigcKey } from './locales.js'\r\n\r\n/** Locale namespace map declaration for the DSH locale system. */\r\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\r\n interface LocaleNamespaceMap {\r\n 'dsh-aigc-canvas': AigcKey\r\n }\r\n}\r\n\r\n/** Services required before mounting. */\r\nexport const inject = ['betterSidebar', 'slots', 'locale', 'conversation']\r\n\r\nexport function apply(ctx: ClientContext): void {\r\n // ── Locale registration ────────────────────────────────────────────────\r\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-aigc-canvas: dictionaries')\r\n const t = ctx.locale.bind(NS) as (key: string) => string\r\n\r\n // ── better-sidebar tab ──────────────────────────────────────────────────\r\n const betterSidebar = (ctx as unknown as {\r\n betterSidebar?: { registerTab(descriptor: unknown): () => void }\r\n }).betterSidebar\r\n if (betterSidebar !== undefined) {\r\n ctx.effect(() =>\r\n betterSidebar.registerTab({\r\n id: 'aigc-canvas:main',\r\n title: () => t('tabTitle'),\r\n order: 50,\r\n dedupeKey: () => 'aigc-canvas:main',\r\n component: ({ scope }: { scope: { sessionId: string } }): ReactNode => {\r\n const storeRef = useRef<CanvasStore | null>(null)\r\n if (storeRef.current === null || storeRef.current.sessionId !== scope.sessionId) {\r\n storeRef.current?.dispose()\r\n storeRef.current = new CanvasStore({ sessionId: scope.sessionId })\r\n }\r\n useEffect(() => {\r\n return () => {\r\n storeRef.current?.dispose()\r\n storeRef.current = null\r\n }\r\n }, [])\r\n return createElement(CanvasViewWithBoundary, { store: storeRef.current, t })\r\n },\r\n }),\r\n )\r\n }\r\n\r\n // ── Settings section ────────────────────────────────────────────────────\r\n const settingsInjected = (): AigcSettingsInjected => ({\r\n t,\r\n send: (text) => ctx.conversation.send(text),\r\n })\r\n ctx.slots.inject('settings.section', () =>\r\n ctx.slots.register({\r\n name: 'settings.section',\r\n id: 'aigc-canvas',\r\n order: 60,\r\n label: () => t('settingsNav'),\r\n locale: NS,\r\n inject: settingsInjected,\r\n }, SettingsPage),\r\n )\r\n}\r\n"],"mappings":"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"}
|