@openchambery/web 1.18.2-beta.6 → 1.18.2-beta.8
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-B2kZjgaf.js → AgentAvatar-BzRb9sP6.js} +1 -1
- package/dist/assets/{AssistantView-COiivQyD.js → AssistantView-C0v6WVEB.js} +1 -1
- package/dist/assets/{ChatContainer-CNQBw5D7.js → ChatContainer-CReoQTua.js} +12 -12
- package/dist/assets/{DiagramView-DD5haMGO.js → DiagramView-D_WMXwYz.js} +1 -1
- package/dist/assets/{FadeInOnReveal-aeWlaqVB.js → FadeInOnReveal-oeyB_nIi.js} +1 -1
- package/dist/assets/{Icon-AXqa-fYB.js → Icon-DHaR0peD.js} +1 -1
- package/dist/assets/{MarkdownRendererImpl-CY3U2y5M.js → MarkdownRendererImpl-DhYt2Oq2.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-B8rygQQ7.js → MobileDetailNavigation-CgiLWb4L.js} +1 -1
- package/dist/assets/{MobileShareBridge-D89lMfZL.js → MobileShareBridge-CED5MFr5.js} +1 -1
- package/dist/assets/{MobileSurface-3Tv0F4Gr.js → MobileSurface-CH2_uvbK.js} +1 -1
- package/dist/assets/{MultiRunWindow-B9WbE8t-.js → MultiRunWindow-BUsyw0Ws.js} +1 -1
- package/dist/assets/{OnboardingScreen-DiPnIwza.js → OnboardingScreen-BZHN7C2r.js} +1 -1
- package/dist/assets/{OverlayScrollbar-B9JI2aL-.js → OverlayScrollbar-DP76aSig.js} +1 -1
- package/dist/assets/{SettingsView-CZIFnaZD.js → SettingsView-BkC2EjbS.js} +1 -1
- package/dist/assets/{SettingsWindow-5vXhJPxQ.js → SettingsWindow-CAW6MEmX.js} +1 -1
- package/dist/assets/{TerminalView-BxbGHB90.js → TerminalView-BlHms0VM.js} +1 -1
- package/dist/assets/{ToolOutputDialog-CeNm90zz.js → ToolOutputDialog-C6tIj91N.js} +1 -1
- package/dist/assets/{appThemeRegistry-CaSmAsn0.js → appThemeRegistry-DVSq4EWU.js} +2 -2
- package/dist/assets/{button-CDvMVaiO.js → button-DCUMIXDC.js} +1 -1
- package/dist/assets/{clipboard-CbqhDr1g.js → clipboard-DF5tFLDb.js} +1 -1
- package/dist/assets/{collapsible-C2aamDvD.js → collapsible-DNg5bLKV.js} +1 -1
- package/dist/assets/{context-menu-CWpj9MM3.js → context-menu-DpH6U8oW.js} +1 -1
- package/dist/assets/{desktopHosts-CBoBpJ1Z.js → desktopHosts-DSgGxDpI.js} +1 -1
- package/dist/assets/{desktopRelayRestore-l2R9muux.js → desktopRelayRestore-DVIx7jsz.js} +1 -1
- package/dist/assets/{diagram-CEon0BQs.js → diagram-cjvFqVa8.js} +1 -1
- package/dist/assets/{dialog--cf4dygO.js → dialog-DaSIYgrj.js} +1 -1
- package/dist/assets/{fileQueries-CE_DaZWQ.js → fileQueries-DXvhIL_U.js} +1 -1
- package/dist/assets/{gitApi-DOg904nv.js → gitApi-Bhdx5iUS.js} +1 -1
- package/dist/assets/gitApiHttp-SLrnr8a5.js +2 -0
- package/dist/assets/{input-k9DGGyZ6.js → input-QS3IWgY5.js} +1 -1
- package/dist/assets/{insertionBoundaries-CVlbmHxP.js → insertionBoundaries-nU86u9Wm.js} +1 -1
- package/dist/assets/{main-BPqbCeMO.js → main-B1xvOgYh.js} +4 -4
- package/dist/assets/{main-Co94kWxG.js → main-CE-WJrYW.js} +2 -2
- package/dist/assets/{markdown-worker-DkeWiER6.js → markdown-worker-D-OR2e_G.js} +1 -1
- package/dist/assets/{markdownTheme-DNT93i5L.js → markdownTheme-y_Rf6mLa.js} +1 -1
- package/dist/assets/{miniChat-CXKdmXX8.js → miniChat-BFIjJLav.js} +2 -2
- package/dist/assets/mobile-CAhmWqvi.js +2 -0
- package/dist/assets/{multirun-CImSf28y.js → multirun-CgvZwd2c.js} +1 -1
- package/dist/assets/{persistence-DPNMIbF5.js → persistence-oSFWyKgV.js} +1 -1
- package/dist/assets/{projectMeta-CjjJoGW4.js → projectMeta-1-jW5f2j.js} +1 -1
- package/dist/assets/{radio-D7GqsVKG.js → radio-B8jlOicg.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-TowM-DTY.js → renderElectronMiniChatApp-B99BmjcT.js} +2 -2
- package/dist/assets/{renderMobileApp-BTK6u8V7.js → renderMobileApp-Dk7PNioy.js} +4 -4
- package/dist/assets/{runtimeConfig-BtWi74Pm.js → runtimeConfig-n4QAk1lU.js} +1 -1
- package/dist/assets/runtimeEndpointReset-Ca3v4eoA.js +145 -0
- package/dist/assets/{sortable-tabs-strip-9_5pMDEx.js → sortable-tabs-strip-D2vXQoD8.js} +1 -1
- package/dist/assets/{src-D5csxl6e.css → src-BhvNwAr-.css} +1 -1
- package/dist/assets/{terminalApi-tB3qLcfa.js → terminalApi-_NnfkxgP.js} +1 -1
- package/dist/assets/{tooltip-DMNR5rN0.js → tooltip-xEnco9xY.js} +1 -1
- package/dist/assets/{url-7MqoLs9X.js → url-DIZgk80M.js} +1 -1
- package/dist/assets/{useAppFontEffects-BbPkX7Aa.js → useAppFontEffects-CFXV7nrE.js} +2 -2
- package/dist/assets/{useDesktopWindowControlsLayout-Ddw59AGl.js → useDesktopWindowControlsLayout-BN0ppWAs.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-tjzwKLjA.js → useEffectiveDirectory-DGlRozSn.js} +1 -1
- package/dist/assets/{useFontPreferences-CIurCeNv.js → useFontPreferences-B-QHyR3C.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-BWxbxrxb.js → useMobileNavigationStore-BUsW7lSl.js} +19 -18
- package/dist/assets/{useSessionAutoCleanup-Bclq-U-4.js → useSessionAutoCleanup-BRoQwvvb.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-Dv7-ZKa9.js → useWorkerHighlightedLines-Ds6gLNsj.js} +1 -1
- package/dist/assets/{utils-Co19EJEL.js → utils-Dxsi3J3l.js} +1 -1
- package/dist/index.html +8 -8
- package/dist/mini-chat.html +8 -8
- package/dist/mobile.html +8 -8
- package/package.json +1 -1
- package/server/lib/event-stream/DOCUMENTATION.md +2 -2
- package/server/lib/event-stream/diff-summary.js +35 -16
- package/server/lib/event-stream/diff-summary.test.js +46 -6
- package/server/lib/event-stream/protocol.test.js +7 -7
- package/server/lib/opencode/DOCUMENTATION.md +1 -1
- package/server/lib/opencode/feature-routes-runtime.test.js +10 -1
- package/server/lib/session-turn-pages/DOCUMENTATION.md +26 -6
- package/server/lib/session-turn-pages/changes.service.js +156 -0
- package/server/lib/session-turn-pages/changes.service.test.js +188 -0
- package/server/lib/session-turn-pages/reconcile.routes.test.js +48 -0
- package/server/lib/session-turn-pages/reconcile.service.js +3 -1
- package/server/lib/session-turn-pages/reconcile.service.test.js +40 -0
- package/server/lib/session-turn-pages/routes.js +273 -12
- package/server/lib/session-turn-pages/routes.test.js +359 -0
- package/server/lib/session-turn-pages/service.js +29 -7
- package/server/lib/session-turn-pages/service.test.js +30 -0
- package/dist/assets/gitApiHttp-D8j1qRH4.js +0 -2
- package/dist/assets/mobile-CTRPt2_t.js +0 -2
- package/dist/assets/runtimeEndpointReset-B0Ql9ZN6.js +0 -145
|
@@ -320,6 +320,99 @@ describe('registerSessionTurnPageRoutes', () => {
|
|
|
320
320
|
expect(part.state.output).toBeUndefined();
|
|
321
321
|
});
|
|
322
322
|
|
|
323
|
+
it('projects message summary.diffs to L1 count/marker before serializing a turn-page response', async () => {
|
|
324
|
+
const patch = 'diff-body-'.repeat(20_000);
|
|
325
|
+
const loadPage = vi.fn(async () => ({
|
|
326
|
+
ok: true,
|
|
327
|
+
records: [{
|
|
328
|
+
info: {
|
|
329
|
+
id: 'msg_u1',
|
|
330
|
+
role: 'user',
|
|
331
|
+
summary: {
|
|
332
|
+
diffs: [{
|
|
333
|
+
file: 'src/large.ts',
|
|
334
|
+
status: 'modified',
|
|
335
|
+
additions: 9,
|
|
336
|
+
deletions: 3,
|
|
337
|
+
patch,
|
|
338
|
+
}],
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
parts: [],
|
|
342
|
+
}],
|
|
343
|
+
turnCount: 1,
|
|
344
|
+
cursor: null,
|
|
345
|
+
complete: true,
|
|
346
|
+
}));
|
|
347
|
+
const { app, route } = registry();
|
|
348
|
+
registerSessionTurnPageRoutes(app, { sessionTurnPageService: { loadPage } });
|
|
349
|
+
const res = response();
|
|
350
|
+
|
|
351
|
+
await route('GET', ROUTE)({
|
|
352
|
+
params: { sessionID: 'ses_1' },
|
|
353
|
+
query: { turns: '3' },
|
|
354
|
+
headers: {},
|
|
355
|
+
}, res);
|
|
356
|
+
|
|
357
|
+
expect(res.statusCode).toBe(200);
|
|
358
|
+
expect(res.body.records[0].info.summary).toEqual({
|
|
359
|
+
diffCount: 1,
|
|
360
|
+
hasDiffs: true,
|
|
361
|
+
});
|
|
362
|
+
expect(res.body.records[0].info.summary.diffs).toBeUndefined();
|
|
363
|
+
expect(JSON.stringify(res.body)).not.toContain(patch);
|
|
364
|
+
expect(JSON.stringify(res.body)).not.toContain('src/large.ts');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('keeps L1 turn-page serialization under 64KiB for a 463-file / ~14MB patch summary', async () => {
|
|
368
|
+
const patchBody = 'P'.repeat(Math.floor((14 * 1024 * 1024) / 463));
|
|
369
|
+
const diffs = Array.from({ length: 463 }, (_, i) => ({
|
|
370
|
+
file: `src/generated/file-${i}.ts`,
|
|
371
|
+
status: 'modified',
|
|
372
|
+
additions: i % 7,
|
|
373
|
+
deletions: i % 3,
|
|
374
|
+
patch: `${patchBody}-${i}`,
|
|
375
|
+
before: `before-${i}`,
|
|
376
|
+
after: `after-${i}`,
|
|
377
|
+
}));
|
|
378
|
+
const loadPage = vi.fn(async () => ({
|
|
379
|
+
ok: true,
|
|
380
|
+
records: [{
|
|
381
|
+
info: {
|
|
382
|
+
id: 'msg_huge',
|
|
383
|
+
role: 'user',
|
|
384
|
+
summary: { title: 'huge', diffs },
|
|
385
|
+
},
|
|
386
|
+
parts: [{ id: 'prt_1', type: 'text', text: 'ok' }],
|
|
387
|
+
}],
|
|
388
|
+
turnCount: 1,
|
|
389
|
+
cursor: null,
|
|
390
|
+
complete: true,
|
|
391
|
+
}));
|
|
392
|
+
const { app, route } = registry();
|
|
393
|
+
registerSessionTurnPageRoutes(app, { sessionTurnPageService: { loadPage } });
|
|
394
|
+
const res = response();
|
|
395
|
+
|
|
396
|
+
await route('GET', ROUTE)({
|
|
397
|
+
params: { sessionID: 'ses_huge' },
|
|
398
|
+
query: { turns: '1' },
|
|
399
|
+
headers: {},
|
|
400
|
+
}, res);
|
|
401
|
+
|
|
402
|
+
expect(res.statusCode).toBe(200);
|
|
403
|
+
const serialized = JSON.stringify(res.body);
|
|
404
|
+
expect(res.body.records[0].info.summary).toEqual({
|
|
405
|
+
title: 'huge',
|
|
406
|
+
diffCount: 463,
|
|
407
|
+
hasDiffs: true,
|
|
408
|
+
});
|
|
409
|
+
expect(res.body.records[0].info.summary.diffs).toBeUndefined();
|
|
410
|
+
expect(serialized).not.toContain('"diffs"');
|
|
411
|
+
expect(serialized).not.toContain(patchBody.slice(0, 64));
|
|
412
|
+
expect(serialized).not.toContain('src/generated/file-0.ts');
|
|
413
|
+
expect(Buffer.byteLength(serialized, 'utf8')).toBeLessThan(64 * 1024);
|
|
414
|
+
});
|
|
415
|
+
|
|
323
416
|
it('projects file parts on first packet and prepend the same way', async () => {
|
|
324
417
|
const png = Buffer.concat([
|
|
325
418
|
Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]),
|
|
@@ -479,3 +572,269 @@ describe('registerSessionTurnPageRoutes', () => {
|
|
|
479
572
|
await pending;
|
|
480
573
|
});
|
|
481
574
|
});
|
|
575
|
+
|
|
576
|
+
const EXACT_MESSAGE_ROUTE = '/api/session/:sessionID/message/:messageID';
|
|
577
|
+
const CHANGES_ROUTE = '/api/openchamber/sessions/:sessionID/changes';
|
|
578
|
+
|
|
579
|
+
describe('registerSessionTurnPageRoutes — exact message GET', () => {
|
|
580
|
+
it('registers GET /api/session/:sessionID/message/:messageID', () => {
|
|
581
|
+
const { app, route } = registry();
|
|
582
|
+
registerSessionTurnPageRoutes(app, {
|
|
583
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
584
|
+
fetchExactMessage: vi.fn(),
|
|
585
|
+
});
|
|
586
|
+
expect(route('GET', EXACT_MESSAGE_ROUTE)).toEqual(expect.any(Function));
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
it('returns original message shape with L1 summary projection only', async () => {
|
|
590
|
+
const patch = '@@ huge @@\n' + 'x'.repeat(2000);
|
|
591
|
+
const fetchExactMessage = vi.fn(async () => ({
|
|
592
|
+
info: {
|
|
593
|
+
id: 'msg_1',
|
|
594
|
+
role: 'user',
|
|
595
|
+
summary: {
|
|
596
|
+
title: 'turn',
|
|
597
|
+
diffs: [{
|
|
598
|
+
file: 'a.ts',
|
|
599
|
+
status: 'modified',
|
|
600
|
+
additions: 2,
|
|
601
|
+
deletions: 1,
|
|
602
|
+
patch,
|
|
603
|
+
}],
|
|
604
|
+
},
|
|
605
|
+
},
|
|
606
|
+
parts: [{ id: 'prt_1', type: 'text', text: 'hello' }],
|
|
607
|
+
}));
|
|
608
|
+
const { app, route } = registry();
|
|
609
|
+
registerSessionTurnPageRoutes(app, {
|
|
610
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
611
|
+
fetchExactMessage,
|
|
612
|
+
});
|
|
613
|
+
const res = response();
|
|
614
|
+
|
|
615
|
+
await route('GET', EXACT_MESSAGE_ROUTE)({
|
|
616
|
+
params: { sessionID: 'ses_1', messageID: 'msg_1' },
|
|
617
|
+
query: { directory: '/repo' },
|
|
618
|
+
headers: {},
|
|
619
|
+
}, res);
|
|
620
|
+
|
|
621
|
+
expect(res.statusCode).toBe(200);
|
|
622
|
+
expect(fetchExactMessage).toHaveBeenCalledWith(expect.objectContaining({
|
|
623
|
+
sessionID: 'ses_1',
|
|
624
|
+
messageID: 'msg_1',
|
|
625
|
+
directory: '/repo',
|
|
626
|
+
}));
|
|
627
|
+
expect(res.body).toEqual({
|
|
628
|
+
info: {
|
|
629
|
+
id: 'msg_1',
|
|
630
|
+
role: 'user',
|
|
631
|
+
summary: {
|
|
632
|
+
title: 'turn',
|
|
633
|
+
diffCount: 1,
|
|
634
|
+
hasDiffs: true,
|
|
635
|
+
},
|
|
636
|
+
},
|
|
637
|
+
parts: [{ id: 'prt_1', type: 'text', text: 'hello' }],
|
|
638
|
+
});
|
|
639
|
+
expect(JSON.stringify(res.body)).not.toContain(patch);
|
|
640
|
+
expect(JSON.stringify(res.body)).not.toContain('a.ts');
|
|
641
|
+
});
|
|
642
|
+
|
|
643
|
+
it('rejects oversize messageID / sessionID with 400', async () => {
|
|
644
|
+
const fetchExactMessage = vi.fn();
|
|
645
|
+
const { app, route } = registry();
|
|
646
|
+
registerSessionTurnPageRoutes(app, {
|
|
647
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
648
|
+
fetchExactMessage,
|
|
649
|
+
});
|
|
650
|
+
const handler = route('GET', EXACT_MESSAGE_ROUTE);
|
|
651
|
+
|
|
652
|
+
const oversize = 'm'.repeat(513);
|
|
653
|
+
const res = response();
|
|
654
|
+
await handler({
|
|
655
|
+
params: { sessionID: 'ses_1', messageID: oversize },
|
|
656
|
+
query: {},
|
|
657
|
+
headers: {},
|
|
658
|
+
}, res);
|
|
659
|
+
expect(res.statusCode).toBe(400);
|
|
660
|
+
expect(res.body.code).toBe('invalid_message');
|
|
661
|
+
expect(fetchExactMessage).not.toHaveBeenCalled();
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
it('maps not_found to HTTP 404', async () => {
|
|
665
|
+
const fetchExactMessage = vi.fn(async () => {
|
|
666
|
+
const error = new Error('not_found');
|
|
667
|
+
error.code = 'not_found';
|
|
668
|
+
throw error;
|
|
669
|
+
});
|
|
670
|
+
const { app, route } = registry();
|
|
671
|
+
registerSessionTurnPageRoutes(app, {
|
|
672
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
673
|
+
fetchExactMessage,
|
|
674
|
+
});
|
|
675
|
+
const res = response();
|
|
676
|
+
await route('GET', EXACT_MESSAGE_ROUTE)({
|
|
677
|
+
params: { sessionID: 'ses_1', messageID: 'msg_missing' },
|
|
678
|
+
query: {},
|
|
679
|
+
headers: {},
|
|
680
|
+
}, res);
|
|
681
|
+
expect(res.statusCode).toBe(404);
|
|
682
|
+
expect(res.body.code).toBe('not_found');
|
|
683
|
+
});
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
describe('registerSessionTurnPageRoutes — changes API', () => {
|
|
687
|
+
it('registers GET /api/openchamber/sessions/:sessionID/changes', () => {
|
|
688
|
+
const { app, route } = registry();
|
|
689
|
+
registerSessionTurnPageRoutes(app, {
|
|
690
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
691
|
+
sessionChangesService: { loadChanges: vi.fn() },
|
|
692
|
+
});
|
|
693
|
+
expect(route('GET', CHANGES_ROUTE)).toEqual(expect.any(Function));
|
|
694
|
+
});
|
|
695
|
+
|
|
696
|
+
it('returns L2 file list without patch bodies when file is omitted', async () => {
|
|
697
|
+
const loadChanges = vi.fn(async () => ({
|
|
698
|
+
ok: true,
|
|
699
|
+
body: {
|
|
700
|
+
files: [{
|
|
701
|
+
file: 'src/a.ts',
|
|
702
|
+
status: 'modified',
|
|
703
|
+
additions: 3,
|
|
704
|
+
deletions: 1,
|
|
705
|
+
}],
|
|
706
|
+
},
|
|
707
|
+
}));
|
|
708
|
+
const { app, route } = registry();
|
|
709
|
+
registerSessionTurnPageRoutes(app, {
|
|
710
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
711
|
+
sessionChangesService: { loadChanges },
|
|
712
|
+
});
|
|
713
|
+
const res = response();
|
|
714
|
+
|
|
715
|
+
await route('GET', CHANGES_ROUTE)({
|
|
716
|
+
params: { sessionID: 'ses_1' },
|
|
717
|
+
query: { messageID: 'msg_1', directory: '/repo' },
|
|
718
|
+
headers: {},
|
|
719
|
+
}, res);
|
|
720
|
+
|
|
721
|
+
expect(res.statusCode).toBe(200);
|
|
722
|
+
expect(loadChanges).toHaveBeenCalledWith(expect.objectContaining({
|
|
723
|
+
sessionID: 'ses_1',
|
|
724
|
+
messageID: 'msg_1',
|
|
725
|
+
directory: '/repo',
|
|
726
|
+
file: undefined,
|
|
727
|
+
}));
|
|
728
|
+
expect(res.body).toEqual({
|
|
729
|
+
files: [{
|
|
730
|
+
file: 'src/a.ts',
|
|
731
|
+
status: 'modified',
|
|
732
|
+
additions: 3,
|
|
733
|
+
deletions: 1,
|
|
734
|
+
}],
|
|
735
|
+
});
|
|
736
|
+
expect(JSON.stringify(res.body)).not.toContain('patch');
|
|
737
|
+
expect(res.body.info).toBeUndefined();
|
|
738
|
+
expect(res.body.parts).toBeUndefined();
|
|
739
|
+
});
|
|
740
|
+
|
|
741
|
+
it('returns L3 single-file diff when file is provided', async () => {
|
|
742
|
+
const loadChanges = vi.fn(async () => ({
|
|
743
|
+
ok: true,
|
|
744
|
+
body: {
|
|
745
|
+
diff: {
|
|
746
|
+
file: 'src/a.ts',
|
|
747
|
+
status: 'modified',
|
|
748
|
+
additions: 3,
|
|
749
|
+
deletions: 1,
|
|
750
|
+
patch: '@@ -1 +1 @@\n+line',
|
|
751
|
+
},
|
|
752
|
+
},
|
|
753
|
+
}));
|
|
754
|
+
const { app, route } = registry();
|
|
755
|
+
registerSessionTurnPageRoutes(app, {
|
|
756
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
757
|
+
sessionChangesService: { loadChanges },
|
|
758
|
+
});
|
|
759
|
+
const res = response();
|
|
760
|
+
|
|
761
|
+
await route('GET', CHANGES_ROUTE)({
|
|
762
|
+
params: { sessionID: 'ses_1' },
|
|
763
|
+
query: { messageID: 'msg_1', file: 'src/a.ts' },
|
|
764
|
+
headers: {},
|
|
765
|
+
}, res);
|
|
766
|
+
|
|
767
|
+
expect(res.statusCode).toBe(200);
|
|
768
|
+
expect(loadChanges).toHaveBeenCalledWith(expect.objectContaining({
|
|
769
|
+
file: 'src/a.ts',
|
|
770
|
+
}));
|
|
771
|
+
expect(res.body.diff.file).toBe('src/a.ts');
|
|
772
|
+
expect(res.body.diff.patch).toContain('+line');
|
|
773
|
+
expect(res.body.files).toBeUndefined();
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
it('rejects missing messageID and control-character file with 400', async () => {
|
|
777
|
+
const loadChanges = vi.fn();
|
|
778
|
+
const { app, route } = registry();
|
|
779
|
+
registerSessionTurnPageRoutes(app, {
|
|
780
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
781
|
+
sessionChangesService: { loadChanges },
|
|
782
|
+
});
|
|
783
|
+
const handler = route('GET', CHANGES_ROUTE);
|
|
784
|
+
|
|
785
|
+
const missing = response();
|
|
786
|
+
await handler({
|
|
787
|
+
params: { sessionID: 'ses_1' },
|
|
788
|
+
query: {},
|
|
789
|
+
headers: {},
|
|
790
|
+
}, missing);
|
|
791
|
+
expect(missing.statusCode).toBe(400);
|
|
792
|
+
expect(missing.body.code).toBe('invalid_message');
|
|
793
|
+
|
|
794
|
+
const badFile = response();
|
|
795
|
+
await handler({
|
|
796
|
+
params: { sessionID: 'ses_1' },
|
|
797
|
+
query: { messageID: 'msg_1', file: 'src/\0evil.ts' },
|
|
798
|
+
headers: {},
|
|
799
|
+
}, badFile);
|
|
800
|
+
expect(badFile.statusCode).toBe(400);
|
|
801
|
+
expect(badFile.body.code).toBe('invalid_file');
|
|
802
|
+
expect(loadChanges).not.toHaveBeenCalled();
|
|
803
|
+
});
|
|
804
|
+
|
|
805
|
+
it('maps change_not_found to HTTP 404 with stable code', async () => {
|
|
806
|
+
const loadChanges = vi.fn(async () => ({ ok: false, error: 'change_not_found' }));
|
|
807
|
+
const { app, route } = registry();
|
|
808
|
+
registerSessionTurnPageRoutes(app, {
|
|
809
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
810
|
+
sessionChangesService: { loadChanges },
|
|
811
|
+
});
|
|
812
|
+
const res = response();
|
|
813
|
+
await route('GET', CHANGES_ROUTE)({
|
|
814
|
+
params: { sessionID: 'ses_1' },
|
|
815
|
+
query: { messageID: 'msg_1', file: 'missing.ts' },
|
|
816
|
+
headers: {},
|
|
817
|
+
}, res);
|
|
818
|
+
expect(res.statusCode).toBe(404);
|
|
819
|
+
expect(res.body).toEqual({
|
|
820
|
+
error: 'change file not found',
|
|
821
|
+
code: 'change_not_found',
|
|
822
|
+
});
|
|
823
|
+
});
|
|
824
|
+
|
|
825
|
+
it('maps aborted to HTTP 499', async () => {
|
|
826
|
+
const loadChanges = vi.fn(async () => ({ ok: false, error: 'aborted' }));
|
|
827
|
+
const { app, route } = registry();
|
|
828
|
+
registerSessionTurnPageRoutes(app, {
|
|
829
|
+
sessionTurnPageService: { loadPage: vi.fn() },
|
|
830
|
+
sessionChangesService: { loadChanges },
|
|
831
|
+
});
|
|
832
|
+
const res = response();
|
|
833
|
+
await route('GET', CHANGES_ROUTE)({
|
|
834
|
+
params: { sessionID: 'ses_1' },
|
|
835
|
+
query: { messageID: 'msg_1' },
|
|
836
|
+
headers: {},
|
|
837
|
+
}, res);
|
|
838
|
+
expect(res.statusCode).toBe(499);
|
|
839
|
+
});
|
|
840
|
+
});
|
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* (true only when nothing older was trimmed from the scanned window).
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import { projectMessageSummaryDiffCounts } from '../event-stream/diff-summary.js';
|
|
20
|
+
|
|
19
21
|
const ASSISTANT_SESSION_DIVIDER_PREFIX = 'oc_asst_session_divider:';
|
|
20
22
|
|
|
21
23
|
const DEFAULT_MAX_SCAN_PAGES = 50;
|
|
@@ -457,22 +459,42 @@ const isUserRecord = (record) => {
|
|
|
457
459
|
};
|
|
458
460
|
|
|
459
461
|
/**
|
|
460
|
-
*
|
|
461
|
-
*
|
|
462
|
+
* L1: project message `summary.diffs` arrays to `{ diffCount, hasDiffs }` and
|
|
463
|
+
* remove the file array. Preserves every other message / summary field.
|
|
464
|
+
*/
|
|
465
|
+
export const projectMessageDiffSummaries = (records) => {
|
|
466
|
+
if (!Array.isArray(records) || records.length === 0) return records;
|
|
467
|
+
|
|
468
|
+
let changedAny = false;
|
|
469
|
+
const projected = records.map((record) => {
|
|
470
|
+
if (!record || typeof record !== 'object') return record;
|
|
471
|
+
const info = projectMessageSummaryDiffCounts(record.info);
|
|
472
|
+
if (info === record.info) return record;
|
|
473
|
+
changedAny = true;
|
|
474
|
+
return { ...record, info };
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
return changedAny ? projected : records;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Summarize message diff snapshots and tool/reasoning parts so a first packet
|
|
482
|
+
* does not have to carry bodies from a long tool-heavy turn.
|
|
462
483
|
*
|
|
463
484
|
* Runs after `selectTurnRecords`, so `turnCount`, `complete`, and cursor
|
|
464
|
-
* encoding are all derived from unprojected records and cannot shift. User
|
|
465
|
-
*
|
|
485
|
+
* encoding are all derived from unprojected records and cannot shift. User and
|
|
486
|
+
* assistant text pass through untouched, and records that gain nothing from
|
|
466
487
|
* projection keep their original object reference.
|
|
467
488
|
*
|
|
468
489
|
* @param {unknown[]} records
|
|
469
490
|
* @returns {unknown[]}
|
|
470
491
|
*/
|
|
471
492
|
export const projectSlimParts = (records) => {
|
|
472
|
-
|
|
493
|
+
const summaryProjected = projectMessageDiffSummaries(records);
|
|
494
|
+
if (!Array.isArray(summaryProjected) || summaryProjected.length === 0) return summaryProjected;
|
|
473
495
|
|
|
474
496
|
let changedAny = false;
|
|
475
|
-
const projected =
|
|
497
|
+
const projected = summaryProjected.map((record) => {
|
|
476
498
|
if (!record || typeof record !== 'object') return record;
|
|
477
499
|
const userRow = isUserRecord(record);
|
|
478
500
|
|
|
@@ -503,7 +525,7 @@ export const projectSlimParts = (records) => {
|
|
|
503
525
|
return { ...record, parts: nextParts };
|
|
504
526
|
});
|
|
505
527
|
|
|
506
|
-
return changedAny ? projected :
|
|
528
|
+
return changedAny ? projected : summaryProjected;
|
|
507
529
|
};
|
|
508
530
|
|
|
509
531
|
const countAuthoredBoundaries = (records) =>
|
|
@@ -172,6 +172,36 @@ describe('projectSlimParts', () => {
|
|
|
172
172
|
},
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
+
it('projects message summary.diffs to L1 count/marker even when parts are empty', () => {
|
|
176
|
+
const patch = 'diff-body-'.repeat(20_000);
|
|
177
|
+
const [projected] = projectSlimParts([{
|
|
178
|
+
info: {
|
|
179
|
+
id: 'msg_diff',
|
|
180
|
+
role: 'user',
|
|
181
|
+
summary: {
|
|
182
|
+
title: 'kept',
|
|
183
|
+
diffs: [{
|
|
184
|
+
file: 'src/large.ts',
|
|
185
|
+
status: 'modified',
|
|
186
|
+
additions: 12,
|
|
187
|
+
deletions: 4,
|
|
188
|
+
patch,
|
|
189
|
+
}],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
parts: [],
|
|
193
|
+
}]);
|
|
194
|
+
|
|
195
|
+
expect(projected.info.summary).toEqual({
|
|
196
|
+
title: 'kept',
|
|
197
|
+
diffCount: 1,
|
|
198
|
+
hasDiffs: true,
|
|
199
|
+
});
|
|
200
|
+
expect(projected.info.summary.diffs).toBeUndefined();
|
|
201
|
+
expect(JSON.stringify(projected)).not.toContain(patch);
|
|
202
|
+
expect(JSON.stringify(projected)).not.toContain('src/large.ts');
|
|
203
|
+
});
|
|
204
|
+
|
|
175
205
|
it('drops tool output and metadata but keeps identity and status', () => {
|
|
176
206
|
const [record] = projectSlimParts([
|
|
177
207
|
{ info: { id: 'msg_a1', role: 'assistant' }, parts: [toolPart('prt_1', 'x'.repeat(5000))] },
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/vendor-heic2any-CUPf3g2A.js","assets/rolldown-runtime-C0FnF6B9.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{A as t,D as n,E as r,F as i,H as a,T as o,X as s,b as c,et as l,j as u,nt as d}from"./useUIStore-5agS8bsW.js";import{$t as f,Mt as p,Pt as m,kn as h,nt as g,ot as ee,pt as te,r as _,st as v,xn as ne,zt as re}from"./persistence-DPNMIbF5.js";import{a as ie,r as ae}from"./vendor-zustand-B4dlGEM2.js";import{t as oe}from"./vendor-opencode-sdk-C07HQypa.js";import{i as se}from"./vendor-pathe-vBmvQE8f.js";import{o as ce}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";var le=(e,t)=>e!==t,ue=new Set([`image/heic`,`image/heif`]),de=!1,fe=()=>{let e=globalThis.window?.Capacitor;return e&&typeof e==`object`?e:null},pe=e=>ue.has((e.type||``).toLowerCase()),me=async e=>{let t=new Uint8Array(await e.arrayBuffer()),n=``,r=32768;for(let e=0;e<t.byteLength;e+=r){let i=t.subarray(e,Math.min(e+r,t.byteLength));n+=String.fromCharCode(...i)}return btoa(n)},he=(e,t)=>{let n=atob(e),r=new Uint8Array(n.length);for(let e=0;e<n.length;e++)r[e]=n.charCodeAt(e);return new Blob([r],{type:t})},ge=async e=>{if(!pe(e)||de)return null;let t=fe();if(!t||typeof t.isNativePlatform!=`function`||!t.isNativePlatform())return null;let n=t.Plugins?.OpenChamberMedia?.transcode;if(typeof n!=`function`)return null;try{let t=await n({data:await me(e),mime:e.type.toLowerCase(),quality:.9});if(typeof t?.data!=`string`||!t.data)return null;let r=typeof t.mime==`string`&&t.mime?t.mime:`image/jpeg`;return he(t.data,r)}catch(e){return de=!0,console.warn(`Native HEIC transcode failed`,e),null}},_e=e=>e.trim().toLowerCase(),ve=e=>e.source===`local`||e.source===`server`||e.source===`vscode`,ye=(e,t)=>{if(!e||!e.includes(`[`)||t.length===0)return[];let n=new Set(t.map(_e)),r=[],i=0;for(;i<e.length;){let t=e.indexOf(`[`,i);if(t===-1)break;let a=e.indexOf(`]`,t+1);if(a===-1)break;if(e[a+1]!==`(`){let i=te(e.slice(t+1,a)).trim();n.has(_e(i))&&r.push({start:t,end:a+1})}i=a+1}return r},be=(e,t)=>{let n=t.start,r=t.end;return r<e.length&&/\s/.test(e[r])?r+=1:n>0&&/\s/.test(e[n-1])&&--n,{start:n,end:r}},xe=(e,t,n,r)=>{let i=ye(e,t);if(i.length===0)return{text:e,mentions:[...n],composerReferences:r===void 0?void 0:[...r],changed:!1};let a=e,o=[...n],s=r===void 0?[]:[...r];for(let e=i.length-1;e>=0;--e){let{start:t,end:n}=be(a,i[e]),r=n-t;a=`${a.slice(0,t)}${a.slice(n)}`,o=o.flatMap(e=>e.range.end<=t?[e]:e.range.start>=n?[{...e,range:{start:e.range.start-r,end:e.range.end-r}}]:[]),s=s.flatMap(e=>e.end<=t?[e]:e.start>=n?[{...e,start:e.start-r,end:e.end-r}]:[])}return{text:a,mentions:o,composerReferences:r===void 0?void 0:s,changed:!0}},Se=new Set([`image`,`screenshot`,`screen-shot`,`clipboard`,`pasted-image`,`pastedimage`,`untitled`,`unknown`,`file`,`blob`]),Ce={"image/avif":`avif`,"image/bmp":`bmp`,"image/gif":`gif`,"image/heic":`heic`,"image/heif":`heif`,"image/jpeg":`jpg`,"image/jpg":`jpg`,"image/png":`png`,"image/svg+xml":`svg`,"image/tiff":`tiff`,"image/webp":`webp`},y=e=>e.trim().toLowerCase(),we=e=>e.charCodeAt(0)<32||`<>:"/\\|?*[]`.includes(e),Te=e=>{let t=e.replace(/\\/g,`/`).split(`/`).pop()??``;return Array.from(t).map(e=>we(e)?`-`:e).join(``).replace(/\s+/g,` `).replace(/-+/g,`-`).trim()},Ee=e=>Ce[e?.trim().toLowerCase()??``]??`png`,De=e=>{let t=Te(e.name),n=Ee(e.type),r=t.lastIndexOf(`.`);if(r>0&&r<t.length-1){let e=t.slice(r+1).toLowerCase();if(/^[a-z0-9]{1,10}$/.test(e))return{base:t.slice(0,r).trim()||`image`,ext:e}}return{base:t.trim()||`image`,ext:n}},Oe=e=>{let{base:t}=De({name:e}),n=t.trim().toLowerCase().replace(/[\s_]+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``);if(Se.has(n))return!0;let r=n.replace(/-\(\d+\)$/g,``);return r!==n&&Se.has(r)?!0:/^(image|file|unknown|untitled|blob)-\d+$/.test(n)},b=(e,t)=>`${e}.${t}`,ke=(e,t,n)=>{let r=b(e,t);if(!n.has(y(r)))return r;for(let r=2;r<2**53-1;r+=1){let i=b(`${e}-${r}`,t);if(!n.has(y(i)))return i}return b(`${e}-${Date.now()}`,t)},Ae=(e,t)=>{for(let n=1;n<2**53-1;n+=1){let r=b(`image-${n}`,e);if(!Array.from(t).some(e=>e.startsWith(`image-${n}.`))&&!t.has(y(r)))return r}return b(`image-${Date.now()}`,e)},je=(e,t)=>{let n=new Set(t.map(y));return e.map(e=>{let{base:t,ext:r}=De(e),i=Oe(b(t,r))?Ae(r,n):ke(t,r,n);return n.add(y(i)),i})},Me=e=>e.map(e=>v(e)).join(` `),Ne=(e,t,n)=>{if(t===n)return[];let r=[];for(let i of e){let e=[v(i),`[${i}]`],a=e.some(e=>t.includes(e)),o=e.some(e=>n.includes(e));a&&!o&&r.push(i)}return r},Pe=e=>e.replaceAll(`[${ee}`,`[`),Fe=/\.(?:png|jpe?g|gif|webp|svg|avif|bmp|heic|heif|tiff?)$/i,Ie=e=>{let t=e.trim();return t.startsWith(`/`)||/^[A-Za-z]:[\\/]/.test(t)||t.startsWith(`\\\\`)},Le=(e,t)=>{let n=e;for(let e of t){let t=e.filename.trim(),r=e.path.trim();if(!t||!r||t===r||Ie(t)||!Fe.test(t)&&!Fe.test(r))continue;let i=`[${r}]`;n=n.split(v(t)).join(i).split(`[${t}]`).join(i)}return n},Re=(e,t)=>{let n=e;for(let e of t??[]){if(e.source!==`vscode`||e.vscodeSource!==`selection`||!e.vscodePath)continue;let t=e.filename.match(/:(\d+(?:-\d+)?)$/)?.[1];if(!t)continue;let r=`[${e.vscodePath}:${t}]`;n=n.split(v(e.filename)).join(r).split(`[${e.filename}]`).join(r)}return n},ze=e=>e.mime===`text/plain`&&typeof e.filename==`string`&&/:\d+(?:-\d+)?$/.test(e.filename),Be=`application/x-directory`,Ve=e=>typeof e==`string`&&e.trim().toLowerCase()===`application/x-directory`,He=e=>typeof e==`string`&&/[/\\]$/.test(e.trim()),Ue=(e,t,n)=>{if(t===`Backspace`){let t=n;for(;t>0&&/\s/.test(e[t-1]);)--t;for(;t>0&&!/\s/.test(e[t-1]);)--t;return{start:t,end:n}}let r=n;for(;r<e.length&&/\s/.test(e[r]);)r+=1;for(;r<e.length&&!/\s/.test(e[r]);)r+=1;return{start:n,end:r}},We=(e,t,n)=>{let r=Math.max(0,Math.min(n.selectionStart,e.length)),i=Math.max(r,Math.min(n.selectionEnd,e.length)),a;if(a=r===i?n.altKey?Ue(e,n.key,r):n.key===`Backspace`?{start:Math.max(0,r-1),end:r}:{start:r,end:Math.min(e.length,r+1)}:{start:r,end:i},a.start===a.end)return null;let o=ye(e,t).filter(e=>e.start<a.end&&e.end>a.start);if(o.length===0)return null;let s=Math.min(a.start,...o.map(e=>e.start)),c=Math.max(a.end,...o.map(e=>e.end));return c<e.length&&/\s/.test(e[c])&&(s===0||/\s/.test(e[s-1]))?c+=1:c===e.length&&s>0&&/\s/.test(e[s-1])&&--s,{text:`${e.slice(0,s)}${e.slice(c)}`,caret:s,removedFilenames:o.map(t=>te(e.slice(t.start+1,t.end-1)).trim())}},x=class extends Error{status;code;constructor(e,t,n=`Failed to upload prompt attachment`){super(n),this.name=`PromptAttachmentUploadError`,this.status=e,this.code=t}},S=`file://`,Ge=e=>{let t=e.trim();if(t.toLowerCase().startsWith(S))return t;let n=se(t).split(`/`).map(e=>/^[A-Za-z]:$/.test(e)?e:encodeURIComponent(e)).join(`/`);return/^[A-Za-z]:/.test(n)?`${S}/${n}`:`${S}${n}`},Ke=e=>{let t=e.trim();if(!t.toLowerCase().startsWith(S))return t;let n=t.slice(7);n.toLowerCase().startsWith(`localhost/`)&&(n=n.slice(9));let r=n.split(`/`).map(e=>{if(/^[A-Za-z]:$/.test(e))return e;try{return decodeURIComponent(e)}catch{return e}}).join(`/`);return/^\/[A-Za-z]:/.test(r)?r.slice(1):r},qe=async e=>[...new Uint8Array(await crypto.subtle.digest(`SHA-256`,await e.arrayBuffer()))].map(e=>e.toString(16).padStart(2,`0`)).join(``),Je=e=>typeof e==`object`&&!!e&&!Array.isArray(e),Ye=async e=>{let t;try{t=await e.json()}catch{throw new x(e.status,`unavailable`)}if(!Je(t)||typeof t.path!=`string`||!t.path)throw new x(e.status,`unavailable`);let n=typeof t.mime==`string`&&t.mime?t.mime:`application/octet-stream`,r=typeof t.size==`number`&&Number.isSafeInteger(t.size)?t.size:0,i=typeof t.sha256==`string`?t.sha256:``;return{path:t.path,url:Ge(t.path),mime:n,size:r,sha256:i}},Xe=e=>{let t=typeof crypto.randomUUID==`function`?crypto.randomUUID():`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`,n=e?.replace(/[^a-z0-9._-]+/gi,`-`).replace(/^-+|-+$/g,``).slice(0,32);return n?`att-${t}-${n}`:`att-${t}`},Ze=(e,t)=>{if(!e.startsWith(`data:`))return null;let n=e.indexOf(`,`);if(n===-1)return null;let r=e.slice(5,n),i=e.slice(n+1),a=r.split(`;`,1)[0]?.trim()||t||`application/octet-stream`;try{if(r.toLowerCase().includes(`;base64`)){let e=atob(i),t=new Uint8Array(e.length);for(let n=0;n<e.length;n++)t[n]=e.charCodeAt(n);return new Blob([t],{type:a})}return new Blob([decodeURIComponent(i)],{type:a})}catch{return null}},Qe=e=>e.startsWith(`data:`)||e.startsWith(`blob:`),$e=async e=>{let t=e.mime||e.body.type||`application/octet-stream`,n=e.body.type===t?e.body:new Blob([e.body],{type:t});if(!Number.isSafeInteger(n.size)||n.size<0||n.size>26214400)throw new x(413,`too-large`);let r=await qe(n),i=Xe(e.filename),a;try{a=await h(`/api/fs/prompt-attachments/${encodeURIComponent(i)}`,{method:`PUT`,headers:{"Content-Type":t,"Content-Length":String(n.size),"X-OpenChamber-Content-Length":String(n.size),"X-OpenChamber-Sha256":r,"X-OpenChamber-Mime":t,...e.filename?{"X-OpenChamber-Filename":encodeURIComponent(e.filename)}:{}},body:n,signal:e.signal})}catch{throw new x(0,`unavailable`)}if(a.status===413)throw new x(413,`too-large`);if(!a.ok)throw new x(a.status,a.status>=500||a.status===0?`unavailable`:`rejected`);let o=await Ye(a);if(o.size!==n.size)throw new x(a.status,`unavailable`);return{...o,mime:t}},et=500,tt=()=>{if(typeof window>`u`)return!1;try{return new URLSearchParams(window.location.search).get(`startupTrace`)===`1`||window.localStorage?.getItem(`OPENCHAMBER_STARTUP_TRACE`)===`1`}catch{return!1}},nt=()=>tt(),C=(e,t)=>{if(!tt())return;let n=typeof performance<`u`?performance.now():Date.now();window.__OPENCHAMBER_STARTUP_TRACE_START__??=n,window.__OPENCHAMBER_STARTUP_TRACE__??=[],window.__OPENCHAMBER_STARTUP_TRACE__.push({t:Math.round(n-window.__OPENCHAMBER_STARTUP_TRACE_START__),name:e,...t?{data:t}:{}}),window.__OPENCHAMBER_STARTUP_TRACE__.length>et&&window.__OPENCHAMBER_STARTUP_TRACE__.splice(0,window.__OPENCHAMBER_STARTUP_TRACE__.length-et)};typeof window<`u`&&(window.__OPENCHAMBER_STARTUP_TRACE_SUMMARY__=()=>{let e=typeof window<`u`?window.__OPENCHAMBER_STARTUP_TRACE__??[]:[],t=e.findIndex(e=>e.name===`ModelControls:ready`),n=t>=0?Math.min(e.length,t+8):e.length;return e.slice(0,n).filter(e=>e.name.includes(`checkConnection`)||e.name.includes(`checkHealth`)||e.name.includes(`initializeApp`)||e.name.includes(`initApp`)||e.name.includes(`loadProviders`)||e.name.includes(`loadAgents`)||e.name.includes(`config.defaults`)||e.name.includes(`ModelControls`)||e.name.includes(`activateDirectory`)||e.name.includes(`opencodeClient:setDirectory`))});var rt=async(e,t,n)=>{let r=typeof performance<`u`?performance.now():Date.now();C(`${e}:start`,n);try{let n=await t(),i=typeof performance<`u`?performance.now():Date.now();return C(`${e}:end`,{durationMs:Math.round(i-r)}),n}catch(t){let n=typeof performance<`u`?performance.now():Date.now();throw C(`${e}:error`,{durationMs:Math.round(n-r),error:t instanceof Error?t.message:String(t)}),t}},it=3,at=3e4,ot=32e3,st=36e5,ct=6e5,lt=new Set([429,502,503,504]),w=new Map;function ut(){let e=Date.now();for(let[t,n]of w)n.consecutiveErrors===0&&e-n.lastErrorAt>st&&w.delete(t)}typeof setInterval<`u`&&setInterval(ut,ct).unref?.();function dt(e){let t=w.get(e);return t||(t={consecutiveErrors:0,lastErrorAt:0,circuitOpen:!1,circuitOpenAt:0,circuitCooldownMs:at},w.set(e,t)),t}function ft(e){if(!e)return;let t=w.get(e);t&&(t.consecutiveErrors=0,t.lastErrorAt=0)}function pt(e,t){if(!e)return;let n=dt(e);n.consecutiveErrors+=1,n.lastErrorAt=Date.now(),mt(t)&&n.consecutiveErrors>=it&&(n.circuitOpen=!0,n.circuitOpenAt=Date.now(),console.warn(`[provider-tracker] Circuit opened for ${e} after ${n.consecutiveErrors} consecutive errors`))}function mt(e){return e!==void 0&<.has(e)}function ht(e){let t=w.get(e);return t?.circuitOpen?Date.now()-t.circuitOpenAt>=t.circuitCooldownMs?(t.circuitOpen=!1,t.consecutiveErrors=0,t.circuitCooldownMs=Math.min(t.circuitCooldownMs*2,ot*4),!1):!0:!1}function gt(e){if(!(!e||!ht(e)))throw Error(`Provider ${e} is temporarily unavailable after repeated errors. Please retry shortly.`)}var _t=`/api`,vt=1e4,yt=4e3,bt=3e3,xt=1e3,St=12e3;function T(e){if(e instanceof Error)return e.message;if(typeof e==`string`)return e;if(e&&typeof e==`object`&&`message`in e&&typeof e.message==`string`)return e.message;try{return JSON.stringify(e)}catch{return String(e)}}function E(e,t){if(e.error){let n=e.response?.status,r=Error(`${t} failed${n?` (${n})`:``}: ${T(e.error)}`);throw n!==void 0&&(r.status=n),r}if(e.data===void 0||e.data===null)throw Error(`${t} failed: empty response`);return e.data}function D(e,t){if(e.error){let n=e.response?.status,r=Error(`${t} failed${n?` (${n})`:``}: ${T(e.error)}`);throw n!==void 0&&(r.status=n),r}return e.data}var Ct=/^[a-zA-Z][a-zA-Z\d+\-.]*:\/\//,wt=e=>{let t=typeof e==`string`&&e.trim().length>0?e.trim():`/api`;if(Ct.test(t)||typeof window>`u`)return t;let n=window.location?.href||window.location?.origin;if(!n)return t;try{return new URL(t,n).toString()}catch(e){return console.warn(`Failed to normalize OpenCode base URL:`,e),t}},Tt=()=>{try{return i().api(`/api`)}catch{return null}},Et=()=>{try{return i().api(`/`)}catch{return null}},Dt=e=>{let t=typeof AbortSignal<`u`?AbortSignal:void 0;if(typeof t?.timeout==`function`)return{signal:t.timeout(e),cleanup:()=>void 0};let n=new AbortController,r=setTimeout(()=>n.abort(),e);return{signal:n.signal,cleanup:()=>clearTimeout(r)}},Ot=e=>{let t=e.filter(e=>e!=null);if(t.length===0)return{signal:new AbortController().signal,cleanup:()=>void 0};if(t.length===1)return{signal:t[0],cleanup:()=>void 0};let n=typeof AbortSignal<`u`?AbortSignal:void 0;if(typeof n?.any==`function`)return{signal:n.any(t),cleanup:()=>void 0};let r=new AbortController,i=()=>r.abort();for(let e of t){if(e.aborted){r.abort();break}e.addEventListener(`abort`,i)}return{signal:r.signal,cleanup:()=>{for(let e of t)e.removeEventListener(`abort`,i)}}},O=e=>oe({...e,fetch:h}),kt=e=>typeof e.mime==`string`&&e.mime.startsWith(`image/`)?!0:typeof e.filename==`string`&&/\.(?:png|jpe?g|gif|webp|svg|avif|bmp|heic|heif|tiff?)$/i.test(e.filename),At=e=>{let t=[];for(let n of e){if(!kt(n))continue;let e=typeof n.filename==`string`?n.filename.trim():``,r=typeof n.url==`string`?n.url:``;if(!e||!r.toLowerCase().startsWith(`file://`))continue;let i=Ke(r).trim();i&&t.push({filename:e,path:i})}return t},jt=async(e,t)=>{let n=[],r=e.files?.length?await Promise.all(e.files.map(e=>t(e))):[],i=e.additionalParts?.length?await Promise.all(e.additionalParts.map(async e=>({text:e.text,synthetic:e.synthetic,files:e.files?.length?await Promise.all(e.files.map(e=>t(e))):[]}))):[],a=e=>Le(e,At([...r,...i.flatMap(e=>e.files)]));if(e.prefaceText&&e.prefaceText.trim()&&n.push({type:`text`,text:a(e.prefaceText),synthetic:e.prefaceTextSynthetic!==!1}),e.text&&e.text.trim()&&n.push({type:`text`,text:a(e.text)}),n.push(...r),i.length>0)for(let e of i){if(e.text&&e.text.trim()){let t={type:`text`,text:a(e.text)};e.synthetic&&(t.synthetic=!0),n.push(t)}n.push(...e.files)}if(e.agentMentions&&e.agentMentions.length>0)for(let t of e.agentMentions){if(!t?.name)continue;let e={type:`agent`,name:t.name};t.source&&(e.source=t.source),n.push(e)}if(n.length===0)throw Error(`Message must have at least one part (text or file)`);return n},k=e=>e.replace(/\\/g,`/`),Mt=400,Nt=()=>{let e=ne();return e&&e.runtime?.isDesktop&&e.files?e.files:null},A=new class{client;baseUrl;scopedClients=new Map;currentDirectory=void 0;directoryContextQueue=Promise.resolve();listDirectoryInFlight=new Map;configProvidersInFlight=new Map;listAgentsInFlight=new Map;configInFlight=new Map;configCache=new Map;configCacheGeneration=0;listDirectoryCache=new Map;healthInFlight=new Map;healthCache=new Map;healthCacheGeneration=0;constructor(e=_t){let t=Tt()||e;this.baseUrl=wt(t),this.client=O({baseUrl:this.baseUrl})}getBaseUrl(){return this.baseUrl}reconnectToRuntimeBaseUrl(){let e=wt(Tt()||_t);e!==this.baseUrl&&(this.baseUrl=e,this.client=O({baseUrl:this.baseUrl}),this.scopedClients.clear(),this.listDirectoryInFlight.clear(),this.configProvidersInFlight.clear(),this.listAgentsInFlight.clear(),this.clearConfigCache(),this.listDirectoryCache.clear(),this.clearHealthCache())}getSdkClient(){return this.client}getScopedSdkClient(e){return this.getScopedApiClient(e)}getScopedApiClient(e){let t=this.normalizeCandidatePath(e)??e,n=t||``,r=this.scopedClients.get(n);if(r)return r;let i=O({baseUrl:this.baseUrl,directory:t});return this.scopedClients.set(n,i),i}normalizeCandidatePath(e){if(typeof e!=`string`)return null;let t=e.trim();if(!t)return null;let n=t.replace(/\\/g,`/`).replace(/^([a-z]):/,(e,t)=>t.toUpperCase()+`:`);return(n.length>1?n.replace(/\/+$/,``):n)||null}deriveHomeDirectory(e){let t=e.match(/^([A-Za-z]:)(?:\/|$)/);if(t){let n=t[1],r=e.slice(n.length+ +(e.charAt(n.length)===`/`)).split(`/`).filter(Boolean);return r.length>=2?{homeDirectory:`${n}/${r[0]}/${r[1]}`,username:r[1]}:r.length===1?{homeDirectory:`${n}/${r[0]}`,username:r[0]}:{homeDirectory:n,username:void 0}}let n=e.startsWith(`/`),r=e.split(`/`).filter(Boolean);return r.length>=2&&(r[0]===`Users`||r[0]===`home`)?{homeDirectory:`${n?`/`:``}${r[0]}/${r[1]}`,username:r[1]}:n?r.length===0?{homeDirectory:`/`,username:void 0}:{homeDirectory:`/${r.join(`/`)}`,username:r[r.length-1]}:r.length>0?{homeDirectory:`/${r.join(`/`)}`,username:r[r.length-1]}:{homeDirectory:`/`,username:void 0}}setDirectory(e){let t=this.normalizeCandidatePath(e)??e;this.currentDirectory!==t&&C(`opencodeClient:setDirectory`,{previous:this.currentDirectory??null,next:t??null}),this.currentDirectory=t}getDirectory(){return this.currentDirectory}async withDirectory(e,t){let n=async()=>{if(e==null)return t();let n=this.currentDirectory,r=this.normalizeCandidatePath(e)??e;this.currentDirectory=r;try{return await t()}finally{this.currentDirectory===r&&(this.currentDirectory=n)}},r=this.directoryContextQueue.then(n,n);return this.directoryContextQueue=r.then(()=>void 0,()=>void 0),r}getApiClient(){return this.client}async getSystemInfo(){let e=new Set,t=t=>{let n=this.normalizeCandidatePath(t);n&&e.add(n)};try{let e=(await this.client.path.get(this.currentDirectory?{directory:this.currentDirectory}:void 0)).data;e&&(t(e.directory),t(e.worktree),t(e.state))}catch{}if(!e.size)try{t((await this.client.project.current(this.currentDirectory?{directory:this.currentDirectory}:void 0)).data?.worktree)}catch{}if(!e.size)try{(await this.listSessions()).forEach(e=>t(e.directory))}catch{}if(t(this.currentDirectory),typeof window<`u`)try{t(p(`lastDirectory`)),t(p(`homeDirectory`))}catch{}if(!e.size&&typeof process<`u`&&typeof process.cwd==`function`&&t(process.cwd()),!e.size)return{homeDirectory:`/`,username:void 0};let[n]=Array.from(e);return this.deriveHomeDirectory(n)}async probeDirectory(e){let t=this.normalizeCandidatePath(e);if(!t)return!1;try{let e=(await this.client.path.get({directory:t})).data,n=typeof e?.directory==`string`?e.directory:null;return!!(n&&n.trim().length>0)}catch{return!1}}async listSessions(){let e=await this.client.session.list(this.currentDirectory?{directory:this.currentDirectory}:void 0);return Array.isArray(e.data)?e.data:[]}async createSession(e,t){let n=this.normalizeCandidatePath(t)??this.currentDirectory;return E(await this.client.session.create({...n?{directory:n}:{},parentID:e?.parentID,title:e?.title,metadata:e?.metadata}),`session.create`)}async getSession(e,t){let n=this.normalizeCandidatePath(t)??this.currentDirectory;return E(await this.client.session.get({sessionID:e,...n?{directory:n}:{}}),`session.get`)}async deleteSession(e,t){let n=this.normalizeCandidatePath(t)??this.currentDirectory;return D(await this.client.session.delete({sessionID:e,...n?{directory:n}:{}}),`session.delete`)===!0}async deleteSessionMessage(e,t,n){let r=this.normalizeCandidatePath(n)??this.currentDirectory;return D(await this.client.session.deleteMessage({sessionID:e,messageID:t,...r?{directory:r}:{}}),`session.deleteMessage`)===!0}async updateSession(e,t,n){let r=this.normalizeCandidatePath(n)??this.currentDirectory,i={...t.title===void 0?{}:{title:t.title},...t.metadata===void 0?{}:{metadata:t.metadata},...t.time?.archived!==void 0&&t.time.archived!==null?{time:{archived:t.time.archived}}:{}};return E(await this.client.session.update({sessionID:e,...r?{directory:r}:{},...i}),`session.update`)}async getSessionMessages(e,t){return E(await this.client.session.messages({sessionID:e,...this.currentDirectory?{directory:this.currentDirectory}:{},...typeof t==`number`?{limit:t}:{}}),`session.messages`)}async getSessionDiff(e){let t=this.normalizeCandidatePath(e.directory)??this.currentDirectory,n=typeof e.messageID==`string`&&e.messageID.trim().length>0?e.messageID.trim():void 0;return E(await this.client.session.diff({sessionID:e.sessionID,...t?{directory:t}:{},...n?{messageID:n}:{}}),`session.diff`)}async getSessionTodos(e){try{let t=await this.client.session.todo({sessionID:e,...this.currentDirectory?{directory:this.currentDirectory}:{}});if(t.error)return[];let n=t.data;return!n||!Array.isArray(n)?[]:n}catch{return[]}}shouldNormalizeToTextPlain(e){if(!e)return!1;let t=e.toLowerCase();return t.startsWith(`text/`)&&t!==`text/plain`?!0:[`application/json`,`application/xml`,`application/javascript`,`application/typescript`,`application/x-yaml`,`application/yaml`,`application/toml`,`application/x-sh`,`application/x-shellscript`,`application/octet-stream`,`image/svg+xml`].includes(t)}isHeicMime(e){if(!e)return!1;let t=e.toLowerCase();return t===`image/heic`||t===`image/heif`}async convertHeicToJpeg(t){try{let n=Ze(t.url,t.mime);if(!n)return t;let r=await ge(n)??await(await ce(async()=>{let{default:t}=await import(`./vendor-heic2any-CUPf3g2A.js`).then(t=>e(t.t(),1));return{default:t}},__vite__mapDeps([0,1]))).default({blob:n,toType:`image/jpeg`,quality:.9}),i=await new Promise((e,t)=>{let n=new FileReader;n.onload=()=>e(n.result),n.onerror=t,n.readAsDataURL(r)}),a=t.filename;return a&&=a.replace(/\.heic$/i,`.jpg`).replace(/\.heif$/i,`.jpg`),{mime:`image/jpeg`,filename:a,url:i}}catch(e){return console.warn(`Failed to convert HEIC to JPEG:`,e),t}}async normalizeFilePart(e){if(this.isHeicMime(e.mime))return this.convertHeicToJpeg(e);if(!this.shouldNormalizeToTextPlain(e.mime))return e;let t=e.url;if(e.url.startsWith(`data:`)){let n=e.url.indexOf(`,`);if(n!==-1){let r=e.url.substring(5,n),i=e.url.substring(n);t=`data:${r.replace(/^[^;,]+/,`text/plain`)}${i}`}}return{mime:`text/plain`,filename:e.filename,url:t}}async toNormalizedFilePartInput(e){let t=await this.normalizeFilePart(e),n=t.url;if(Qe(n)){let e=Ze(n,t.mime);if(!e)throw Error(`Failed to materialize attachment bytes for ${t.filename??`file`}`);n=(await $e({body:e,mime:t.mime,filename:t.filename})).url}return{...e.id?{id:e.id}:{},type:`file`,mime:t.mime,filename:t.filename,url:n}}async buildMessageParts(e){return jt(e,e=>this.toNormalizedFilePartInput(e))}async sendMessage(e){let t=e.messageId??g(`msg`),n=await this.buildMessageParts({text:e.text,prefaceText:e.prefaceText,prefaceTextSynthetic:e.prefaceTextSynthetic,files:e.files,additionalParts:e.additionalParts,agentMentions:e.agentMentions}),r=this.normalizeCandidatePath(e.directory??null)??this.currentDirectory;e.format&&(e.id,e.providerID,e.modelID,e.agent,e.variant,this.baseUrl,e.format.type),gt(e.providerID);let i;try{let a=await this.client.session.promptAsync({sessionID:e.id,...r?{directory:r}:{},model:{providerID:e.providerID,modelID:e.modelID},agent:e.agent,variant:e.variant,messageID:t,...e.delivery?{delivery:e.delivery}:{},...e.format?{format:e.format}:{},parts:n});if(a.response instanceof Response)i=a.response;else if(a.error){let e=a.response?.status;if(!e)throw Error(`Message send transport failure: ${T(a.error)}`);i=new Response(JSON.stringify(a.error),{status:e})}else i=new Response(JSON.stringify(a.data??!0),{status:200})}catch(t){throw pt(e.providerID),t}if(i.ok)return ft(e.providerID),t;let a=``;try{a=await i.text()}catch{}let o=a&&a.trim().length>0?`: ${a.trim()}`:``,s=Error(`Failed to send message (${i.status})${o}`);throw s.status=i.status,pt(e.providerID,i.status),s}async sendCommand(e){let t=e.messageId??g(`msg`),n=[];if(e.files&&e.files.length>0)for(let t of e.files)n.push(await this.toNormalizedFilePartInput(t));let r=this.normalizeCandidatePath(e.directory??null)??this.currentDirectory;return D(await this.client.session.command({sessionID:e.id,...r?{directory:r}:{},command:e.command,arguments:e.arguments??``,model:`${e.providerID}/${e.modelID}`,agent:e.agent,variant:e.variant,...n.length>0?{parts:n}:{},messageID:t}),`session.command`),t}async abortSession(e){return!!(await this.client.session.abort({sessionID:e,...this.currentDirectory?{directory:this.currentDirectory}:{}},{throwOnError:!0})).data}async shellSession(e){let t=this.normalizeCandidatePath(e.directory??null)??this.currentDirectory;return E(await this.client.session.shell({sessionID:e.sessionId,...t?{directory:t}:{},messageID:e.messageId,agent:e.agent,model:e.model,command:e.command}),`session.shell`)}async revertSession(e,t,n,r){let i=this.normalizeCandidatePath(r)??this.currentDirectory;return E(await this.client.session.revert({sessionID:e,...i?{directory:i}:{},messageID:t,partID:n}),`session.revert`)}async summarizeSession(e,t,n,r){let i=this.normalizeCandidatePath(r)??this.currentDirectory;return D(await this.client.session.summarize({sessionID:e,...i?{directory:i}:{},providerID:t,modelID:n}),`session.summarize`)===!0}async unrevertSession(e){return E(await this.client.session.unrevert({sessionID:e,...this.currentDirectory?{directory:this.currentDirectory}:{}}),`session.unrevert`)}async forkSession(e,t,n){let r=this.normalizeCandidatePath(n)??this.currentDirectory,i=E(await this.client.session.fork({sessionID:e,...r?{directory:r}:{},messageID:t}),`session.fork`);return i.id,i}async getSessionStatus(){return await this.getSessionStatusForDirectory(this.currentDirectory??null)??{}}async getSessionStatusForDirectory(e,t){try{let n=typeof e==`string`?e.trim():``,r=await this.client.session.status(n?{directory:n}:void 0,t?{signal:t}:void 0);return r.error||!r.data||typeof r.data!=`object`?null:r.data}catch{return null}}async getSessionActive(e){try{let t=await O({baseUrl:wt(Et()||`/`)}).v2.session.active(e?{signal:e}:void 0),n=t.response?.status;if(t.error||n!==void 0&&n!==200)return n===404||n===405||n===501?{state:`unsupported`}:{state:`unknown`};let r=t.data,i=r&&typeof r==`object`&&`data`in r&&r.data!==void 0?r.data:r;if(!i||typeof i!=`object`||Array.isArray(i))return{state:`unknown`};let a={};for(let[e,t]of Object.entries(i)){if(typeof e!=`string`||e.length===0||!t||typeof t!=`object`||t.type!==`running`)return{state:`unknown`};a[e]={type:`running`}}return{state:`supported`,membership:a}}catch{return{state:`unknown`}}}async getGlobalSessionStatus(){return await this.getSessionStatusForDirectory(null)??{}}async getWebServerSessionActivity(){try{let e=await h(`/api/session-activity`,{method:`GET`,headers:{Accept:`application/json`}});if(!e.ok)return null;let t=await e.json().catch(()=>null);return!t||typeof t!=`object`?null:t}catch{return null}}async listToolIds(e){try{let t=typeof e?.directory==`string`?e.directory.trim():this.currentDirectory?this.currentDirectory.trim():``;return((await this.client.tool.ids(t?{directory:t}:void 0)).data||[]).filter(e=>typeof e==`string`&&e!==`invalid`)}catch{return[]}}async replyToPermission(e,t,n){let r=this.normalizeCandidatePath(n?.directory??null)??this.currentDirectory;return D(await this.client.permission.reply({requestID:e,...r?{directory:r}:{},reply:t,...n?.message?{message:n.message}:{}}),`permission.reply`)===!0}async createPermission(e,t,n,r){try{let i=await this.client.v2.session.permission.create({sessionID:e,action:t,resources:n,...r?.id?{id:r.id}:{},...r?.save?{save:r.save}:{},...r?.metadata?{metadata:r.metadata}:{},...r?.source?{source:r.source}:{},...r?.agent?{agent:r.agent}:{}});if(i.error!==void 0)return null;let a=i.data?.data;return a===void 0?null:{id:a.id,effect:a.effect}}catch{return null}}async fetchPermission(e,t){try{let n=await this.client.v2.session.permission.get({sessionID:e,requestID:t});if(n.error===void 0){let e=n.data?.data;if(e!==void 0)return{state:`ok`,permission:e}}return n.response?.status===404?{state:`resolved`}:{state:`unknown`}}catch{return{state:`unknown`}}}async listPendingPermissions(e){let t=[],n=async e=>{let t=typeof e==`string`?e.trim():``,n=await this.client.permission.list(t?{directory:t}:void 0);if(n.error)throw Error(`permission.list failed: ${T(n.error)}`);return n.data||[]};t.push(n(null));let r=new Set;for(let t of e?.directories??[]){let e=this.normalizeCandidatePath(t??null);e&&r.add(e)}for(let e of r)t.push(n(e));let i=await Promise.all(t),a=[],o=new Set;for(let e of i)for(let t of e){if(!t||typeof t!=`object`)continue;let e=t.id;typeof e==`string`&&e.length!==0&&(o.has(e)||(o.add(e),a.push(t)))}return a}async replyToQuestion(e,t,n){let r=!Array.isArray(t)||t.length===0?[]:Array.isArray(t[0])?t:[t],i=this.normalizeCandidatePath(n)??this.currentDirectory;return D(await this.client.question.reply({requestID:e,...i?{directory:i}:{},answers:r}),`question.reply`)===!0}async rejectQuestion(e){return D(await this.client.question.reject({requestID:e,...this.currentDirectory?{directory:this.currentDirectory}:{}}),`question.reject`)===!0}async listPendingQuestions(e){let t=[],n=async e=>{let t=typeof e==`string`?e.trim():``,n=await this.client.question.list(t?{directory:t}:void 0);if(n.error)throw Error(`question.list failed: ${T(n.error)}`);return n.data||[]};t.push(n(null));let r=new Set;for(let t of e?.directories??[]){let e=this.normalizeCandidatePath(t??null);e&&r.add(e)}for(let e of r)t.push(n(e));let i=await Promise.all(t),a=[],o=new Set;for(let e of i)for(let t of e){if(!t||typeof t!=`object`)continue;let e=t.id;typeof e==`string`&&e.length!==0&&(o.has(e)||(o.add(e),a.push(t)))}return a}clearConfigCache(){this.configCacheGeneration+=1,this.configInFlight.clear(),this.configCache.clear()}clearHealthCache(){this.healthCacheGeneration+=1,this.healthInFlight.clear(),this.healthCache.clear()}async getConfig(e){let t=this.normalizeCandidatePath(e)??e??this.currentDirectory??void 0,n=t??``,r=this.configCache.get(n);if(r&&r.expiresAt>Date.now())return C(`opencodeClient.getConfig:cacheHit`,{directory:t??null}),r.config;let i=this.configInFlight.get(n);if(i)return C(`opencodeClient.getConfig:deduped`,{directory:t??null}),i;let a=this.configCacheGeneration,o=(async()=>{C(`opencodeClient.getConfig:start`,{directory:t??null});let e=typeof performance<`u`?performance.now():Date.now(),r=await(t?this.getScopedApiClient(t):this.client).config.get();if(!r.data)throw Error(`Failed to get config`);let i=typeof performance<`u`?performance.now():Date.now();return C(`opencodeClient.getConfig:end`,{directory:t??null,durationMs:Math.round(i-e)}),a===this.configCacheGeneration&&this.configCache.set(n,{config:r.data,expiresAt:Date.now()+vt}),r.data})();this.configInFlight.set(n,o);try{return await o}finally{this.configInFlight.get(n)===o&&this.configInFlight.delete(n)}}async updateConfig(e){let t=E(await this.client.config.update({config:e}),`global.config.update`);return this.clearConfigCache(),t}async updateConfigPartial(e){let t=e(await this.getConfig());return await this.updateConfig(t)}async getProviders(){return this.getProvidersForConfig(this.currentDirectory)}async getProvidersForConfig(e){let t=e===void 0?this.currentDirectory??void 0:this.normalizeCandidatePath(e)??void 0,n=t??``,r=this.configProvidersInFlight.get(n);if(r)return r;let i=(async()=>E(await this.client.config.providers(t?{directory:t}:void 0),`config.providers`))();this.configProvidersInFlight.set(n,i);try{return await i}finally{this.configProvidersInFlight.delete(n)}}async getApp(){return{version:`0.0.3`,config:await this.getConfig()}}async initApp(){try{return await this.checkHealth()}catch{return!1}}async listAgents(e,t){let n=e===void 0?this.currentDirectory??void 0:this.normalizeCandidatePath(e)??void 0,r=n??``;if(!t){let e=this.listAgentsInFlight.get(r);if(e)return e}let i=(async()=>{let e=Dt(St),r=Ot(t?[t,e.signal]:[e.signal]);try{let e=n?{directory:n}:void 0,t=await this.client.app.agents(e,{signal:r.signal});if(!t.error&&Array.isArray(t.data)&&t.data.length>0)return t.data;let i=await h(`/api/agent`,{...n?{query:{directory:n}}:{},signal:r.signal});if(!i.ok)throw t.error?Error(`app.agents failed${t.response?.status?` (${t.response.status})`:``}: ${T(t.error)}`):Error(`agent.list failed (${i.status})`);let a=await i.json().catch(()=>null);if(!Array.isArray(a))throw Error(`agent.list failed: invalid response`);return a}finally{e.cleanup(),r.cleanup()}})();if(t)return i;this.listAgentsInFlight.set(r,i);try{return await i}finally{this.listAgentsInFlight.delete(r)}}async readFile(e){try{let t=await this.client.file.read({path:e,...this.currentDirectory?{directory:this.currentDirectory}:{}});return String(E(t,`file.read`))}catch{return`// Content of ${e}\n// This would be loaded from the server`}}async listFiles(e){try{let t=e||this.currentDirectory||`/`,n=E(await this.client.file.list({path:t,...this.currentDirectory?{directory:this.currentDirectory}:{}}),`file.list`);return Array.isArray(n)?n:[]}catch{return[]}}async listCommands(){return(E(await this.client.command.list(this.currentDirectory?{directory:this.currentDirectory}:void 0),`command.list`)||[]).map(e=>({name:e.name,description:e.description,agent:e.agent,model:e.model,source:e.source}))}async listCommandsWithDetails(){return(E(await this.client.command.list(this.currentDirectory?{directory:this.currentDirectory}:void 0),`command.list`)||[]).map(e=>({name:e.name,description:e.description,agent:e.agent,model:e.model,source:e.source,template:e.template}))}async listSkillsWithDetails(){try{let e=(await this.client.app.skills(this.currentDirectory?{directory:this.currentDirectory}:void 0)).data;if(!Array.isArray(e))return[];let t=[];for(let n of e){let e=typeof n.name==`string`?n.name.trim():``,r=typeof n.location==`string`?n.location:``;if(!e||!r)continue;let i={name:e,location:r};typeof n.description==`string`&&(i.description=n.description),typeof n.content==`string`&&(i.content=n.content),t.push(i)}return t}catch{return[]}}async getCommandDetails(e){try{let t=await this.client.command.list(this.currentDirectory?{directory:this.currentDirectory}:void 0);if(t.data){let n=t.data.find(t=>t.name===e);if(n)return{name:n.name,template:n.template,description:n.description,agent:n.agent,model:n.model}}return null}catch{return null}}async checkHealth(){let e=r(),t=this.healthCache.get(e);if(t&&t.expiresAt>Date.now())return t.healthy;let n=this.healthInFlight.get(e);if(n)return n;let i=this.healthCacheGeneration,a=(async()=>{let t=!1;try{let e=this.baseUrl.endsWith(`/`)?this.baseUrl.replace(/\/+$/,``):this.baseUrl,n=e===`/api`||e.endsWith(`/api`)?`/api/opencode/health`:`${e}/opencode/health`;C(`opencodeClient.checkHealth:url`,{baseUrl:this.baseUrl,healthUrl:n});let r=Dt(yt),i=await h(n,{signal:r.signal}).finally(r.cleanup);if(C(`opencodeClient.checkHealth:response`,{status:i.status}),i.ok){let e=await i.json();C(`opencodeClient.checkHealth:result`,{healthy:e?.healthy}),t=e?.healthy===!0}}catch{t=!1}return i!==this.healthCacheGeneration||e!==r()?!1:(this.healthCache.set(e,{healthy:t,expiresAt:Date.now()+(t?bt:xt)}),t)})();this.healthInFlight.set(e,a);try{return await a}finally{this.healthInFlight.get(e)===a&&this.healthInFlight.delete(e)}}async createDirectory(e,t){let n=Nt();if(n?.createDirectory)try{return await n.createDirectory(e)}catch(e){let t=e instanceof Error?e.message:String(e);throw Error(t||`Failed to create directory`)}let r={path:e,...t?.allowOutsideWorkspace?{allowOutsideWorkspace:!0}:{}},i=await h(`${this.baseUrl}/fs/mkdir`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(r)});if(!i.ok){let e=await i.json().catch(()=>({error:`Failed to create directory`}));throw Error(e.error||`Failed to create directory`)}return await i.json()}async cloneRepository(e){let t=await h(`${this.baseUrl}/fs/clone`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify(e)});if(!t.ok){let e=await t.json().catch(()=>({error:`Failed to clone repository`}));throw Error(e.error||`Failed to clone repository`)}return await t.json()}async listLocalDirectory(e,t){let n=`${typeof e==`string`?k(e.trim()):``}|${t?.respectGitignore?`1`:`0`}`,r=Date.now(),i=this.listDirectoryCache.get(n);if(i&&i.expiresAt>r)return i.entries;let a=this.listDirectoryInFlight.get(n);if(a)return a;let o=(async()=>{let r=Nt();if(r)try{let i=await r.listDirectory(e||``,t);if(!i||!Array.isArray(i.entries))return[];let a=i.entries.map(e=>({name:e.name,path:k(e.path),isDirectory:!!e.isDirectory,isFile:!e.isDirectory,isSymbolicLink:!1}));return this.listDirectoryCache.set(n,{entries:a,expiresAt:Date.now()+Mt}),a}catch(e){throw console.error(`Failed to list directory contents:`,e),e}try{let r=new URLSearchParams;e&&e.trim().length>0&&r.set(`path`,e),t?.respectGitignore&&r.set(`respectGitignore`,`true`);let i=r.toString(),a=await h(`${this.baseUrl}/fs/list${i?`?${i}`:``}`);if(!a.ok){let e=await a.json().catch(()=>({})),t=typeof e.error==`string`?e.error:`Failed to list directory`;throw Error(t)}let o=await a.json();if(!o||!Array.isArray(o.entries))return[];let s=o.entries;return this.listDirectoryCache.set(n,{entries:s,expiresAt:Date.now()+Mt}),s}catch(e){throw console.error(`Failed to list directory contents:`,e),e}})().finally(()=>{this.listDirectoryInFlight.get(n)===o&&this.listDirectoryInFlight.delete(n)});return this.listDirectoryInFlight.set(n,o),o}async searchFiles(e,t){let n=typeof t?.directory==`string`&&t.directory.trim().length>0?t.directory.trim():this.currentDirectory,r=n?k(n):null,i=n?this.getScopedApiClient(n):this.client;try{let n=await i.find.files({query:e,limit:typeof t?.limit==`number`&&Number.isFinite(t.limit)?t.limit:void 0,dirs:t?.dirs===!1||t?.type===`file`?`false`:`true`,type:t?.type});return(Array.isArray(n?.data)?n.data:[]).map(e=>{let t=k(e),n=t.split(`/`).filter(Boolean).pop()||t;return{name:n,path:k(r?`${r}/${t}`:t),relativePath:t,extension:n.includes(`.`)?n.split(`.`).pop()?.toLowerCase():void 0}})}catch(e){throw console.error(`Failed to search files:`,e),e}}async getFilesystemHome(){let e=r();if(!e||e===`local`){let e=await re();if(e)return e}try{let e=await h(`${this.baseUrl}/fs/home`,{method:`GET`,headers:{Accept:`application/json`}});if(!e.ok){let t=await e.json().catch(()=>({})),n=typeof t.error==`string`&&t.error.length>0?t.error:`Failed to resolve home directory`;throw Error(n)}let t=await e.json();return t&&typeof t.home==`string`&&t.home.length>0?t.home:null}catch(e){return console.warn(`Failed to resolve filesystem home directory:`,e),null}}async setOpenCodeWorkingDirectory(e){if(!e||typeof e!=`string`||!e.trim())return console.warn(`[OpencodeClient] setOpenCodeWorkingDirectory: invalid path`,e),null;let t=`${this.baseUrl}/opencode/directory`;try{let n=await h(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:e})}),r=await n.json().catch(()=>null);if(!n.ok){let e=r??{},t=typeof e.error==`string`&&e.error.length>0?e.error:`Failed to update OpenCode working directory`;throw Error(t)}return r&&typeof r==`object`?r:{success:!0,restarted:!1,path:e}}catch(e){throw console.warn(`Failed to update OpenCode working directory:`,e),e}}},Pt=3e4,Ft=40,It=60,Lt=(e,t,n,r,i,a)=>{let o=e.trim(),s=t.trim().toLowerCase();return JSON.stringify([o,s,n,r,i,a])},Rt=(e,t)=>{try{let n=JSON.parse(e);return Array.isArray(n)&&n[0]===t}catch{return!1}},zt=ie()(ae((e,t)=>({cache:{},cacheKeys:[],inFlight:{},async searchFiles(n,r,i=It,a){if(!n||n.trim().length===0)return[];let o=n.trim(),s=typeof r==`string`?r.trim():``,c=!!a?.includeHidden,l=a?.respectGitignore??!0,u=a?.type===`directory`?`directory`:`file`,d=Lt(o,s,i,c,l,u),f=Date.now(),p=t().cache[d];if(p&&f-p.timestamp<Pt)return p.files;let m=t().inFlight[d];if(m)return m;let h=A.searchFiles(s,{directory:o,limit:i,includeHidden:c,respectGitignore:l,dirs:u!==`file`,type:u}).then(t=>(e(e=>{if(e.inFlight[d]!==h)return e;let n={...e.cache,[d]:{files:t,timestamp:Date.now()}},r=e.cacheKeys.filter(e=>e!==d);for(r.push(d);r.length>Ft;){let e=r.shift();e&&delete n[e]}return{cache:n,cacheKeys:r}}),t)).finally(()=>{e(e=>{if(e.inFlight[d]!==h)return e;let t={...e.inFlight};return delete t[d],{inFlight:t}})});return e(e=>({inFlight:{...e.inFlight,[d]:h}})),h},invalidateDirectory(t){if(!t||t.trim().length===0){e({cache:{},cacheKeys:[],inFlight:{}});return}let n=t.trim();e(e=>{let t={...e.cache},r=e.cacheKeys.filter(e=>!Rt(e,n)||(delete t[e],!1)),i=Object.entries(e.inFlight).filter(([e])=>!Rt(e,n));return{cache:t,cacheKeys:r,inFlight:Object.fromEntries(i)}})}}),{name:`file-search-store`})),Bt=()=>{if(typeof window>`u`)return!1;try{return window.localStorage.getItem(`openchamber_stream_debug`)===`1`}catch{return!1}},Vt=`openchamber_stream_perf`,j=()=>{if(typeof window>`u`)return!1;try{return window.localStorage.getItem(Vt)===`1`}catch{return!1}},Ht=()=>typeof performance<`u`&&typeof performance.now==`function`?performance.now():Date.now(),Ut=()=>{if(!j()||typeof window>`u`)return null;if(!window.__openchamberStreamPerfState){let e=Date.now();window.__openchamberStreamPerfState={counters:new Map,startedAt:e,lastUpdatedAt:e}}return window.__openchamberStreamPerfState},Wt=e=>Array.from(e.entries()).map(([e,t])=>({metric:e,count:t.count,avg:t.count>0?Number((t.total/t.count).toFixed(3)):0,max:Number(t.max.toFixed(3)),total:Number(t.total.toFixed(3)),last:Number(t.last.toFixed(3))})).sort((e,t)=>t.total-e.total||t.count-e.count),Gt=(e,t)=>{let n=Ut();if(!n)return;let r=n.counters.get(e)??{count:0,total:0,max:0,last:0};r.count+=1,r.total+=t,r.max=Math.max(r.max,t),r.last=t,n.counters.set(e,r),n.lastUpdatedAt=Date.now()},Kt=e=>{if(!(typeof window>`u`))try{if(e){window.localStorage.setItem(Vt,`1`),window.__openchamberStreamPerfState={counters:new Map,startedAt:Date.now(),lastUpdatedAt:Date.now()};return}window.localStorage.removeItem(Vt),delete window.__openchamberStreamPerfState,delete window.__openchamberVsCodeStreamPerfState}catch{}},qt=()=>{typeof window>`u`||(j()&&(window.__openchamberStreamPerfState={counters:new Map,startedAt:Date.now(),lastUpdatedAt:Date.now()}),window.__openchamberVsCodeStreamPerfState&&(window.__openchamberVsCodeStreamPerfState={...window.__openchamberVsCodeStreamPerfState,counters:new Map,startedAt:Date.now(),lastUpdatedAt:Date.now()}))},Jt=()=>{if(typeof window>`u`)return{enabled:!1,startedAt:null,lastUpdatedAt:null,durationMs:0,entries:[]};let e=window.__openchamberStreamPerfState;return!j()||!e?{enabled:!1,startedAt:null,lastUpdatedAt:null,durationMs:0,entries:[]}:{enabled:!0,startedAt:e.startedAt,lastUpdatedAt:e.lastUpdatedAt,durationMs:Math.max(0,Date.now()-e.startedAt),entries:Wt(e.counters)}},Yt=()=>{if(typeof window>`u`)return{enabled:!1,startedAt:null,lastUpdatedAt:null,durationMs:0,entries:[]};let e=window.__openchamberVsCodeStreamPerfState;if(!j()||!e)return{enabled:!1,startedAt:null,lastUpdatedAt:null,durationMs:0,entries:[]};let t=typeof e.startedAt==`number`?e.startedAt:null;return{enabled:!0,startedAt:t,lastUpdatedAt:typeof e.lastUpdatedAt==`number`?e.lastUpdatedAt:null,durationMs:t?Math.max(0,Date.now()-t):0,entries:Wt(e.counters)}},Xt=(e,t=1)=>{Gt(e,t)},Zt=(e,t)=>{Gt(e,t)},Qt=(e,t)=>{if(!j())return t();let n=Ht();try{return t()}finally{Gt(e,Ht()-n)}},M=null,$t=0,N=c(),en=p(`lastDirectory`,{storage:N}),tn=typeof en==`string`&&en.length>0,P=e=>{try{zt.getState().invalidateDirectory(e)}catch(e){console.warn(`Failed to invalidate file search cache:`,e)}},F=e=>{let t=e.trim();if(!t)return t;let n=t.replace(/\\/g,`/`).replace(/^([a-z]):/,(e,t)=>t.toUpperCase()+`:`);return n.length>1?n.replace(/\/+$/,``):n},nn=(e,t)=>{let n=e.trim();return n.startsWith(`~`)?n===`~`?t||n:(n.startsWith(`~/`)||n.startsWith(`~\\`))&&t?`${t}${n.slice(1)}`:n:n},I=(e,t)=>F(nn(e,t)),rn=()=>{let e=p(`homeDirectory`,{storage:N});if(typeof e!=`string`||e.trim().length===0)return null;let t=F(e);return t.length>0?t:null},an=()=>{let e=p(`lastDirectory`,{storage:N});if(typeof e!=`string`||e.trim().length===0)return null;let t=F(e);return t.length>0?t:null},on=()=>{if(typeof process>`u`)return null;let e={},t=e?.HOME||e?.USERPROFILE||(e?.HOMEDRIVE&&e?.HOMEPATH?`${e.HOMEDRIVE}${e.HOMEPATH}`:void 0);if(typeof t==`string`&&t.trim().length>0){let e=F(t);return e.length>0?e:null}let n=process?.cwd?.();if(typeof n==`string`&&n.trim().length>0){let e=F(n);return e.length>0?e:null}return null},L=()=>{if(typeof window<`u`){if(M)return M;let e=typeof window.__OPENCHAMBER_HOME__==`string`&&window.__OPENCHAMBER_HOME__.length>0?window.__OPENCHAMBER_HOME__:null;if(e&&e.length>0)return M=e,m(`homeDirectory`,e,{storage:N}),e;let t=rn();if(t&&!f())return M=t,t}return on()||`/`},sn=e=>{if(typeof e!=`string`)return null;let t=e.trim();if(!t)return null;let n=t.replace(/\\/g,`/`);if(n.length>1){let e=n.replace(/\/+$/,``);if(e&&e.length>0)return e===`/`?null:e}return n===`/`||n.length===0?null:n},cn=e=>(M=e,typeof window<`u`&&m(`homeDirectory`,e,{storage:N}),_({homeDirectory:e}),e),ln=async()=>{let e=e=>{let t=sn(e);return t?cn(t):null};try{let t=e(await A.getFilesystemHome());if(t)return t}catch(e){console.warn(`Failed to obtain filesystem home directory:`,e)}try{let t=e((await A.getSystemInfo())?.homeDirectory);if(t)return t}catch(e){console.warn(`Failed to get home directory from system info:`,e)}try{let t=e(await re());if(t)return t}catch(e){console.warn(`Failed to obtain desktop-integrated home directory:`,e)}let t=L();return e(t)||t},R=(()=>{if(!f())return null;let e=window.__VSCODE_CONFIG__?.workspaceFolder;if(typeof e!=`string`||e.trim().length===0)return null;let t=F(e);return t.length>0?t:null})()||L(),z=(()=>{let e=an();return e&&!f()?I(e,R):R})();z&&A.setDirectory(z);var un=!!(R&&R!==`/`),B=ie()(ae((e,t)=>({currentDirectory:z,directoryHistory:[z],historyIndex:0,homeDirectory:R,hasPersistedDirectory:tn,isHomeReady:un,isSwitchingDirectory:!1,setDirectory:(n,r)=>{let i=I(n,M||t().homeDirectory||p(`homeDirectory`,{storage:N}));Bt(),le(t().currentDirectory,i)&&(A.setDirectory(i),P(),e(e=>{let t=[...e.directoryHistory.slice(0,e.historyIndex+1),i];return m(`lastDirectory`,i,{storage:N}),_({lastDirectory:i}),{currentDirectory:i,directoryHistory:t,historyIndex:t.length-1,hasPersistedDirectory:!0,isHomeReady:!0,isSwitchingDirectory:!1}}))},goBack:()=>{let n=t();if(n.historyIndex>0){let t=n.historyIndex-1,r=n.directoryHistory[t];A.setDirectory(r),P(),m(`lastDirectory`,r,{storage:N}),_({lastDirectory:r}),e({currentDirectory:r,historyIndex:t,hasPersistedDirectory:!0,isHomeReady:!0,isSwitchingDirectory:!1})}},goForward:()=>{let n=t();if(n.historyIndex<n.directoryHistory.length-1){let t=n.historyIndex+1,r=n.directoryHistory[t];A.setDirectory(r),P(),m(`lastDirectory`,r,{storage:N}),_({lastDirectory:r}),e({currentDirectory:r,historyIndex:t,hasPersistedDirectory:!0,isHomeReady:!0,isSwitchingDirectory:!1})}},goToParent:()=>{let{currentDirectory:e,setDirectory:n}=t();if(e===(M||t().homeDirectory||L())||e===`/`)return;let r=e.endsWith(`/`)?e.slice(0,-1):e,i=r.lastIndexOf(`/`);n(i===-1?M||L():i===0?`/`:r.substring(0,i))},goHome:async()=>{let e=M||t().homeDirectory||await ln();t().setDirectory(e)},synchronizeHomeDirectory:n=>{let r=t(),i=n;M=i;let a=r.homeDirectory!==i,o=p(`lastDirectory`,{storage:N}),s=typeof o==`string`&&o.length>0,c=!s&&(r.currentDirectory===`/`||r.currentDirectory===r.homeDirectory||!r.currentDirectory);if(!a&&!c){r.isHomeReady||e({isHomeReady:!0});return}let l=typeof i==`string`&&i!==``&&i!==`/`,u=r.currentDirectory?I(r.currentDirectory,i):r.currentDirectory,d=r.directoryHistory.map(e=>I(e,i)),f=d.some((e,t)=>e!==r.directoryHistory[t]),h=!!(u&&u!==r.currentDirectory),g={homeDirectory:i,hasPersistedDirectory:s,isHomeReady:l};if(c?(g.currentDirectory=i,g.directoryHistory=[i],g.historyIndex=0,g.isSwitchingDirectory=!1):(h||f)&&(g.currentDirectory=u,g.directoryHistory=d,g.historyIndex=Math.min(r.historyIndex,d.length-1),g.isSwitchingDirectory=!1),e(()=>g),(c||h)&&l){let e=c?i:u;A.setDirectory(e),P(),m(`lastDirectory`,e,{storage:N}),_({lastDirectory:e})}_({homeDirectory:i})}}),{name:`directory-store`}));typeof window<`u`&&(ln().then(e=>{B.getState().synchronizeHomeDirectory(e)}),u(e=>{M=null;let n=++$t;if(t(e)){let e=rn(),t=an(),n=e||`/`,r=t||n;M=e,B.setState({currentDirectory:r,directoryHistory:[r],historyIndex:0,homeDirectory:n,hasPersistedDirectory:!!t,isHomeReady:!!(e&&e!==`/`),isSwitchingDirectory:!1}),r&&(A.setDirectory(r),P())}ln().then(e=>{n===$t&&B.getState().synchronizeHomeDirectory(e)})}));var dn=`x-openchamber-target-port`,fn=()=>{let e=a();for(let[t,n]of Object.entries(e)){if(t.trim().toLowerCase()!==dn)continue;let e=n.trim();return e?{[dn]:e}:void 0}},pn=(e,t)=>{let n=s();return n?n.openWebSocket(d(e),t,fn()):l(t?new WebSocket(e,t):new WebSocket(e))},V=`/api/git`,mn=1200,hn=5e3,gn=2,_n=5e3,vn=`${V}/worktrees/queue-activation`,yn=`message_queue_activation_pending`,bn=`worktree_lifecycle_busy`,xn=`worktree_activation_stale`,Sn=5e3,Cn=3e4,wn=[0,500,1e3,2e3,4e3,8e3,14e3],H=new Map,U=new Map,Tn=new Map,W=new Map,G=new Map,K=new Map,q=new Map,En=new Map,J=new Map,Dn=new Set,Y=0,On=[],kn=()=>Y<gn?(Y+=1,Promise.resolve()):new Promise(e=>{On.push(e)}),An=()=>{let e=On.shift();if(e){e();return}Y=Math.max(0,Y-1)},X=async e=>{await kn();try{return await e()}finally{An()}},jn=Symbol.for(`openchamber.git.discoveryGated`),Mn=e=>(Object.defineProperty(e,jn,{value:!0,configurable:!0}),e),Nn=e=>typeof e==`function`&&e[jn]===!0,Z=e=>e.trim(),Pn=(e,t)=>t===`light`?`${Z(e)}::light`:Z(e),Fn=e=>Tn.get(Z(e))??0,Q=e=>{let t=Z(e);Tn.set(t,Fn(e)+1);for(let e of Array.from(H.keys()))(e===t||e.startsWith(`${t}::`))&&H.delete(e);for(let e of Array.from(U.keys()))(e===t||e.startsWith(`${t}::`))&&U.delete(e)};function $(e,t,n){let r={...n};return t&&(r.directory=t),i().api(e,r)}var In=(e,t,n)=>{let r=Z(e);if(!r)return;let i=Date.now()+_n;W.set(r,{value:t,expiresAt:i});let a=typeof n==`string`&&n?n:e;K.set(r,{value:{root:a},expiresAt:i})};async function Ln(e){let t=Array.from(new Set(e.map(e=>Z(e)).filter(Boolean))),n=new Map;if(t.length===0)return n;let r=Date.now(),a=[];for(let e of t){let t=W.get(e),i=K.get(e);if(t&&t.expiresAt>r&&i&&i.expiresAt>r){n.set(e,{isGitRepository:t.value,primaryRoot:i.value.root});continue}a.push(e)}if(a.length===0)return n;let o=e=>{for(let t of e){let e=typeof t.directory==`string`?Z(t.directory):``;if(!e)continue;let r=!!t.isGitRepository,i=typeof t.primaryRoot==`string`&&t.primaryRoot?t.primaryRoot:null;In(e,r,i),n.set(e,{isGitRepository:r,primaryRoot:i})}},s=async e=>{await Promise.all(e.map(async e=>{try{let[t,r]=await Promise.all([Rn(e),Bn(e).then(e=>e.root).catch(()=>e)]);In(e,t,t?r:null),n.set(e,{isGitRepository:t,primaryRoot:t?r:null})}catch{In(e,!1,null),n.set(e,{isGitRepository:!1,primaryRoot:null})}}))};try{await X(async()=>{let e=new URLSearchParams;for(let t of a)e.append(`directories`,t);let t=i().api(`${V}/discover`),n=e.toString(),r=n?t.includes(`?`)?`${t}&${n}`:`${t}?${n}`:t,s=await h(r);if(s.status===501||!s.ok)throw Error(`Batch git discover unavailable: ${s.status} ${s.statusText}`);let c=await s.json().catch(()=>null),l=Array.isArray(c)?c:[];if(l.length===0&&a.length>0)throw Error(`Batch git discover returned empty payload`);o(l)})}catch{}let c=a.filter(e=>!n.has(e));return c.length>0&&await s(c),n}async function Rn(e){let t=Z(e),n=Date.now(),r=W.get(t);if(r&&r.expiresAt>n)return r.value;let i=G.get(t);if(i)return i;let a=(async()=>{let n=await h($(`${V}/check`,e));if(!n.ok)throw Error(`Failed to check git repository: ${n.statusText}`);let r=!!(await n.json()).isGitRepository;return W.set(t,{value:r,expiresAt:Date.now()+hn}),r})();G.set(t,a);try{return await a}finally{G.get(t)===a&&G.delete(t)}}async function zn(e,t){let n=t?.mode,r=Pn(e,n),i=Date.now(),a=H.get(r);if(a&&a.expiresAt>i)return a.value;let o=U.get(r);if(o)return o;let s=(async()=>{let t=Fn(e),i=await h($(`${V}/status`,e,n?{mode:n}:void 0));if(!i.ok)throw Error(`Failed to get git status: ${i.statusText}`);let a=await i.json();return Fn(e)===t&&H.set(r,{value:a,expiresAt:Date.now()+mn}),a})();U.set(r,s);try{return await s}finally{U.get(r)===s&&U.delete(r)}}async function Bn(e){let t=Z(e),n=Date.now(),r=K.get(t);if(r&&r.expiresAt>n)return r.value;let i=q.get(t);if(i)return i;let a=X(async()=>{let n=await h($(`${V}/primary-root`,e));if(!n.ok)throw Error(`Failed to resolve git primary root: ${n.statusText}`);let r=await n.json().catch(()=>({})),i={root:typeof r.root==`string`&&r.root?r.root:e};return K.set(t,{value:i,expiresAt:Date.now()+_n}),i});q.set(t,a);try{return await a}finally{q.get(t)===a&&q.delete(t)}}async function Vn(e){let t=await h($(`${V}/toplevel`,e));if(!t.ok)throw Error(`Failed to resolve git toplevel: ${t.statusText}`);let n=await t.json().catch(()=>({}));return{root:typeof n.root==`string`&&n.root?n.root:e}}async function Hn(e,t){let{path:n,staged:r,contextLines:i}=t;if(!n)throw Error(`path is required to fetch git diff`);let a=await h($(`${V}/diff`,e,{path:n,staged:r?`true`:void 0,context:i}));if(!a.ok)throw Error(`Failed to get git diff: ${a.statusText}`);return a.json()}async function Un(e,t){let{path:n,staged:r}=t;if(!n)throw Error(`path is required to fetch git file diff`);let i=await h($(`${V}/file-diff`,e,{path:n,staged:r?`true`:void 0}));if(!i.ok)throw Error(`Failed to get git file diff: ${i.statusText}`);return i.json()}async function Wn(e,t,n){if(!t)throw Error(`path is required to revert git changes`);let r=await h($(`${V}/revert`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t,scope:n?.scope})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to revert git changes`)}Q(e)}async function Gn(e,t){await Kn(e,[t])}async function Kn(e,t){let n=t.map(e=>e.trim()).filter(Boolean);if(n.length===0)throw Error(`path is required to stage git changes`);let r=await h($(`${V}/stage`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({paths:n})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to stage git changes`)}Q(e)}async function qn(e,t){await Jn(e,[t])}async function Jn(e,t){let n=t.map(e=>e.trim()).filter(Boolean);if(n.length===0)throw Error(`path is required to unstage git changes`);let r=await h($(`${V}/unstage`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({paths:n})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to unstage git changes`)}Q(e)}async function Yn(e,t,n){await Qn(e,t,n,`stage`)}async function Xn(e,t,n){await Qn(e,t,n,`unstage`)}async function Zn(e,t,n){await Qn(e,t,n,`discard`)}async function Qn(e,t,n,r){if(!t)throw Error(`path is required to apply a git hunk`);if(typeof n!=`string`||!n.trim())throw Error(`patch is required to apply a git hunk`);let i=await h($(`${V}/apply-hunk`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({path:t,patch:n,action:r})});if(!i.ok){let e=await i.json().catch(()=>({error:i.statusText}));throw Error(e.error||`Failed to apply git hunk`)}Q(e)}async function $n(e){if(!e)return!1;let t=await h($(`${V}/worktree-type`,e));if(!t.ok)throw Error(`Failed to detect worktree type: ${t.statusText}`);return!!(await t.json()).linked}async function er(e,t){let n=await h($(`${V}/branches`,e),{signal:t?.signal});if(!n.ok)throw Error(`Failed to get branches: ${n.statusText}`);return n.json()}async function tr(e,t){if(!t?.branch)throw Error(`branch is required to delete a branch`);let n=await h($(`${V}/branches`,e),{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to delete branch`)}return n.json()}async function nr(e,t){if(!t?.branch)throw Error(`branch is required to delete remote branch`);let n=await h($(`${V}/remote-branches`,e),{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to delete remote branch`)}return n.json()}async function rr(e,t){let n=t?.remote?.trim();if(!n)throw Error(`remote is required to remove a remote`);let r=await h($(`${V}/remotes`,e),{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({remote:n})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to remove remote`)}return r.json()}async function ir(e,t,n){if(!Array.isArray(t)||t.length===0)throw Error(`No files provided to generate commit message`);let r={files:t};n?.zenModel&&(r.zenModel=n.zenModel),n?.providerId&&(r.providerId=n.providerId),n?.modelId&&(r.modelId=n.modelId);let i=await h($(`${V}/commit-message`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(r)});if(!i.ok){let e=await i.json().catch(()=>({error:i.statusText}));console.error(`[git-generation][browser] http error`,{status:i.status,statusText:i.statusText,error:e});let t=typeof e?.traceId==`string`&&e.traceId?` (traceId: ${e.traceId})`:``;throw Error(`${e.error||`Failed to generate commit message`}${t}`)}let a=await i.json();if(!a?.message||typeof a.message!=`object`)throw Error(`Malformed commit generation response`);return{message:{subject:typeof a.message.subject==`string`&&a.message.subject.trim().length>0?a.message.subject.trim():``,highlights:Array.isArray(a.message.highlights)?a.message.highlights.filter(e=>typeof e==`string`&&e.trim().length>0).map(e=>e.trim()):[]}}}async function ar(e,t){let{base:n,head:r,context:i,zenModel:a,providerId:o,modelId:s}=t;if(!n||!r)throw Error(`base and head are required`);let c={base:n,head:r};i?.trim()&&(c.context=i.trim()),a&&(c.zenModel=a),o&&(c.providerId=o),s&&(c.modelId=s);let l=await h($(`${V}/pr-description`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(c)});if(!l.ok){let e=await l.json().catch(()=>({error:l.statusText}));throw Error(e.error||`Failed to generate PR description`)}let u=await l.json().catch(()=>null),d=typeof u?.title==`string`?u.title:``,f=typeof u?.body==`string`?u.body:``;if(!d&&!f)throw Error(`Malformed PR description response`);return{title:d,body:f}}async function or(e){let t=Z(e),n=Date.now(),r=En.get(t);if(r&&r.expiresAt>n)return r.value;let i=J.get(t);if(i)return i;let a=X(async()=>{let n=await h($(`${V}/worktrees`,e));if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to list worktrees`)}let r=await n.json();return En.set(t,{value:r,expiresAt:Date.now()+_n}),r});J.set(t,a);try{return await a}finally{J.get(t)===a&&J.delete(t)}}Mn(or);async function sr(e,t){let n=await h($(`${V}/worktrees/validate`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t??{})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to validate worktree`)}return n.json()}async function cr(e){let t=await h($(`${V}/worktrees/bootstrap-status`,e));if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to get worktree bootstrap status`)}return t.json()}async function lr(e,t){let n=await h($(`${V}/worktrees/preview`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t??{})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to preview worktree`)}return n.json()}var ur=e=>typeof e==`string`&&e.length>0,dr=e=>{if(!e||typeof e!=`object`)return null;let t=e;if(!ur(t.name)||!ur(t.path))return null;let n={head:typeof t.head==`string`?t.head:``,name:t.name,branch:typeof t.branch==`string`?t.branch:``,path:t.path};return t.directoryCreated===!0&&(n.directoryCreated=!0),t.bootstrapStatus&&typeof t.bootstrapStatus==`object`&&(n.bootstrapStatus=t.bootstrapStatus),n},fr=(e,t,n)=>{if(e!==503||!t||typeof t!=`object`)return null;let r=t;if(r.code!==yn)return null;let i=dr(r.worktree);if(!i)return null;let a=r.repair;if(!a||typeof a!=`object`)return null;let o=a;if(o.method!==`POST`||o.path!==vn)return null;let s=o.body;if(!s||typeof s!=`object`)return null;let c=s;return c.projectDirectory!==n||c.directory!==i.path?null:i},pr=(e,t,n,r)=>`${e}\u0000${t}\u0000${n}\u0000${r}`,mr=e=>new Promise(t=>{setTimeout(t,e)}),hr=async e=>{if(e.status===409){let t=await e.json().catch(()=>null);return t?.code===bn||t?.code===xn}return e.status===503&&(await e.json().catch(()=>null))?.code===yn},gr=e=>e===400||e===401||e===403||e===501,_r=(e,t)=>{let r=n(),i=o(),a=pr(r,i,e,t);if(Dn.has(a))return;Dn.add(a);let s=()=>n()===r&&o()===i;(async()=>{let n=Date.now(),r=0;for(;Date.now()-n<Cn;){if(!s())return;let i=wn[Math.min(r,wn.length-1)]??0;if(i>0){let e=Cn-(Date.now()-n);if(e<=0||(await mr(Math.min(i,e)),!s()))return}let a=new AbortController,o=setTimeout(()=>a.abort(),Sn);try{let n=await h($(vn,void 0),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({projectDirectory:e,directory:t}),signal:a.signal});if(n.ok||gr(n.status))return;if(await hr(n)){r+=1;continue}return}catch{r+=1}finally{clearTimeout(o)}}})().catch(()=>{}).finally(()=>{Dn.delete(a)})};async function vr(e,t){let n=await h($(`${V}/worktrees`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t??{})}),r=await n.json().catch(()=>null);if(n.ok){let e=dr(r);if(e)return e;if(r&&typeof r==`object`)return r;throw Error(`Failed to create worktree`)}let i=fr(n.status,r,e);if(i)return _r(e,i.path),i;let a=r&&typeof r==`object`?r:{error:n.statusText};throw Error(a.error||`Failed to create worktree`)}async function yr(e,t){let n=await h($(`${V}/worktrees`,e),{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t??{})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to delete worktree`)}return n.json()}async function br(e,t,n={}){let r=await h($(`${V}/commit`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({message:t,addAll:n.addAll??!1,files:n.files,stageFiles:n.stageFiles})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to create commit`)}let i=await r.json();return Q(e),i}async function xr(e,t={}){let n=await h($(`${V}/push`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to push`)}let r=await n.json();return Q(e),r}async function Sr(e,t={}){let n=await h($(`${V}/pull`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to pull`)}let r=await n.json();return Q(e),r}async function Cr(e,t={}){let n=await h($(`${V}/fetch`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to fetch`)}let r=await n.json();return Q(e),r}async function wr(e){let t=await h($(`${V}/stashes`,e));if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to list stashes`)}return t.json()}async function Tr(e,t){let n=await h($(`${V}/stashes/file-counts`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({refs:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to count stash files`)}return n.json()}async function Er(e,t={}){let n=await h($(`${V}/stash`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to stash changes`)}return n.json()}var Dr=async(e,t,n)=>{let r=await h($(`${V}/${t}`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to ${t}`)}return r.json()},Or=(e,t)=>Dr(e,`stash/apply`,t),kr=(e,t)=>Dr(e,`stash/pop`,t),Ar=(e,t)=>Dr(e,`stash/drop`,t);async function jr(e,t){let n=await h($(`${V}/checkout`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({branch:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to checkout branch`)}return n.json()}async function Mr(e,t,n){let r=await h($(`${V}/branches`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:t,startPoint:n})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to create branch`)}return r.json()}async function Nr(e,t,n){let r=await h($(`${V}/branches/rename`,e),{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({oldName:t,newName:n})});if(!r.ok){let e=await r.json().catch(()=>({error:r.statusText}));throw Error(e.error||`Failed to rename branch`)}return r.json()}async function Pr(e,t={}){let n=await h($(`${V}/log`,e,{maxCount:t.maxCount,from:t.from,to:t.to,file:t.file,all:t.all?`true`:void 0}));if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(`Failed to get git log: ${e.error||n.statusText}`)}return n.json()}async function Fr(e,t){let n=await h($(`${V}/commit-files`,e,{hash:t}));if(!n.ok)throw Error(`Failed to get commit files: ${n.statusText}`);return n.json()}async function Ir(e,t,n,r){let i=await h($(`${V}/commit-file-diff`,e,{hash:t,path:n,binary:r?`true`:void 0}));if(!i.ok)throw Error(`Failed to get commit file diff: ${i.statusText}`);return i.json()}async function Lr(){let e=await h($(`${V}/identities`,void 0));if(!e.ok)throw Error(`Failed to get git identities: ${e.statusText}`);return e.json()}async function Rr(e){let t=await h($(`${V}/identities`,void 0),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e)});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to create git identity`)}return t.json()}async function zr(e,t){let n=await h($(`${V}/identities/${e}`,void 0),{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to update git identity`)}return n.json()}async function Br(e){let t=await h($(`${V}/identities/${e}`,void 0),{method:`DELETE`});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to delete git identity`)}}async function Vr(e){if(!e)return null;let t=await h($(`${V}/current-identity`,e));if(!t.ok)throw Error(`Failed to get current git identity: ${t.statusText}`);let n=await t.json();return n?{userName:n.userName??null,userEmail:n.userEmail??null,sshCommand:n.sshCommand??null}:null}async function Hr(e){if(!e)return!1;let t=await h($(`${V}/has-local-identity`,e));if(!t.ok)throw Error(`Failed to check local identity: ${t.statusText}`);return(await t.json().catch(()=>null))?.hasLocalIdentity===!0}async function Ur(){let e=await h($(`${V}/global-identity`,void 0));if(!e.ok)throw Error(`Failed to get global git identity: ${e.statusText}`);let t=await e.json();return!t||!t.userName&&!t.userEmail?null:{userName:t.userName??null,userEmail:t.userEmail??null,sshCommand:t.sshCommand??null}}async function Wr(e,t){let n=await h($(`${V}/set-identity`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({profileId:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to set git identity`)}return n.json()}async function Gr(){let e=await h($(`${V}/discover-credentials`,void 0));if(!e.ok)throw Error(`Failed to discover git credentials: ${e.statusText}`);return e.json()}async function Kr(e,t){let n=await h($(`${V}/remotes`,e),{signal:t?.signal});if(!n.ok)throw Error(`Failed to get remotes: ${n.statusText}`);return n.json()}async function qr(e,t){let n=await h($(`${V}/rebase`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to rebase`)}return n.json()}async function Jr(e){let t=await h($(`${V}/rebase/abort`,e),{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to abort rebase`)}return t.json()}async function Yr(e,t){let n=await h($(`${V}/merge`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(t)});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to merge`)}return n.json()}async function Xr(e,t){let n=await h($(`${V}/checkout-commit`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({hash:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to checkout commit`)}return n.json()}async function Zr(e,t){let n=await h($(`${V}/cherry-pick`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({hash:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to cherry-pick`)}return n.json()}async function Qr(e,t){let n=await h($(`${V}/revert-commit`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({hash:t})});if(!n.ok){let e=await n.json().catch(()=>({error:n.statusText}));throw Error(e.error||`Failed to revert commit`)}return n.json()}async function $r(e,t,n,r){let i=await h($(`${V}/reset-to-commit`,e),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({hash:t,mode:n,force:r})});if(!i.ok){let e=await i.json().catch(()=>({error:i.statusText}));throw Error(e.error||`Failed to reset`)}return i.json()}async function ei(e){let t=await h($(`${V}/merge/abort`,e),{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to abort merge`)}return t.json()}async function ti(e){let t=await h($(`${V}/rebase/continue`,e),{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to continue rebase`)}return t.json()}async function ni(e){let t=await h($(`${V}/merge/continue`,e),{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({error:t.statusText}));throw Error(e.error||`Failed to continue merge`)}return t.json()}async function ri(e,t){return await Er(e,{message:t?.message}),{success:!0}}async function ii(e){return await kr(e,{ref:`stash@{0}`}),{success:!0}}async function ai(e){let t=await h($(`${V}/conflict-details`,e));if(!t.ok)throw Error(`Failed to get conflict details: ${t.statusText}`);return t.json()}async function oi(e,t){let n=await h(`${V}/validate-directory`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({directory:e,worktreeRoot:t})});if(!n.ok)throw Error(`Failed to validate worktree directory: ${n.statusText}`);return n.json()}async function si(e){let t=await h(`${V}/canonicalize-worktree-state`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({directory:e})});if(!t.ok)throw Error(`Failed to canonicalize worktree state: ${t.statusText}`);return t.json()}export{Bn as $,Hn as A,C as At,xr as B,He as Bt,ir as C,Kt as Ct,ai as D,Zt as Dt,Fr as E,Qt as Et,cr as F,Me as Ft,or as G,xe as Gt,Nn as H,Pe as Ht,Ur as I,Ne as It,lr as J,Yr as K,Kr as L,Re as Lt,Lr as M,nt as Mt,Pr as N,Be as Nt,Vr as O,zt as Ot,zn as P,je as Pt,$r as Q,Cr as R,ze as Rt,Ar as S,qt as St,Ir as T,Xt as Tt,$n as U,ye as Ut,Hr as V,We as Vt,wr as W,ve as Wt,rr as X,qr as Y,Nr as Z,Br as _,X as _t,Rn as a,Gn as at,Gr as b,Jt as bt,Zr as c,ri as ct,Tr as d,qn as dt,Vn as et,Mr as f,Jn as ft,tr as g,oi as gt,vr as h,sr as ht,si as i,Wr as it,Un as j,rt as jt,er as k,A as kt,ni as l,Er as lt,Rr as m,zr as mt,Jr as n,Wn as nt,jr as o,Kn as ot,br as p,Xn as pt,kr as q,Or as r,Zn as rt,Xr as s,Yn as st,ei as t,Qr as tt,ti as u,ii as ut,yr as v,pn as vt,ar as w,Bt as wt,Ln as x,Yt as xt,nr as y,B as yt,Sr as z,Ve as zt};
|