| 6 | import LinearCopyButton from './LinearCopyButton'; |
| 7 | // ─── Shared fetchAuth (same as AgentDetail) ───────────── |
| 8 | function fetchAuth<T>(url: string, options?: RequestInit): Promise<T> { |
| 9 | const token = localStorage.getItem('token'); |
| 10 | return fetch(`/api${url}`, { |
| 11 | ...options, |
| 12 | headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) }, |
| 13 | }).then(async r => { |
| 14 | if (r.status === 204) { |
| 15 | return undefined as T; |
| 16 | } |
| 17 | if (!r.ok) { |
| 18 | const error = await r.json().catch(() => ({ detail: `HTTP ${r.status}` })); |
| 19 | throw new Error(error.detail || `HTTP ${r.status}`); |
| 20 | } |
| 21 | return r.json() as Promise<T>; |
| 22 | }); |
| 23 | } |
| 24 | |
| 25 | // ─── Types ────────────────────────────────────────────── |
| 26 | interface ChannelConfigProps { |