@openchambery/web 2.1.9-beta.1 → 2.1.9-beta.2
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/dist/assets/{AgentAvatar-CJQwq8UM.js → AgentAvatar-qLxaEaDh.js} +1 -1
- package/dist/assets/{AssistantView-j9aI8OWI.js → AssistantView-CeP8V0X-.js} +3 -3
- package/dist/assets/{DiagramView-EsIuVPrU.js → DiagramView-DRCsjVx9.js} +1 -1
- package/dist/assets/{FadeInOnReveal-BNVExwoL.js → FadeInOnReveal-CX8Bkq-l.js} +1 -1
- package/dist/assets/{Icon-B4xKSuz3.js → Icon-BCFeHDWx.js} +1 -1
- package/dist/assets/{ImageLoadingPlaceholder-xB8WeKks.js → ImageLoadingPlaceholder-DEpMJXzV.js} +1 -1
- package/dist/assets/{LoadingImage-CoT3GWhg.js → LoadingImage-BAT9D9wN.js} +1 -1
- package/dist/assets/{MarkdownRenderer-TmfHeWHu.js → MarkdownRenderer-BvKaN2KX.js} +2 -2
- package/dist/assets/{MarkdownRendererImpl-vkv1QLTd.js → MarkdownRendererImpl-D6iUJhtT.js} +1 -1
- package/dist/assets/{MarkstreamRendererImpl-BbnksqWU.js → MarkstreamRendererImpl-B14yVm7-.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-CtGncmBY.js → MobileDetailNavigation-e4vO0lXT.js} +1 -1
- package/dist/assets/{MobileShareBridge-pYQFFYmm.js → MobileShareBridge-BnA02Mps.js} +2 -2
- package/dist/assets/{MobileTabPageHeader-D7NAfatx.js → MobileTabPageHeader-nApqJ-1X.js} +1 -1
- package/dist/assets/{MultiRunWindow-gZk-f5lA.js → MultiRunWindow-C7Vgvpoz.js} +1 -1
- package/dist/assets/{OnboardingScreen-BiLurnX5.js → OnboardingScreen-CqcZEptL.js} +1 -1
- package/dist/assets/{OverlayScrollbar-DIsrS93m.js → OverlayScrollbar-BY5HaNrb.js} +1 -1
- package/dist/assets/{SettingsView-D7Ykm-CM.js → SettingsView-Be7_mr8t.js} +1 -1
- package/dist/assets/{SettingsWindow-CyPZw4xx.js → SettingsWindow-ZnWK6Itb.js} +1 -1
- package/dist/assets/{TerminalView-D-X0mGO4.js → TerminalView-BluEtXH8.js} +1 -1
- package/dist/assets/{ToolOutputDialog-C4vQBg3z.js → ToolOutputDialog-6gouT_GS.js} +1 -1
- package/dist/assets/{appThemeRegistry-DUH4Fprj.js → appThemeRegistry-D59Upe3t.js} +1 -1
- package/dist/assets/{assistant-attachment-cache-Bzewqov4.js → assistant-attachment-cache-B2UAUHUZ.js} +1 -1
- package/dist/assets/{button-BupmKVUs.js → button-CWSs9Baz.js} +1 -1
- package/dist/assets/{collapsible-BAPWS6G-.js → collapsible-ngtoKADo.js} +1 -1
- package/dist/assets/{desktopHosts-BZ7iYE-l.js → desktopHosts-C0e7Nes2.js} +1 -1
- package/dist/assets/{desktopRelayRestore-S9wEiY2U.js → desktopRelayRestore-DckkHKsi.js} +1 -1
- package/dist/assets/{diagram-0a7vH45N.js → diagram-DmlTCkmV.js} +1 -1
- package/dist/assets/{dialog-BYLD4Cm3.js → dialog-BMa16qrs.js} +1 -1
- package/dist/assets/{dropdown-menu.styles-HOWSubFF.js → dropdown-menu.styles-BNwZmBRp.js} +1 -1
- package/dist/assets/{fileMentionTouchSelection-BcqQPEDT.js → fileMentionTouchSelection-DbICTM0g.js} +1 -1
- package/dist/assets/{fileQueries-DZR-mK8h.js → fileQueries-DVpZC5ha.js} +1 -1
- package/dist/assets/{gitApi-BtJfaFQy.js → gitApi-Bq2BWLAz.js} +1 -1
- package/dist/assets/{image-loading-CsxDGgek.js → image-loading-Bj11k4gM.js} +1 -1
- package/dist/assets/{input-DgrLdIys.js → input-CALwaZEB.js} +1 -1
- package/dist/assets/{insertionBoundaries-z2K9a6oY.js → insertionBoundaries-n7dVxiuI.js} +1 -1
- package/dist/assets/{main-DAHeBbJJ.js → main-BlZ-gMwg.js} +2 -2
- package/dist/assets/{main-BDCqUxWf.js → main-DRGmBqpD.js} +4 -4
- package/dist/assets/{markdownHeightCache-Dyctmwqv.js → markdownHeightCache-DXM_5jTe.js} +1 -1
- package/dist/assets/{mcpQueries-BSwb38Pz.js → mcpQueries-BxICKLst.js} +1 -1
- package/dist/assets/miniChat-PxCQIMUm.js +2 -0
- package/dist/assets/mobile-Bs5d4s3_.js +2 -0
- package/dist/assets/{multirun-DldZm-Aq.js → multirun-BxUSBUb_.js} +1 -1
- package/dist/assets/{persistence-B4Ni3Gmv.js → persistence-BKszKaoQ.js} +1 -1
- package/dist/assets/{platform-BQPsr8Zl.js → platform-CgwxwfA4.js} +1 -1
- package/dist/assets/{projectMeta-zESSNFVw.js → projectMeta-dZJ-hOil.js} +1 -1
- package/dist/assets/{relay-image-stream-qI2NTXbG.js → relay-image-stream-SV0lH6aG.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-t1IsnPfc.js → renderElectronMiniChatApp-CGWfxiDc.js} +2 -2
- package/dist/assets/{renderMobileApp-BrC28EkU.js → renderMobileApp-DJmWaXgS.js} +4 -4
- package/dist/assets/runtime-auth-BpCQ-dPr.js +1 -0
- package/dist/assets/{runtime-fetch-QCWYlAx0.js → runtime-fetch-WgH0pROs.js} +1 -1
- package/dist/assets/{runtime-switch-3ad3yzM7.js → runtime-switch-CMiMO5Yj.js} +1 -1
- package/dist/assets/{runtimeConfig-5NAbSrPI.js → runtimeConfig-B-2tboUz.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-CxreCHBU.js → runtimeEndpointReset-BbJRibgL.js} +2 -2
- package/dist/assets/{scheduledTaskNavigation-C1PrFEhV.js → scheduledTaskNavigation-DQcLqQ52.js} +1 -1
- package/dist/assets/{sessionChangeSummary-CUMpXSiU.js → sessionChangeSummary-DTeJLaNT.js} +1 -1
- package/dist/assets/{sessionLookup-DD8YnthC.js → sessionLookup-_U9nCuBN.js} +1 -1
- package/dist/assets/{sortable-tabs-strip-DogWaIrG.js → sortable-tabs-strip-CscHgCaq.js} +1 -1
- package/dist/assets/{speechSettingsQueries-PsDvs5QG.js → speechSettingsQueries-CdlOc_sI.js} +2 -2
- package/dist/assets/{terminalApi-kRMttlcP.js → terminalApi-rxsMWL0o.js} +1 -1
- package/dist/assets/{textarea-Boj9axpc.js → textarea-ClV5sMS-.js} +1 -1
- package/dist/assets/{tooltip-Dbgnq-Mh.js → tooltip-CV6dvLBp.js} +1 -1
- package/dist/assets/{url-Bd61gNgl.js → url-nBOUbtV_.js} +1 -1
- package/dist/assets/{useAppFontEffects-Ba6H7bLU.js → useAppFontEffects-YhyFj8z3.js} +5 -5
- package/dist/assets/{useAssistantUIStore-Dlvb7P0q.js → useAssistantUIStore-OyPm_4M_.js} +1 -1
- package/dist/assets/{useDesktopWindowControlsLayout-CbeUwtDM.js → useDesktopWindowControlsLayout-jdIXqoD8.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-wtPL_zdo.js → useEffectiveDirectory-COgvBW0Q.js} +1 -1
- package/dist/assets/{useFontPreferences-lAw0Cbza.js → useFontPreferences-DqEIKMEW.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-DXpdkzw_.js → useMobileNavigationStore-CuOiHjP1.js} +11 -11
- package/dist/assets/{useUIStore-CDMI_Yzu.js → useUIStore-CEqU9Ujv.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-BXDSKlPX.js → useWorkerHighlightedLines-DGH-O6ZJ.js} +1 -1
- package/dist/index.html +11 -11
- package/dist/mini-chat.html +11 -11
- package/dist/mobile.html +11 -11
- package/package.json +1 -1
- package/server/lib/git/DOCUMENTATION.md +1 -1
- package/server/lib/git/branches.test.js +39 -0
- package/server/lib/git/service.js +3 -43
- package/server/lib/relay/DOCUMENTATION.md +20 -0
- package/server/lib/relay/relay-server.e2e.test.ts +35 -0
- package/server/lib/relay/tunnel-host.js +14 -4
- package/server/lib/relay/tunnel-host.test.js +37 -1
- package/dist/assets/miniChat-DEIx3C4R.js +0 -2
- package/dist/assets/mobile-DmNNI21w.js +0 -2
- package/dist/assets/runtime-auth-C8w0nlKy.js +0 -1
|
@@ -75,6 +75,26 @@ See also `packages/web/server/lib/opencode/DOCUMENTATION.md` (“Catalog / OpenC
|
|
|
75
75
|
4. **Handshake.** Over that connection pair, client and host run the E2EE handshake and derive a shared encrypted channel the relay cannot read.
|
|
76
76
|
5. **Traffic.** All normal app traffic is multiplexed and encrypted through that channel. On the host, decrypted requests are dispatched to the local server over loopback; responses stream back encrypted. Reconnects re-establish a fresh channel and the app's existing retry machinery recovers.
|
|
77
77
|
|
|
78
|
+
## Negotiated JSON response compression
|
|
79
|
+
|
|
80
|
+
Each HTTP request may advertise `acceptEncoding: 'gzip'` in its tunnel JSON head
|
|
81
|
+
when the client supports `DecompressionStream`. The Host may then set
|
|
82
|
+
`encoding: 'gzip'` on the response head and stream gzip bytes as ordinary HttpBody
|
|
83
|
+
frames **before encryption**. The client decompresses before exposing its Fetch
|
|
84
|
+
Response; HTTP headers describe the decoded body, with no compressed content-length
|
|
85
|
+
or content-encoding leaked to callers. Wire framing, batching and crypto counters
|
|
86
|
+
are unchanged. Old Hosts ignore the opt-in; old clients (including native Android
|
|
87
|
+
notifications) omit it and receive uncompressed bodies.
|
|
88
|
+
|
|
89
|
+
Only application/json and application/*+json bodies qualify. Known decoded bodies
|
|
90
|
+
under 1 KiB, HEAD/no-body responses, SSE and binary assets are not compressed.
|
|
91
|
+
Unknown-length JSON is streamed rather than buffered in full; loopback fetch's
|
|
92
|
+
automatic decompression is accounted for before checking length. Cancellation and
|
|
93
|
+
errors propagate through the stream pipeline. Host tests cover negotiation and
|
|
94
|
+
legacy/SSE/binary exclusions; client tests cover malformed gzip and cancellation;
|
|
95
|
+
the authenticated compiled-Relay integration test checks decoded snapshot fidelity
|
|
96
|
+
and encrypted wire-byte reduction on 4,000 session summaries.
|
|
97
|
+
|
|
78
98
|
## Candidate refresh (staying off the relay when direct works)
|
|
79
99
|
|
|
80
100
|
Pairing-payload transport candidates are a snapshot: when DHCP hands the host
|
|
@@ -36,6 +36,9 @@ import { requestSpeechSession } from '../../../../ui/src/lib/voice/direct-sessio
|
|
|
36
36
|
|
|
37
37
|
const timeoutMs = 10_000;
|
|
38
38
|
const previewPng = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+aD1sAAAAASUVORK5CYII=', 'base64');
|
|
39
|
+
const initializationSnapshot = { sessions: Array.from({ length: 4000 }, (_, id) => ({
|
|
40
|
+
id: `session-${id}`, title: `Session ${id}`, directory: '/repo/project', time: { created: 1000, updated: 2000 },
|
|
41
|
+
})) };
|
|
39
42
|
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
40
43
|
|
|
41
44
|
const eventually = async (predicate: () => boolean | Promise<boolean>, message: string, timeout = timeoutMs) => {
|
|
@@ -215,6 +218,10 @@ const startOrigin = async () => {
|
|
|
215
218
|
});
|
|
216
219
|
return;
|
|
217
220
|
}
|
|
221
|
+
if (pathname === '/api/e2e/initialization' && req.method === 'GET') {
|
|
222
|
+
await uiAuth.requireAuth(req, res, () => res.json(initializationSnapshot));
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
218
225
|
if (pathname === '/api/agent' && req.method === 'GET') {
|
|
219
226
|
await uiAuth.requireAuth(req, res, () => {
|
|
220
227
|
const directory = new URL(req.url ?? '/', 'http://origin').searchParams.get('location[directory]');
|
|
@@ -401,10 +408,32 @@ describe('private relay compiled-process boundary', () => {
|
|
|
401
408
|
origin = await startOrigin();
|
|
402
409
|
const identity = await buildIdentity();
|
|
403
410
|
host = startRelayHost({ relayUrl: relay.url, identity, getLocalPort: () => origin.port, onStatus: () => {}, logger: { warn: () => {}, info: () => {} } });
|
|
411
|
+
let receivedBytes = 0;
|
|
404
412
|
client = createRelayTunnelClient({
|
|
405
413
|
relayUrl: relay.url, serverId: identity.serverId, hostEncPubJwk: identity.hostEncPubJwk,
|
|
406
414
|
helloRetryMs: 50, helloTimeoutMs: 2_000, pingIntervalMs: 500, pingTimeoutMs: 250,
|
|
407
415
|
reconnectBaseDelayMs: 50, reconnectMaxDelayMs: 250, batchWindowMs: 5,
|
|
416
|
+
createWireSocket: (url) => {
|
|
417
|
+
const socket = new globalThis.WebSocket(url);
|
|
418
|
+
socket.binaryType = 'arraybuffer';
|
|
419
|
+
const wire = {
|
|
420
|
+
get readyState() { return socket.readyState; },
|
|
421
|
+
send: (data: string | ArrayBuffer | Uint8Array) => socket.send(data as string | ArrayBuffer),
|
|
422
|
+
close: (code?: number, reason?: string) => socket.close(code, reason),
|
|
423
|
+
onopen: null as (() => void) | null,
|
|
424
|
+
onmessage: null as ((event: { data: unknown }) => void) | null,
|
|
425
|
+
onclose: null as ((event: { code: number; reason: string }) => void) | null,
|
|
426
|
+
onerror: null as (() => void) | null,
|
|
427
|
+
};
|
|
428
|
+
socket.onopen = () => wire.onopen?.();
|
|
429
|
+
socket.onmessage = (event) => {
|
|
430
|
+
receivedBytes += typeof event.data === 'string' ? Buffer.byteLength(event.data) : event.data.byteLength;
|
|
431
|
+
wire.onmessage?.({ data: event.data });
|
|
432
|
+
};
|
|
433
|
+
socket.onclose = (event) => wire.onclose?.({ code: event.code, reason: event.reason });
|
|
434
|
+
socket.onerror = () => wire.onerror?.();
|
|
435
|
+
return wire;
|
|
436
|
+
},
|
|
408
437
|
});
|
|
409
438
|
|
|
410
439
|
await eventually(() => host!.getStatus().state === 'connected' && client!.getStatus().state === 'connected', 'host and TypeScript client did not connect');
|
|
@@ -415,6 +444,12 @@ describe('private relay compiled-process boundary', () => {
|
|
|
415
444
|
expect(httpResponse.status).toBe(200);
|
|
416
445
|
expect(await httpResponse.json()).toEqual({ body: 'stream-body', hasRelayConnection: true });
|
|
417
446
|
|
|
447
|
+
const beforeSnapshot = receivedBytes;
|
|
448
|
+
const compressed = await client.fetch('/api/e2e/initialization', { headers: { authorization: 'Bearer client-token' } });
|
|
449
|
+
expect(compressed.status).toBe(200);
|
|
450
|
+
expect(await compressed.json()).toEqual(initializationSnapshot);
|
|
451
|
+
expect(receivedBytes - beforeSnapshot).toBeLessThan(Buffer.byteLength(JSON.stringify(initializationSnapshot)) / 4);
|
|
452
|
+
|
|
418
453
|
const sseResponse = await client.fetch('/api/e2e/sse', { headers: { authorization: 'Bearer client-token' } });
|
|
419
454
|
const reader = sseResponse.body!.getReader();
|
|
420
455
|
const chunks: Uint8Array[] = [];
|
|
@@ -258,11 +258,21 @@ export const createTunnelHost = ({
|
|
|
258
258
|
if (STRIPPED_RESPONSE_HEADERS.has(name)) continue;
|
|
259
259
|
responseHeaders[name] = value;
|
|
260
260
|
}
|
|
261
|
-
await sendJson(TunnelFrameType.HttpResponse, streamId, { status: response.status, headers: responseHeaders });
|
|
262
|
-
|
|
263
261
|
try {
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
const contentType = (response.headers.get('content-type') ?? '').split(';', 1)[0].trim().toLowerCase();
|
|
263
|
+
const contentLength = response.headers.has('content-encoding') ? null : response.headers.get('content-length');
|
|
264
|
+
// Compress finite JSON responses before encryption, never SSE or binary assets.
|
|
265
|
+
// Old clients omit acceptEncoding and old hosts ignore it, preserving v1 framing.
|
|
266
|
+
const gzip = request.acceptEncoding === 'gzip' && typeof CompressionStream === 'function'
|
|
267
|
+
&& method !== 'HEAD' && response.body !== null
|
|
268
|
+
&& (contentType === 'application/json' || /^application\/[^/]+\+json$/.test(contentType))
|
|
269
|
+
&& (contentLength === null || Number(contentLength) >= 1024);
|
|
270
|
+
const body = gzip ? response.body.pipeThrough(new CompressionStream('gzip')) : response.body;
|
|
271
|
+
await sendJson(TunnelFrameType.HttpResponse, streamId, {
|
|
272
|
+
status: response.status, headers: responseHeaders, ...(gzip ? { encoding: 'gzip' } : {}),
|
|
273
|
+
});
|
|
274
|
+
if (body) {
|
|
275
|
+
for await (const chunk of body) {
|
|
266
276
|
if (closed || stream.abort.signal.aborted) return;
|
|
267
277
|
const bytes = chunk instanceof Uint8Array ? chunk : new Uint8Array(chunk);
|
|
268
278
|
for (const piece of chunkPayload(bytes, MAX_TUNNEL_PAYLOAD_BYTES)) {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// corrupted payload. This test must stay red until send serialization is fixed.
|
|
8
8
|
// Production send path is intentionally not changed here.
|
|
9
9
|
|
|
10
|
-
import { describe, expect, it } from '
|
|
10
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
MAX_TUNNEL_PAYLOAD_BYTES,
|
|
@@ -68,6 +68,42 @@ const waitFor = async (predicate, { timeoutMs = 2000, intervalMs = 5 } = {}) =>
|
|
|
68
68
|
throw new Error('waitFor timed out');
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
describe('negotiated JSON response compression', () => {
|
|
72
|
+
it.each([
|
|
73
|
+
{ acceptEncoding: 'gzip', contentType: 'application/json', compressed: true },
|
|
74
|
+
{ acceptEncoding: 'gzip', contentType: 'application/problem+json', compressed: true },
|
|
75
|
+
{ acceptEncoding: undefined, contentType: 'application/json', compressed: false },
|
|
76
|
+
{ acceptEncoding: 'gzip', contentType: 'text/event-stream', compressed: false },
|
|
77
|
+
{ acceptEncoding: 'gzip', contentType: 'image/png', compressed: false },
|
|
78
|
+
{ acceptEncoding: 'gzip', contentType: 'application/json', small: true, compressed: false },
|
|
79
|
+
])('preserves body and legacy/SSE behavior for $contentType / $acceptEncoding / small=$small', async ({ acceptEncoding, contentType, small, compressed }) => {
|
|
80
|
+
const text = JSON.stringify({ rows: Array.from({ length: small ? 1 : 4000 }, (_, id) => ({ id, title: 'Session summary', directory: '/repo/project' })) });
|
|
81
|
+
const raw = textEncoder.encode(text);
|
|
82
|
+
const fetchMock = vi.spyOn(globalThis, 'fetch').mockResolvedValue(new Response(raw, {
|
|
83
|
+
headers: { 'content-type': contentType, 'content-length': String(raw.byteLength) },
|
|
84
|
+
}));
|
|
85
|
+
const frames = [];
|
|
86
|
+
const host = createTunnelHost({ connectionId: 'compression-test', getLocalPort: () => 9,
|
|
87
|
+
sendFrame: (frame) => { frames.push(decodeTunnelFrame(frame)); }, getBufferedAmount: () => 0 });
|
|
88
|
+
try {
|
|
89
|
+
await host.handleFrame(encodeTunnelFrame(TunnelFrameType.HttpRequest, 1, encodeJsonPayload({
|
|
90
|
+
method: 'GET', path: '/api/test', query: '', headers: {}, ...(acceptEncoding ? { acceptEncoding } : {}),
|
|
91
|
+
})));
|
|
92
|
+
await waitFor(() => frames.some((frame) => frame.frameType === TunnelFrameType.StreamEnd));
|
|
93
|
+
const head = JSON.parse(textDecoder.decode(frames.find((frame) => frame.frameType === TunnelFrameType.HttpResponse).payload));
|
|
94
|
+
expect(head.encoding).toBe(compressed ? 'gzip' : undefined);
|
|
95
|
+
expect(head.headers['content-length']).toBeUndefined();
|
|
96
|
+
const body = new Blob(frames.filter((frame) => frame.frameType === TunnelFrameType.HttpBody).map((frame) => frame.payload));
|
|
97
|
+
if (compressed) {
|
|
98
|
+
expect(body.size).toBeLessThan(raw.byteLength / 4);
|
|
99
|
+
expect(await new Response(body.stream().pipeThrough(new DecompressionStream('gzip'))).text()).toBe(text);
|
|
100
|
+
} else {
|
|
101
|
+
expect(await body.text()).toBe(text);
|
|
102
|
+
}
|
|
103
|
+
} finally { host.close(); fetchMock.mockRestore(); }
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
71
107
|
describe('isTunnelWsPathAllowed', () => {
|
|
72
108
|
it('allows exact terminal/dictation/event sockets and preview proxy prefix', () => {
|
|
73
109
|
expect(isTunnelWsPathAllowed('/api/terminal/ws')).toBe(true);
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/renderElectronMiniChatApp-t1IsnPfc.js","assets/rolldown-runtime-hePW80VL.js","assets/persistence-B4Ni3Gmv.js","assets/runtime-auth-C8w0nlKy.js","assets/runtime-switch-3ad3yzM7.js","assets/runtime-fetch-QCWYlAx0.js","assets/vendor-zustand-o69pgTEK.js","assets/vendor-base-ui-CdzJ6My_.js","assets/useUIStore-CDMI_Yzu.js","assets/vendor-react-BP2cRVqX.js","assets/vendor-pathe-vBmvQE8f.js","assets/vendor-tanstack-query-core-BWz0ose6.js","assets/platform-BQPsr8Zl.js","assets/vendor-opencode-client-MF2GBrFx.js","assets/vendor-aparajita-capacitor-secure-storage-xol_6BsB.js","assets/vendor-reactuses-core-BpfIZ1tg.js","assets/vendor-lodash-es-DfLbG5Af.js","assets/vendor-js-cookie-hSOiFTtX.js","assets/button-BupmKVUs.js","assets/store-CG7Ytsg9.js","assets/vendor-class-variance-authority-BLUaYARZ.js","assets/vendor-tailwind-merge-BicNWLTg.js","assets/useMobileNavigationStore-DXpdkzw_.js","assets/vendor-tanstack-react-query-CdqCAt40.js","assets/vendor-sonner-ZS8XIOVl.js","assets/useAssistantUIStore-Dlvb7P0q.js","assets/vendor-zod-Dzk5kdUU.js","assets/vendor-fuse.js-DB5wDJbI.js","assets/Icon-B4xKSuz3.js","assets/useAppFontEffects-Ba6H7bLU.js","assets/desktopHosts-BZ7iYE-l.js","assets/desktopRelayRestore-S9wEiY2U.js","assets/vendor-pierre-diffs-DPBtNDJ5.js","assets/vendor-hast-util-to-html-Bw_SgZ1t.js","assets/vendor-character-entities-legacy-Wut6vMuj.js","assets/vendor-character-entities-html4-DlN_yAFd.js","assets/vendor-ccount-CyGsA0u7.js","assets/vendor-comma-separated-tokens-B9ouxNNS.js","assets/vendor-oniguruma-to-es-CrHzjjSU.js","assets/vendor-oniguruma-parser-D2DIvhSP.js","assets/vendor-diff-Dq7CZNim.js","assets/vendor-lru_map-BMOrLc9L.js","assets/rasterizePng-CpK-xCkB.js","assets/dualLimitLru-D8Sphgua.js","assets/AgentAvatar-CJQwq8UM.js","assets/vendor-dicebear-core-CV95S5Pg.js","assets/vendor-dicebear-styles-7lEG-JsF.js","assets/useThemeSystem-8jhE4Zyk.js","assets/dialog-BYLD4Cm3.js","assets/gitApi-BtJfaFQy.js","assets/vendor-simplewebauthn-browser-Dwhcdg_5.js","assets/projectMeta-zESSNFVw.js","assets/input-DgrLdIys.js","assets/tooltip-Dbgnq-Mh.js","assets/OverlayScrollbar-DIsrS93m.js","assets/textarea-Boj9axpc.js","assets/vendor-framer-motion-D-oiwsxL.js","assets/vendor-dnd-kit-core-5pNnzVdw.js","assets/vendor-dnd-kit-accessibility-COSwgjFs.js","assets/vendor-dnd-kit-sortable-Dm50I0m7.js","assets/speechSettingsQueries-PsDvs5QG.js","assets/dropdown-menu.styles-HOWSubFF.js","assets/image-loading-CsxDGgek.js","assets/fileQueries-DZR-mK8h.js","assets/useRuntimeAPIs-Cx8S1HLz.js","assets/relay-image-stream-qI2NTXbG.js","assets/image-loading-CObM4tcX.css","assets/sessionChangeSummary-CUMpXSiU.js","assets/LoadingImage-CoT3GWhg.js","assets/ImageLoadingPlaceholder-xB8WeKks.js","assets/sessionChangeSummary-vC84qM3v.css","assets/insertionBoundaries-z2K9a6oY.js","assets/fileMentionTouchSelection-BcqQPEDT.js","assets/appThemeRegistry-DUH4Fprj.js","assets/MarkdownRenderer-TmfHeWHu.js","assets/markdownHeightCache-Dyctmwqv.js","assets/url-Bd61gNgl.js","assets/markdown-worker-DFNZ3KJ_.js","assets/useEffectiveDirectory-wtPL_zdo.js","assets/FadeInOnReveal-BNVExwoL.js","assets/markdownTheme-CV7_0QAL.js","assets/useWorkerHighlightedLines-BXDSKlPX.js","assets/vendor-tanstack-react-virtual-B_EO--9t.js","assets/vendor-cmdk-RDxC-9Iz.js","assets/vendor-aria-hidden-BbL3cEyI.js","assets/sortable-tabs-strip-DogWaIrG.js","assets/vendor-motion-88WXBOBf.js","assets/vendor-legendapp-list-CNxU_ALy.js","assets/useFontPreferences-lAw0Cbza.js","assets/terminalApi-kRMttlcP.js","assets/useDesktopWindowControlsLayout-CbeUwtDM.js","assets/src-CdGit3gf.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{t as e}from"./runtimeConfig-5NAbSrPI.js";import{o as t}from"./vendor-aparajita-capacitor-secure-storage-xol_6BsB.js";/* empty css */window.__OPENCHAMBER_RUNTIME_APIS__=e(),t(async()=>{let{renderElectronMiniChatApp:e}=await import(`./renderElectronMiniChatApp-t1IsnPfc.js`);return{renderElectronMiniChatApp:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91])).then(({renderElectronMiniChatApp:t})=>{t(window.__OPENCHAMBER_RUNTIME_APIS__??e())});
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/renderMobileApp-BrC28EkU.js","assets/rolldown-runtime-hePW80VL.js","assets/runtime-auth-C8w0nlKy.js","assets/runtime-switch-3ad3yzM7.js","assets/runtime-fetch-QCWYlAx0.js","assets/persistence-B4Ni3Gmv.js","assets/vendor-zustand-o69pgTEK.js","assets/vendor-base-ui-CdzJ6My_.js","assets/useUIStore-CDMI_Yzu.js","assets/vendor-react-BP2cRVqX.js","assets/vendor-pathe-vBmvQE8f.js","assets/vendor-tanstack-query-core-BWz0ose6.js","assets/platform-BQPsr8Zl.js","assets/vendor-opencode-client-MF2GBrFx.js","assets/vendor-aparajita-capacitor-secure-storage-xol_6BsB.js","assets/capgoAdapter-KNLHDj7G.js","assets/types-BuiqMmh_.js","assets/vendor-pierre-diffs-DPBtNDJ5.js","assets/vendor-hast-util-to-html-Bw_SgZ1t.js","assets/vendor-character-entities-legacy-Wut6vMuj.js","assets/vendor-character-entities-html4-DlN_yAFd.js","assets/vendor-ccount-CyGsA0u7.js","assets/vendor-comma-separated-tokens-B9ouxNNS.js","assets/vendor-oniguruma-to-es-CrHzjjSU.js","assets/vendor-oniguruma-parser-D2DIvhSP.js","assets/vendor-diff-Dq7CZNim.js","assets/vendor-lru_map-BMOrLc9L.js","assets/vendor-sonner-ZS8XIOVl.js","assets/vendor-reactuses-core-BpfIZ1tg.js","assets/vendor-lodash-es-DfLbG5Af.js","assets/vendor-js-cookie-hSOiFTtX.js","assets/button-BupmKVUs.js","assets/store-CG7Ytsg9.js","assets/vendor-class-variance-authority-BLUaYARZ.js","assets/vendor-tailwind-merge-BicNWLTg.js","assets/MobileShareBridge-pYQFFYmm.js","assets/MobileDetailNavigation-CtGncmBY.js","assets/vendor-tanstack-react-query-CdqCAt40.js","assets/useMobileNavigationStore-DXpdkzw_.js","assets/useAssistantUIStore-Dlvb7P0q.js","assets/vendor-zod-Dzk5kdUU.js","assets/vendor-fuse.js-DB5wDJbI.js","assets/Icon-B4xKSuz3.js","assets/rasterizePng-CpK-xCkB.js","assets/AgentAvatar-CJQwq8UM.js","assets/vendor-dicebear-core-CV95S5Pg.js","assets/vendor-dicebear-styles-7lEG-JsF.js","assets/dualLimitLru-D8Sphgua.js","assets/useThemeSystem-8jhE4Zyk.js","assets/dialog-BYLD4Cm3.js","assets/gitApi-BtJfaFQy.js","assets/useAppFontEffects-Ba6H7bLU.js","assets/desktopHosts-BZ7iYE-l.js","assets/desktopRelayRestore-S9wEiY2U.js","assets/vendor-simplewebauthn-browser-Dwhcdg_5.js","assets/projectMeta-zESSNFVw.js","assets/input-DgrLdIys.js","assets/tooltip-Dbgnq-Mh.js","assets/OverlayScrollbar-DIsrS93m.js","assets/textarea-Boj9axpc.js","assets/vendor-framer-motion-D-oiwsxL.js","assets/vendor-dnd-kit-core-5pNnzVdw.js","assets/vendor-dnd-kit-accessibility-COSwgjFs.js","assets/vendor-dnd-kit-sortable-Dm50I0m7.js","assets/speechSettingsQueries-PsDvs5QG.js","assets/dropdown-menu.styles-HOWSubFF.js","assets/image-loading-CsxDGgek.js","assets/fileQueries-DZR-mK8h.js","assets/useRuntimeAPIs-Cx8S1HLz.js","assets/relay-image-stream-qI2NTXbG.js","assets/image-loading-CObM4tcX.css","assets/sessionChangeSummary-CUMpXSiU.js","assets/LoadingImage-CoT3GWhg.js","assets/ImageLoadingPlaceholder-xB8WeKks.js","assets/sessionChangeSummary-vC84qM3v.css","assets/insertionBoundaries-z2K9a6oY.js","assets/fileMentionTouchSelection-BcqQPEDT.js","assets/appThemeRegistry-DUH4Fprj.js","assets/MarkdownRenderer-TmfHeWHu.js","assets/markdownHeightCache-Dyctmwqv.js","assets/url-Bd61gNgl.js","assets/markdown-worker-DFNZ3KJ_.js","assets/useEffectiveDirectory-wtPL_zdo.js","assets/FadeInOnReveal-BNVExwoL.js","assets/markdownTheme-CV7_0QAL.js","assets/useWorkerHighlightedLines-BXDSKlPX.js","assets/vendor-tanstack-react-virtual-B_EO--9t.js","assets/vendor-cmdk-RDxC-9Iz.js","assets/vendor-aria-hidden-BbL3cEyI.js","assets/sortable-tabs-strip-DogWaIrG.js","assets/vendor-motion-88WXBOBf.js","assets/vendor-legendapp-list-CNxU_ALy.js","assets/useFontPreferences-lAw0Cbza.js","assets/terminalApi-kRMttlcP.js","assets/MobileTabPageHeader-D7NAfatx.js","assets/vendor-codemirror-autocomplete-7c2L_4dM.js","assets/vendor-codemirror-lang-angular-DXOgWEVj.js","assets/vendor-codemirror-lang-json-mLulNbwB.js","assets/vendor-codemirror-lang-markdown-CV1IO6Qs.js","assets/vendor-codemirror-lang-python-YM2WVLHF.js","assets/vendor-codemirror-legacy-modes-DwltVFbT.js","assets/mcpQueries-BSwb38Pz.js","assets/collapsible-BAPWS6G-.js","assets/vendor-codemirror-commands-B8KrBQ9B.js","assets/vendor-codemirror-search-ZqtrPLjU.js","assets/vendor-replit-codemirror-vim-DDj0dSVY.js","assets/vendor-codemirror-language-data-Ctd4WxgW.js","assets/projectActions-CWvNGKfA.js","assets/runtimeEndpointReset-CxreCHBU.js","assets/scheduledTaskNavigation-C1PrFEhV.js","assets/sessionLookup-DD8YnthC.js","assets/vendor-cron-parser-BmO80h0C.js","assets/runtimeEndpointReset-ByXtaeWD.css","assets/SettingsView-D7Ykm-CM.js","assets/vendor-yaml-C9KlJAlj.js","assets/vendor-qrcode-D7jBCyl-.js","assets/vendor-dijkstrajs-BAzPDGZM.js","assets/AssistantView-j9aI8OWI.js","assets/assistant-attachment-cache-Bzewqov4.js","assets/src-CdGit3gf.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{t as e}from"./runtimeConfig-5NAbSrPI.js";import{o as t}from"./vendor-aparajita-capacitor-secure-storage-xol_6BsB.js";/* empty css */window.__OPENCHAMBER_RUNTIME_APIS__=e(),t(async()=>{let{renderMobileApp:e}=await import(`./renderMobileApp-BrC28EkU.js`);return{renderMobileApp:e}},__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119])).then(({renderMobileApp:t})=>{t(window.__OPENCHAMBER_RUNTIME_APIS__??e())});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e}from"./rolldown-runtime-hePW80VL.js";var t=`openchamber-relay-v1`,n=65526,r={HttpRequest:1,HttpBody:2,HttpResponse:3,StreamEnd:4,StreamAbort:5,WsOpen:6,WsOpened:7,WsText:8,WsBinary:9,WsClose:10,Ping:11,Pong:12},i=new Set(Object.values(r)),a=e=>i.has(e),o={ControlReplaced:4001,DuplicateClient:4002,StuckControlReset:4003,HostUnavailable:4008,AuthFailed:4010,LimitExceeded:4029,HostWentAway:1012,RekeyMismatch:1008,ChannelFailure:1011},s=globalThis.crypto.subtle,c={name:`ECDH`,namedCurve:`P-256`},l=16,u=32,d=16,f=4,p=8,m=class extends Error{constructor(e){super(e),this.name=`RelayCryptoError`}},h=()=>s.generateKey(c,!0,[`deriveBits`]),g=async e=>{let t=await s.exportKey(`jwk`,e);return{kty:t.kty,crv:t.crv,x:t.x,y:t.y}},_=async e=>{if(e.kty!==`EC`||e.crv!==`P-256`||typeof e.x!=`string`||typeof e.y!=`string`)throw new m(`invalid ECDH public key JWK`);try{return await s.importKey(`jwk`,{kty:e.kty,crv:e.crv,x:e.x,y:e.y,ext:!0},c,!0,[])}catch{throw new m(`invalid ECDH public key JWK`)}},v=()=>{let e=new Uint8Array(l);return globalThis.crypto.getRandomValues(e),e},y=async(e,n,r)=>{if(r.length!==l)throw new m(`invalid handshake nonce length`);let i=await s.deriveBits({name:`ECDH`,public:n},e,256),a=await s.importKey(`raw`,i,`HKDF`,!1,[`deriveBits`]),o=new Uint8Array(await s.deriveBits({name:`HKDF`,hash:`SHA-256`,salt:r,info:new TextEncoder().encode(t)},a,512)),c=(e,t)=>s.importKey(`raw`,e,{name:`AES-GCM`},!1,t);return{clientToHost:await c(o.slice(0,u),[`encrypt`,`decrypt`]),hostToClient:await c(o.slice(u),[`encrypt`,`decrypt`])}},b=(e,t,n)=>{for(let r=7;r>=0;--r)e[t+r]=Number(n&255n),n>>=8n},x=(e,t)=>{let n=0n;for(let r=0;r<p;r+=1)n=n<<8n|BigInt(e[t+r]);return n},S=e=>{let t=new Uint8Array(f);globalThis.crypto.getRandomValues(t);let n=0n;return{async encrypt(r){if(r.length>65536)throw new m(`plaintext frame exceeds maximum size`);n+=1n;let i=new Uint8Array(12);i.set(t,0),b(i,f,n);let a=new Uint8Array(await s.encrypt({name:`AES-GCM`,iv:i},e,r)),o=new Uint8Array(13+a.length);return o[0]=1,o.set(i,1),o.set(a,13),o}}},C=e=>{let t=0n;return{async decrypt(n){if(n.length<13+d)throw new m(`encrypted frame too short`);if(n[0]!==1)throw new m(`unsupported encrypted frame version`);let r=n.slice(1,13),i=x(r,f);if(i<=t)throw new m(`frame counter regression`);let a;try{a=await s.decrypt({name:`AES-GCM`,iv:r},e,n.slice(13))}catch{throw new m(`frame decryption failed`)}return t=i,new Uint8Array(a)}}},w=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_`,ee=e=>{let t=``;for(let n=0;n<e.length;n+=3){let r=e[n],i=n+1<e.length?e[n+1]:void 0,a=n+2<e.length?e[n+2]:void 0;t+=w[r>>2],t+=w[(r&3)<<4|(i??0)>>4],i!==void 0&&(t+=w[(i&15)<<2|(a??0)>>6]),a!==void 0&&(t+=w[a&63])}return t},te=e=>{let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=`object`||!t)return null;let n=t;if(n.v!==1)return null;let r=n.batch===!0;return n.t===`ready`?{t:`ready`,v:1,batch:r}:n.t===`hello`&&typeof n.nonce==`string`&&typeof n.clientPubJwk==`object`&&n.clientPubJwk!==null?{t:`hello`,v:1,clientPubJwk:n.clientPubJwk,nonce:n.nonce,batch:r}:null},ne=e=>({type:`fail`,closeCode:o.ChannelFailure,reason:e}),re=async(e,t={})=>{let n=t.batch!==!1,r=await _(e),i=await h(),a=v(),o={t:`hello`,v:1,clientPubJwk:await g(i.publicKey),nonce:ee(a),...n?{batch:!0}:{}},s=!1;return{helloText:JSON.stringify(o),get established(){return s},async handleText(e){if(s)return te(e)?.t===`ready`?{type:`ignore`}:ne(`plaintext frame on established channel`);let t=te(e);if(t?.t!==`ready`)return{type:`ignore`};let o=await y(i.privateKey,r,a);return s=!0,{type:`established`,batch:n&&t.batch===!0,channel:{encryptor:S(o.clientToHost),decryptor:C(o.hostToClient)}}}}},T=4294967295,E=class extends Error{constructor(e){super(e),this.name=`TunnelCodecError`}},D=(e,t,n,r=!1)=>{if(!Number.isInteger(t)||t<0||t>T)throw new E(`invalid stream id`);if(n.length>65526)throw new E(`tunnel payload exceeds maximum size`);let i=new Uint8Array(5+n.length);return i[0]=r?e|128:e,i[1]=t>>>24&255,i[2]=t>>>16&255,i[3]=t>>>8&255,i[4]=t&255,i.set(n,5),i},ie=e=>{if(e.length<5)throw new E(`tunnel frame too short`);let t=e[0],n=!!(t&128),r=t&-129;if(!a(r))throw new E(`unknown tunnel frame type ${r}`);return{frameType:r,streamId:(e[1]<<24|e[2]<<16|e[3]<<8|e[4])>>>0,payload:e.slice(5),hasMoreFragments:n}},O=new TextEncoder,k=new TextDecoder,A=e=>O.encode(JSON.stringify(e)),j=(e,t)=>{let n;try{n=JSON.parse(k.decode(e))}catch{throw new E(`malformed JSON tunnel payload`)}if(!t(n))throw new E(`unexpected JSON tunnel payload shape`);return n},M=(e,t=n)=>{if(t<=0||t>65526)throw new E(`invalid chunk size`);if(e.length===0)return[new Uint8Array];let r=[];for(let n=0;n<e.length;n+=t)r.push(e.slice(n,n+t));return r},N=(e,t,n)=>{let r=M(n);return r.map((n,i)=>D(e,t,n,i<r.length-1))},ae=(e=16777216)=>{let t=new Map;return{push(n){let r=`${n.streamId}:${n.frameType}`,i=t.get(r);if(!n.hasMoreFragments&&!i)return n.payload;let a=i?.chunks??[],o=(i?.totalBytes??0)+n.payload.length;if(o>e)throw t.delete(r),new E(`fragmented message exceeds maximum size`);if(a.push(n.payload),n.hasMoreFragments)return t.set(r,{chunks:a,totalBytes:o}),null;t.delete(r);let s=new Uint8Array(o),c=0;for(let e of a)s.set(e,c),c+=e.length;return s},dropStream(e){for(let n of t.keys())n.startsWith(`${e}:`)&&t.delete(n)}}},oe=e=>{if(e.length===0)throw new E(`cannot encode an empty frame batch`);if(e.length===1){let t=e[0],n=new Uint8Array(1+t.length);if(n[0]=0,n.set(t,1),n.length>65536)throw new E(`frame batch exceeds maximum plaintext size`);return n}let t=1;for(let n of e)t+=4+n.length;if(t>65536)throw new E(`frame batch exceeds maximum plaintext size`);let n=new Uint8Array(t);n[0]=1;let r=1;for(let t of e)n[r]=t.length>>>24&255,n[r+1]=t.length>>>16&255,n[r+2]=t.length>>>8&255,n[r+3]=t.length&255,r+=4,n.set(t,r),r+=t.length;return n},se=e=>{if(e.length<1)throw new E(`empty batch plaintext`);let t=e[0];if(t===0)return[e.slice(1)];if(t!==1)throw new E(`unknown batch container tag ${t}`);let n=[],r=1;for(;r<e.length;){if(r+4>e.length)throw new E(`truncated batch frame length`);let t=(e[r]<<24|e[r+1]<<16|e[r+2]<<8|e[r+3])>>>0;if(r+=4,r+t>e.length)throw new E(`truncated batch frame body`);n.push(e.slice(r,r+t)),r+=t}if(n.length===0)throw new E(`empty frame batch`);return n},ce=new Set([r.HttpBody,r.WsText,r.WsBinary]),le=e=>{let t=e.windowMs??150,n=e.maxBatchBytes??24576,r=e.maxBatchFrames??32,i=e.now??(()=>Date.now()),a=e.setTimer??((e,t)=>setTimeout(e,t)),o=e.clearTimer??(e=>clearTimeout(e)),s=[],c=0,l=null,u=0,d=!1,f=()=>{l!==null&&(o(l),l=null)},p=()=>{if(f(),s.length===0)return;let t=s;s=[],c=0,u=i(),e.sendBatch(oe(t))};return{enqueue:e=>{if(d)return;let o=e[0]&-129;if(!ce.has(o)){s.push(e),p();return}let f=i();if(s.length===0&&f-u>=t){s.push(e),p();return}let m=4+e.length;if(s.length>0&&1+c+m>65536&&p(),s.push(e),c+=m,c>=n||s.length>=r){p();return}l===null&&(l=a(p,t))},flush:p,dispose(){d=!0,f(),s=[],c=0}}},ue=()=>{let e=1;return{next(){if(e>T)throw new E(`stream id space exhausted`);let t=e;return e+=2,t}}},P=e=>typeof e==`object`&&!!e&&!Array.isArray(e),F=e=>P(e)&&Object.values(e).every(e=>typeof e==`string`),de=e=>P(e)&&typeof e.status==`number`&&F(e.headers),I=e=>P(e)&&typeof e.reason==`string`,fe=e=>P(e)&&typeof e.code==`number`&&typeof e.reason==`string`,pe=/^[a-z][a-z\d+.-]*:\/\//i,L=`http://tunnel.invalid`,me=e=>{try{let t=pe.test(e)?new URL(e):new URL(e,L);return`${t.pathname}${t.search}`}catch{return e}},R=e=>({async*[Symbol.asyncIterator](){yield e}}),he=e=>({async*[Symbol.asyncIterator](){let t=e.getReader();try{for(;;){let{done:e,value:n}=await t.read();if(e)return;n&&(yield n)}}finally{t.releaseLock()}}}),ge=e=>{let t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),t},_e=async e=>{if(e==null)return{body:null};if(e instanceof ReadableStream)return{body:he(e)};if(typeof e==`string`)return{body:R(new TextEncoder().encode(e))};if(e instanceof ArrayBuffer)return{body:R(new Uint8Array(e.slice(0)))};if(ArrayBuffer.isView(e))return{body:R(ge(e))};let t=new Response(e),n=t.headers.get(`content-type`)??void 0;return{body:R(new Uint8Array(await t.arrayBuffer())),contentType:n}},ve=async(e,t)=>{let n,r=new Headers,i=`GET`,a=null,o;e instanceof Request?(n=e.url,i=e.method,e.headers.forEach((e,t)=>r.set(t,e)),o=e.signal,a=e.body):n=e.toString(),t&&(t.method&&(i=t.method),t.headers&&new Headers(t.headers).forEach((e,t)=>r.set(t,e)),t.body!==void 0&&(a=t.body),t.signal&&(o=t.signal));let s=pe.test(n)?new URL(n):new URL(n,L),{body:c,contentType:l}=await _e(a);l&&!r.has(`content-type`)&&r.set(`content-type`,l);let u={};return r.forEach((e,t)=>{u[t]=e}),{method:i.toUpperCase(),path:s.pathname,query:s.search.startsWith(`?`)?s.search.slice(1):s.search,headers:u,body:c,signal:o}},ye=new Uint8Array,be=new TextEncoder,xe=new TextDecoder,z=e=>e instanceof Error?e:Error(String(e)),B=()=>new DOMException(`The operation was aborted.`,`AbortError`),Se=e=>{e.binaryType=`arraybuffer`;let t={get readyState(){return e.readyState},send(t){e.send(t)},close(t,n){e.close(t,n)},onopen:null,onmessage:null,onclose:null,onerror:null};return e.onopen=()=>t.onopen?.(),e.onmessage=e=>t.onmessage?.({data:e.data}),e.onclose=e=>t.onclose?.({code:e.code,reason:e.reason}),e.onerror=()=>t.onerror?.(),t},Ce=e=>{let t={get readyState(){return e.readyState},get binaryType(){return e.binaryType},set binaryType(t){t&&(e.binaryType=t)},onopen:null,onmessage:null,onerror:null,onclose:null,send(t){e.send(t)},close(t,n){e.close(t,n)}};return e.onopen=()=>t.onopen?.(),e.onmessage=e=>{let n=e.data;(typeof n==`string`||n instanceof ArrayBuffer)&&t.onmessage?.({data:n})},e.onerror=()=>t.onerror?.(),e.onclose=e=>t.onclose?.({code:e.code,reason:e.reason}),t},we=0,Te=1,Ee=2,De=3,Oe=new Set([o.AuthFailed,o.DuplicateClient,o.LimitExceeded]),ke={[o.AuthFailed]:`relay authentication failed`,[o.DuplicateClient]:`relay connection replaced by another client`,[o.LimitExceeded]:`relay connection limit reached`},Ae=()=>{let e=typeof navigator<`u`&&navigator.onLine===!1,t=typeof document<`u`&&document.visibilityState===`hidden`;return e||t},je=e=>{let t=e.helloRetryMs??1e3,n=e.helloTimeoutMs??3e4,i=e.pingIntervalMs??3e4,a=e.pingTimeoutMs??15e3,o=e.batchWindowMs??150,s=e.batch!==!1,c=e.reconnectBaseDelayMs??1e3,l=e.reconnectMaxDelayMs??3e4,u=e.hiddenOrOfflineMaxDelayMs??6e4,d=e.createWireSocket??(e=>Se(new WebSocket(e))),f=!1,p={state:`idle`},m=new Set,h=null,g=null,_=null,v=0,y=0,b=null,x=[],S=!1,C=e=>{if(p.state!==e.state||p.lastError!==e.lastError){p=e;for(let e of m)try{e(p)}catch{}}},w=e=>{let t=x;x=[];for(let n of t)n.reject(e)},ee=e=>{let t=x;x=[];for(let n of t)n.resolve(e)},te=(e,t)=>{e.dead=!0;let n=Array.from(e.streams.values());e.streams.clear();for(let e of n)try{e.fail(t)}catch{}},ne=()=>{b!==null&&(clearTimeout(b),b=null)},T=()=>{f||b===null||Ae()||(ne(),k(),P())},E=()=>{typeof document<`u`&&document.visibilityState===`visible`&&T()},O=()=>{S||typeof window>`u`||(S=!0,window.addEventListener(`online`,T),typeof document<`u`&&document.addEventListener(`visibilitychange`,E))},k=()=>{!S||typeof window>`u`||(S=!1,window.removeEventListener(`online`,T),typeof document<`u`&&document.removeEventListener(`visibilitychange`,E))},oe=()=>{if(f||b!==null)return;let e=Math.max(0,y-1),t=c*2**Math.min(e,10),n=Ae()?u:l,r=Math.min(n,t);O(),b=setTimeout(()=>{b=null,k(),P()},r)},ce=()=>{let t=new URL(e.relayUrl);return t.searchParams.set(`v`,`1`),t.searchParams.set(`role`,`client`),t.searchParams.set(`serverId`,e.serverId),e.grant&&t.searchParams.set(`grant`,e.grant),t.toString()},P=async()=>{if(f)return;ne(),v+=1;let c=v;C({state:y>0?`reconnecting`:`connecting`,lastError:p.lastError});let l;try{l=await re(e.hostEncPubJwk,{batch:s})}catch(e){if(c!==v||f)return;fe(c,z(e),!0);return}if(c!==v||f)return;let u;try{u=d(ce())}catch(e){fe(c,z(e));return}g=u;let m=!1,b=null,x=null,S=null,T=null,E=Promise.resolve(),O=null,k=null,A=!1,j=null,M=Date.now(),N=()=>{b!==null&&(clearInterval(b),b=null),x!==null&&(clearTimeout(x),x=null),S!==null&&(clearInterval(S),S=null),T!==null&&(clearTimeout(T),T=null),j!==null&&(j.dispose(),j=null)};_=N;function P(e,t=!1,n=!1){if(!(m||c!==v)){m=!0,N(),O&&(h=null,te(O,Error(`relay tunnel reset: ${e.message}`))),w(e);try{u.close()}catch{}if(g===u&&(g=null),!f){if(y+=1,n){C({state:`error`,lastError:e.message});return}C({state:t?`error`:`reconnecting`,lastError:e.message}),oe()}}}let F=()=>{try{u.send(l.helloText)}catch{}},de=(e,t)=>{k=e,A=t,b!==null&&(clearInterval(b),b=null),x!==null&&(clearTimeout(x),x=null);let n=new Map,s=ue(),c=ae(),l=Promise.resolve(),d=t=>{l=l.then(async()=>{if(p.dead)return;let n=await e.encryptor.encrypt(t);u.send(n)}).catch(()=>{})},f=t?le({windowMs:o,sendBatch:d}):null;j=f;let p={streams:n,assembler:c,nextStreamId:()=>s.next(),dead:!1,send(e){if(p.dead)return;let t=e[0]&-129;t!==r.Ping&&t!==r.Pong&&(M=Date.now()),f?f.enqueue(e):d(e)}};O=p,h=p,y=0,M=Date.now(),C({state:`connected`}),ee(p),S=setInterval(()=>{Date.now()-M<i||(p.send(D(r.Ping,0,ye)),T===null&&(T=setTimeout(()=>{T=null,P(Error(`relay keepalive timeout`))},a)))},i)},I=(e,t)=>{let n;try{n=ie(t)}catch(e){P(z(e));return}if(T!==null&&(clearTimeout(T),T=null),n.frameType===r.Ping){e.send(D(r.Pong,n.streamId,ye));return}if(n.frameType===r.Pong)return;M=Date.now();let i=n.payload;if(n.frameType===r.WsText||n.frameType===r.WsBinary){let t;try{t=e.assembler.push(n)}catch(e){P(z(e));return}if(t===null)return;i=t}else if(n.hasMoreFragments){P(Error(`unexpected fragmented tunnel frame`));return}let a=e.streams.get(n.streamId);a&&a.handleFrame(n.frameType,i)};u.onopen=()=>{m||c!==v||(F(),b=setInterval(F,t))},u.onmessage=e=>{if(m||c!==v)return;let t=e.data;if(typeof t==`string`){E=E.then(async()=>{if(m||c!==v)return;let e=await l.handleText(t);if(e.type===`established`){if(k)return;de(e.channel,e.batch)}else e.type===`fail`&&P(Error(`relay handshake failed: ${e.reason}`))}).catch(e=>{P(z(e))});return}let n=t instanceof ArrayBuffer?new Uint8Array(t):t instanceof Uint8Array?t:null;n&&(E=E.then(async()=>{if(m||c!==v)return;let e=O,t=k;if(!e||!t){P(Error(`encrypted frame before handshake completed`));return}let r;try{r=await t.decryptor.decrypt(n)}catch(e){P(z(e));return}if(A){let t;try{t=se(r)}catch(e){P(z(e));return}for(let n of t){if(m||c!==v||e.dead)return;I(e,n)}return}I(e,r)}).catch(e=>{P(z(e))}))},u.onclose=e=>{let t=Oe.has(e.code);P(Error(ke[e.code]??`relay socket closed (code ${e.code})`),t,t)},u.onerror=()=>{},x=setTimeout(()=>{x=null,P(Error(`relay handshake timeout`),!0)},n);function fe(e,t,n=!1){e!==v||f||(w(t),y+=1,C({state:n?`error`:`reconnecting`,lastError:t.message}),oe())}},F=e=>f?Promise.reject(Error(`relay tunnel closed`)):e?.aborted?Promise.reject(B()):h&&!h.dead?Promise.resolve(h):new Promise((t,n)=>{let r=null,i={resolve(n){r&&e&&e.removeEventListener(`abort`,r),t(n)},reject(t){r&&e&&e.removeEventListener(`abort`,r),n(t)}};e&&(r=()=>{x=x.filter(e=>e!==i),n(B())},e.addEventListener(`abort`,r,{once:!0})),x.push(i)}),pe=async(e,t)=>{let n=await ve(e,t),i=n.signal;if(i?.aborted)throw B();let a=await F(i),o=a.nextStreamId();return await new Promise((e,t)=>{let s=!1,c=!1,l=null,u=null,d=()=>{a.streams.delete(o),a.assembler.dropStream(o),u&&i&&i.removeEventListener(`abort`,u)},f=e=>{if(!c){if(c=!0,d(),!s){t(e);return}try{l?.error(e)}catch{}}},p=e=>{a.dead||a.send(D(r.StreamAbort,o,A({reason:e})))};u=()=>{p(`aborted`),f(B())},a.streams.set(o,{handleFrame(t,n){if(t===r.HttpResponse){if(s||c)return;let t;try{t=j(n,de)}catch(e){p(`malformed response head`),f(z(e));return}let r=t.status===204||t.status===205||t.status===304,i=null;r||(i=new ReadableStream({start(e){l=e},cancel(){c||(c=!0,d(),p(`response body cancelled`))}})),s=!0,e(new Response(i,{status:t.status,headers:t.headers})),r&&(c=!0,d());return}if(t===r.HttpBody){if(!s||c)return;try{l?.enqueue(n)}catch{}return}if(t===r.StreamEnd){if(c)return;if(!s){f(Error(`tunnel stream ended before response head`));return}c=!0,d();try{l?.close()}catch{}return}if(t===r.StreamAbort){let e=`stream aborted by host`;try{e=j(n,I).reason}catch{}f(Error(e))}},fail(e){f(e)}}),i&&i.addEventListener(`abort`,u,{once:!0});let m={method:n.method,path:n.path,query:n.query,headers:n.headers};a.send(D(r.HttpRequest,o,A(m))),(async()=>{try{if(n.body)for await(let e of n.body){if(c||a.dead)return;for(let t of M(e))a.send(D(r.HttpBody,o,t))}!c&&!a.dead&&a.send(D(r.StreamEnd,o,ye))}catch(e){p(`request body failed`),f(z(e))}})()})},L=e=>{let t=e.indexOf(`?`);return t===-1?{path:e,query:``}:{path:e.slice(0,t),query:e.slice(t+1)}};return P(),{fetch:pe,openWebSocket:(e,t,n)=>{let i=we,a=null,o=0,s=!1,c={get readyState(){return i},onopen:null,onmessage:null,onerror:null,onclose:null,send(e){if(i!==Te||!a||a.dead)throw Error(`relay tunnel socket is not open`);if(typeof e==`string`){for(let t of N(r.WsText,o,be.encode(e)))a.send(t);return}let t=e instanceof ArrayBuffer?new Uint8Array(e.slice(0)):(()=>{let t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e.buffer,e.byteOffset,e.byteLength)),t})();for(let e of N(r.WsBinary,o,t))a.send(e)},close(e=1e3,t=``){i!==De&&i!==Ee&&(i===Te&&a&&!a.dead&&(i=Ee,a.send(D(r.WsClose,o,A({code:e,reason:t})))),l(e,t))}},l=(e,t,n=!1)=>{if(!s){if(s=!0,a&&(a.streams.delete(o),a.assembler.dropStream(o)),i=De,n)try{c.onerror?.()}catch{}try{c.onclose?.({code:e,reason:t})}catch{}}};return(async()=>{let u;try{u=await F()}catch(e){l(1006,z(e).message,!0);return}if(s)return;a=u,o=u.nextStreamId(),u.streams.set(o,{handleFrame(e,t){if(e===r.WsOpened){if(i===we){i=Te;try{c.onopen?.()}catch{}}return}if(e===r.WsText){try{c.onmessage?.({data:xe.decode(t)})}catch{}return}if(e===r.WsBinary){let e=new ArrayBuffer(t.byteLength);new Uint8Array(e).set(t);try{c.onmessage?.({data:e})}catch{}return}if(e===r.WsClose){let e=1e3,n=``;try{let r=j(t,fe);e=r.code,n=r.reason}catch{}l(e,n);return}if(e===r.StreamAbort){let e=`stream aborted`;try{e=j(t,I).reason}catch{}l(1006,e,!0)}},fail(e){l(1012,e.message,!0)}});let{path:d,query:f}=L(e),p={path:d,query:f,...t&&t.length>0?{protocols:t}:{},...n&&Object.keys(n).length>0?{headers:n}:{}};u.send(D(r.WsOpen,o,A(p)))})(),c},getStatus:()=>p,subscribeStatus(e){return m.add(e),()=>{m.delete(e)}},close:()=>{if(f)return;f=!0,v+=1,ne(),k(),_?.(),_=null;let e=h;h=null;let t=Error(`relay tunnel closed`);e&&te(e,t),w(t);try{g?.close()}catch{}g=null,C({state:`idle`})}}},V=null,H=null,Me=(e,t)=>e.relayUrl===t.relayUrl&&e.serverId===t.serverId&&e.grant===t.grant&&JSON.stringify(e.hostEncPubJwk)===JSON.stringify(t.hostEncPubJwk),Ne=()=>V,Pe=()=>H,Fe=()=>V!==null,Ie=()=>V?.getStatus().state===`connected`,Le=e=>V&&H&&Me(H,e)?V:(V?.close(),H=e,V=je(e),V),Re=(e,t)=>{V!==t&&(V?.close(),H=e,V=t)},ze=()=>{V?.close(),V=null,H=null},Be=e({acquireRuntimeUrlAuthToken:()=>kt,beginRuntimeAuthEndpointSwitch:()=>ot,buildRuntimeAuthHeaders:()=>jt,clearRuntimeUrlAuthToken:()=>X,endRuntimeAuthEndpointSwitch:()=>st,getLocalRuntimeUrlAuthTokenSync:()=>_t,getRuntimeAuthGeneration:()=>Ge,getRuntimeBearerTokenSync:()=>Z,getRuntimeExtraHeadersSync:()=>ft,getRuntimeUrlAuthTokenSync:()=>gt,invalidateRuntimeAuthSession:()=>lt,refreshLocalRuntimeUrlAuthToken:()=>St,refreshRuntimeUrlAuthToken:()=>xt,setRuntimeBearerToken:()=>ut,setRuntimeExtraHeaders:()=>dt,setRuntimeUrlAuthToken:()=>pt,subscribeRuntimeAuthGeneration:()=>ct,subscribeRuntimeUrlAuthToken:()=>At}),Ve=()=>null,He=``,Ue={},U=``,W=0,G=null,K=``,q=0,J=null,Y=0,We=1e4,Ge=()=>Y,Ke=e=>e.toLowerCase()===`authorization`,qe=e=>{let t={};for(let[n,r]of Object.entries(e||{})){let e=n.trim(),i=r.trim();e&&i&&!Ke(e)&&(t[e]=i)}return t},Je=(e,t)=>{let n=Object.entries(e);return n.length===Object.keys(t).length&&n.every(([e,n])=>t[e]===n)},Ye=e=>typeof e==`string`?e.trim():``,Xe=()=>{if(typeof window>`u`)return``;let e=window.__OPENCHAMBER_CLIENT_TOKEN__;return Ye(e)},Ze=()=>{if(typeof window>`u`)return``;let e=window.__OPENCHAMBER_API_BASE_URL__;return typeof e==`string`?e.trim():``},Qe=(e,t)=>{let n=typeof e==`string`&&e.trim()?e.trim():Ze();if(!n)return t;try{return new URL(t,`${n.replace(/\/+$/,``)}/`).toString()}catch{return t}},X=()=>{U=``,W=0,K=``,q=0},$e=new Set,et=null,tt=0,nt=async e=>{let t=new TextEncoder().encode(e),n=await crypto.subtle.digest(`SHA-256`,t);return[...new Uint8Array(n)].map(e=>e.toString(16).padStart(2,`0`)).join(``)},rt=e=>{for(let t of $e)try{t(e)}catch{}},it=e=>e||(tt>0?`endpoint-switch`:`credential`),at=(e={})=>{let t=e.previousBearerDigest===void 0?et??void 0:e.previousBearerDigest||void 0;Y+=1,G=null,X(),Ot(),rt({generation:Y,reason:it(e.reason),...t?{previousBearerDigest:t}:{}})},ot=()=>{tt+=1},st=()=>{tt=Math.max(0,tt-1)},ct=e=>($e.add(e),()=>{$e.delete(e)}),lt=()=>{at({reason:`invalidate`})},ut=e=>{let t=Ye(e),n=t===Z(),r=et;He=t,Ve=()=>t?{type:`bearer`,token:t}:null,!n&&(et=null,at({previousBearerDigest:r}),t&&nt(t).then(e=>{Z()===t&&(et=e)}).catch(()=>void 0))},dt=e=>{let t=qe(e);Je(Ue,t)||(Ue=t,at({previousBearerDigest:null}))},ft=()=>{if(Object.keys(Ue).length>0)return Ue;if(typeof window>`u`)return{};let e=window.__OPENCHAMBER_RUNTIME_HEADERS__;return e&&typeof e==`object`?qe(e):{}},Z=()=>He||Xe(),pt=(e,t)=>{let n=Ye(e);if(!n||typeof t!=`number`||!Number.isFinite(t)){X();return}let r=U;U=n,W=t,r&&r!==n&&Et()},mt=()=>!U||W<=Date.now()+We?(X(),``):U,ht=()=>!K||q<=Date.now()+We?(K=``,q=0,``):K,gt=()=>{let e=mt();return!e&&(Z()||typeof window<`u`)&&xt().catch(()=>{}),e},_t=e=>{let t=ht();return!t&&e&&typeof window<`u`&&St(e).catch(()=>{}),t},vt=async()=>{let e=await Ve(),t=e?.type===`bearer`?Ye(e.token):Z();return t?{type:`bearer`,token:t}:null},yt=e=>{if(G)return G;let t=Y,n=(async()=>{let n=await vt(),r=new Headers;for(let[e,t]of Object.entries(ft()))r.set(e,t);n?.type===`bearer`&&r.set(`Authorization`,`Bearer ${n.token}`);let i=Ne(),a=i?await i.fetch(`/auth/url-token`,{method:`POST`,headers:r}):await fetch(Qe(e,`/auth/url-token`),{method:`POST`,headers:r,credentials:`include`});if(!a.ok)throw t===Y&&X(),Error(`Failed to mint runtime URL auth token (${a.status})`);let o=await a.json().catch(()=>null),s=typeof o?.token==`string`?o.token.trim():``,c=typeof o?.expiresAt==`number`?o.expiresAt:0;if(t!==Y)throw Error(`Runtime URL auth token response is stale`);if(pt(s,c),!U)throw Error(`Runtime URL auth token response was invalid`);return U})().finally(()=>{G===n&&(G=null)});return G=n,G},bt=e=>{if(J)return J;let t=(async()=>{let t=await fetch(Qe(e,`/auth/url-token`),{method:`POST`,credentials:`include`});if(!t.ok)throw K=``,q=0,Error(`Failed to mint local runtime URL auth token (${t.status})`);let n=await t.json().catch(()=>null),r=typeof n?.token==`string`?n.token.trim():``,i=typeof n?.expiresAt==`number`?n.expiresAt:0;if(!r||!Number.isFinite(i))throw Error(`Local runtime URL auth token response was invalid`);return K=r,q=i,r})().finally(()=>{J===t&&(J=null)});return J=t,J},xt=async e=>mt()||yt(e),St=async e=>ht()||bt(e),Q=0,$=null,Ct=null,wt=new Set,Tt=5e3,Et=()=>{for(let e of wt)try{e()}catch{}},Dt=()=>{$!==null&&(clearTimeout($),$=null)},Ot=()=>{if(Dt(),Q<=0||typeof window>`u`)return;let e=W-We-Tt,t=W>0?Math.max(0,e-Date.now()):0;$=setTimeout(()=>{$=null,!(Q<=0)&&yt(Ct).catch(()=>{}).finally(()=>{Ot()})},t)},kt=e=>{typeof e==`string`&&e.trim()&&(Ct=e.trim()),Q+=1,Ot();let t=!1;return()=>{t||(t=!0,Q=Math.max(0,Q-1),Q===0&&Dt())}},At=e=>(wt.add(e),()=>{wt.delete(e)}),jt=async e=>{let t=new Headers(e);for(let[e,n]of Object.entries(ft()))t.has(e)||t.set(e,n);if(t.has(`Authorization`))return t;let n=await vt();return n?.type===`bearer`&&t.set(`Authorization`,`Bearer ${n.token}`),t};export{Ne as C,Ce as D,je as E,L as O,Pe as S,Ie as T,ct as _,st as a,Re as b,Z as c,lt as d,St as f,dt as g,ut as h,X as i,me as k,ft as l,Be as m,ot as n,_t as o,xt as p,jt as r,Ge as s,kt as t,gt as u,At as v,Fe as w,ze as x,Le as y};
|