@jxsuite/studio 4.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/chunks/{2020-xp8vnwma.js → 2020-n6tfwnda.js} +2 -2
  2. package/dist/chunks/{Overlay.dev-723bv0df.js → Overlay.dev-etqjwyf9.js} +4 -4
  3. package/dist/chunks/cf-account-picker-en86v7x7.js +163 -0
  4. package/dist/chunks/{content-source-t88vb2dr.js → content-source-48xg86wj.js} +17 -17
  5. package/dist/chunks/{convert-to-repeater-dhw1nrz9.js → convert-to-repeater-43tfn7cs.js} +24 -24
  6. package/dist/chunks/{entry-commands-6z6bhxg0.js → entry-commands-e63f1xc0.js} +20 -20
  7. package/dist/chunks/{extension-sections-3ydgjbdy.js → extension-sections-txv08xxg.js} +23 -23
  8. package/dist/chunks/{file-ops-rskmhxyq.js → file-ops-wbh4hhsx.js} +16 -16
  9. package/dist/chunks/{files-0cratsr0.js → files-3kfkwhk4.js} +25 -24
  10. package/dist/chunks/{focus-trap.esm-ggawf1hy.js → focus-trap.esm-9t2drp0g.js} +6 -5
  11. package/dist/chunks/{format-host-tgcmfs4p.js → format-host-w16q81tf.js} +2 -2
  12. package/dist/chunks/fs-events-hrrg328g.js +1 -1
  13. package/dist/chunks/{git-panel-0yywyk76.js → git-panel-532whr1y.js} +16 -15
  14. package/dist/chunks/{index-nj44jpzj.js → index-wcnt3r9g.js} +2 -2
  15. package/dist/chunks/{jx-validate-8q2g05x1.js → jx-validate-8er6gbxy.js} +3 -3
  16. package/dist/chunks/{layers-panel-z3tqe5cd.js → layers-panel-07hm7g5j.js} +19 -19
  17. package/dist/chunks/{monaco-setup-rws7k4br.js → monaco-setup-vx9bhp1d.js} +2 -2
  18. package/dist/chunks/{publish-panel-54jvhskq.js → publish-panel-v9st96ja.js} +11 -10
  19. package/dist/chunks/{quick-search-cgfmjwq5.js → quick-search-zccjp6gv.js} +26 -25
  20. package/dist/chunks/{right-panel-cqp8bc4v.js → right-panel-vm3b6kwy.js} +17 -17
  21. package/dist/chunks/{sp-overlay.dev-yztmtrs1.js → sp-overlay.dev-qgvhnxf4.js} +5 -5
  22. package/dist/chunks/{sp-tooltip.dev-xcvpnqr0.js → sp-tooltip.dev-4sastdnw.js} +3 -3
  23. package/dist/chunks/{studio-txwkm6p9.js → studio-0bq6eh7v.js} +2 -2
  24. package/dist/chunks/studio-1ngbejft.js +181 -0
  25. package/dist/chunks/{studio-gv8vvshc.js → studio-1wagb550.js} +3 -3
  26. package/dist/chunks/{studio-kjjsjak4.js → studio-2b946z26.js} +58 -57
  27. package/dist/chunks/{studio-4pqqxbrt.js → studio-3bqpr0zh.js} +16 -16
  28. package/dist/chunks/{studio-v38hmvx1.js → studio-4b5z1x43.js} +42 -8
  29. package/dist/chunks/{studio-9c4k4vhv.js → studio-4n2b5gzb.js} +4 -4
  30. package/dist/chunks/{studio-p8j86wag.js → studio-4r1pv6zf.js} +2 -2
  31. package/dist/chunks/{studio-mmv72a27.js → studio-5fx3g9jg.js} +29 -48
  32. package/dist/chunks/{studio-5rywrkxz.js → studio-5myknm0a.js} +42 -42
  33. package/dist/chunks/{studio-sf7zjgv1.js → studio-6yw4y3my.js} +3 -3
  34. package/dist/chunks/{studio-pdfjntbk.js → studio-950k0dx6.js} +35 -35
  35. package/dist/chunks/{studio-eenfkt4e.js → studio-ahn3pdgx.js} +5 -5
  36. package/dist/chunks/{studio-eesa1myv.js → studio-b55y6ewx.js} +9 -9
  37. package/dist/chunks/{studio-cb12yz9w.js → studio-cmb03bg5.js} +99 -1264
  38. package/dist/chunks/studio-dm19q43r.js +195 -0
  39. package/dist/chunks/{studio-ahjfdy6e.js → studio-ef49pnzx.js} +6 -6
  40. package/dist/chunks/{studio-wx5609xd.js → studio-ew0djmhg.js} +10 -10
  41. package/dist/chunks/{studio-9r6j5ev1.js → studio-f3wqjtk5.js} +4 -3
  42. package/dist/chunks/{studio-8swrjbny.js → studio-fbf92ckf.js} +14 -14
  43. package/dist/chunks/{studio-4q0wznzf.js → studio-gcye7qka.js} +442 -126
  44. package/dist/chunks/{studio-ex8zyp98.js → studio-gfgb8pe6.js} +23 -184
  45. package/dist/chunks/{studio-r1r7afxx.js → studio-jc994dnr.js} +24 -24
  46. package/dist/chunks/{studio-yxrkyv8a.js → studio-jkftxyvz.js} +52 -3416
  47. package/dist/chunks/{studio-hbtp0eh1.js → studio-msd847zn.js} +13 -13
  48. package/dist/chunks/{studio-kyk2v92a.js → studio-mtfnaqs9.js} +14 -14
  49. package/dist/chunks/{studio-vadzgkrz.js → studio-n6j9t10q.js} +2 -2
  50. package/dist/chunks/{studio-68n67094.js → studio-q9jd1a60.js} +4 -4
  51. package/dist/chunks/studio-qcy05dp8.js +1743 -0
  52. package/dist/chunks/{studio-htsf0w6m.js → studio-qjy2z9bv.js} +12 -30
  53. package/dist/chunks/{studio-2zkz8evn.js → studio-trxrabqf.js} +12 -12
  54. package/dist/chunks/{studio-5q69gfag.js → studio-x4qkdat5.js} +12 -11
  55. package/dist/chunks/studio-x813zp48.js +195 -0
  56. package/dist/chunks/{studio-1hbqnt19.js → studio-zqazsct2.js} +29 -29
  57. package/dist/chunks/{workspace-xpres40v.js → workspace-fjx52ryv.js} +4 -4
  58. package/dist/iframe-entry.js +34 -33
  59. package/dist/manifest.json +7 -0
  60. package/dist/studio.js +534 -546
  61. package/favicon.ico +0 -0
  62. package/index.html +1 -0
  63. package/package.json +15 -14
  64. package/src/about/about-modal.ts +4 -3
  65. package/src/files/files.ts +6 -4
  66. package/src/files/media-paths.ts +13 -42
  67. package/src/files/media-usage.ts +41 -131
  68. package/src/hosting/document.ts +2 -0
  69. package/src/hosting/layout.ts +8 -0
  70. package/src/new-project/import-tab.ts +37 -15
  71. package/src/new-project/location-fields.ts +8 -5
  72. package/src/panels/ai-chat/composer.ts +10 -0
  73. package/src/platforms/cloud.ts +241 -70
  74. package/src/publish/publish-panel.ts +62 -2
  75. package/src/services/ai-import-tools.ts +50 -12
  76. package/src/services/ai-models.ts +108 -1
  77. package/src/services/context-manager.ts +12 -1
  78. package/src/services/tool-executor.ts +11 -0
  79. package/src/settings/preferences-accounts.ts +193 -12
  80. package/src/settings/preferences-dialog.ts +75 -18
  81. package/src/types.ts +27 -3
  82. package/src/ui/ai-managed-connect.ts +62 -13
  83. package/src/ui/ai-model-picker.ts +29 -2
  84. package/src/ui/cf-account-picker.ts +200 -0
  85. package/styles/shell.css +36 -0
  86. package/dist/chunks/studio-bw5dz6km.js +0 -608
package/dist/studio.js CHANGED
@@ -1,6 +1,11 @@
1
1
  import {
2
2
  seedPublishConnected
3
- } from "./chunks/studio-v38hmvx1.js";
3
+ } from "./chunks/studio-4b5z1x43.js";
4
+ import {
5
+ LanguageResolutionController,
6
+ ProgressCircle,
7
+ languageResolverUpdatedSymbol
8
+ } from "./chunks/studio-n8b9wqwy.js";
4
9
  import {
5
10
  IS_MOBILE,
6
11
  IS_TOUCH_DEVICE,
@@ -8,12 +13,7 @@ import {
8
13
  Underlay,
9
14
  modal_css_default
10
15
  } from "./chunks/studio-rn9ta2mz.js";
11
- import {
12
- clearCfConnection,
13
- getCfAccountId,
14
- getCfToken
15
- } from "./chunks/studio-kyh9avvv.js";
16
- import"./chunks/studio-txwkm6p9.js";
16
+ import"./chunks/studio-0bq6eh7v.js";
17
17
  import {
18
18
  ElementResolutionController,
19
19
  FocusVisiblePolyfillMixin,
@@ -32,26 +32,21 @@ import {
32
32
  isIPhone,
33
33
  isWebKit,
34
34
  randomID
35
- } from "./chunks/studio-mmv72a27.js";
35
+ } from "./chunks/studio-5fx3g9jg.js";
36
+ import"./chunks/studio-ahnzd9rg.js";
36
37
  import {
37
38
  firstFocusableIn
38
39
  } from "./chunks/studio-z6nw2ek2.js";
39
40
  import {
40
41
  DependencyManagerController
41
- } from "./chunks/studio-vadzgkrz.js";
42
+ } from "./chunks/studio-n6j9t10q.js";
43
+ import {
44
+ when
45
+ } from "./chunks/studio-tmc5emrw.js";
42
46
  import"./chunks/studio-8q517dfr.js";
43
47
  import {
44
48
  Popover
45
49
  } from "./chunks/studio-rdx8jcxy.js";
46
- import {
47
- LanguageResolutionController,
48
- ProgressCircle,
49
- languageResolverUpdatedSymbol
50
- } from "./chunks/studio-n8b9wqwy.js";
51
- import"./chunks/studio-ahnzd9rg.js";
52
- import {
53
- when
54
- } from "./chunks/studio-tmc5emrw.js";
55
50
  import {
56
51
  defineElement
57
52
  } from "./chunks/studio-18j3bmcz.js";
@@ -71,7 +66,7 @@ import {
71
66
  registerStyleCommands,
72
67
  render as render3,
73
68
  setInspectorTab
74
- } from "./chunks/studio-1hbqnt19.js";
69
+ } from "./chunks/studio-zqazsct2.js";
75
70
  import {
76
71
  CommandUnavailableError,
77
72
  chordFromEvent,
@@ -103,7 +98,7 @@ import {
103
98
  showSlashMenu,
104
99
  showSlashMenuAtRect,
105
100
  suppressBlockActionBar
106
- } from "./chunks/studio-yxrkyv8a.js";
101
+ } from "./chunks/studio-jkftxyvz.js";
107
102
  import {
108
103
  PROJECT_STYLES_TITLE,
109
104
  PROJECT_STYLES_VIEW,
@@ -117,7 +112,7 @@ import {
117
112
  tokenLabel,
118
113
  transposeStylebookStyle,
119
114
  writeTokenOverride
120
- } from "./chunks/studio-8swrjbny.js";
115
+ } from "./chunks/studio-fbf92ckf.js";
121
116
  import {
122
117
  DERIVE_PRESETS,
123
118
  JxColorPopover,
@@ -150,7 +145,7 @@ import {
150
145
  spNumberField,
151
146
  spTextArea,
152
147
  spTextField
153
- } from "./chunks/studio-pdfjntbk.js";
148
+ } from "./chunks/studio-950k0dx6.js";
154
149
  import {
155
150
  LitElement,
156
151
  css
@@ -158,6 +153,38 @@ import {
158
153
  import {
159
154
  negotiateCollab
160
155
  } from "./chunks/studio-dg7zyt5x.js";
156
+ import {
157
+ ensureCfConnection,
158
+ listAccounts,
159
+ notifyCredentialsChanged,
160
+ onCredentialsChanged,
161
+ platformBrokersCf,
162
+ refreshCfConnection,
163
+ resetCfConnectionCache,
164
+ revokeAccount
165
+ } from "./chunks/studio-x813zp48.js";
166
+ import {
167
+ aiConnection,
168
+ cachedModels,
169
+ ensureProxyProbe,
170
+ fetchAvailableModels,
171
+ getBaseUrl,
172
+ getOpenAiKey,
173
+ hasAiCredentials,
174
+ hasOpenAiKey,
175
+ isManagedProxy,
176
+ isProxyConfigured,
177
+ modelContextWindow,
178
+ modelToolSupport,
179
+ preferredModel,
180
+ proxyStateCode,
181
+ resetModelCache,
182
+ saveAiProvider,
183
+ setModel,
184
+ setOpenAiKey,
185
+ storedModel
186
+ } from "./chunks/studio-dm19q43r.js";
187
+ import"./chunks/studio-kyh9avvv.js";
161
188
  import {
162
189
  addFieldFormTpl,
163
190
  createEntry,
@@ -170,12 +197,12 @@ import {
170
197
  registerContentCommands,
171
198
  renderEntryMode,
172
199
  schemaForType
173
- } from "./chunks/studio-r1r7afxx.js";
200
+ } from "./chunks/studio-jc994dnr.js";
174
201
  import"./chunks/studio-eqq1w638.js";
175
202
  import {
176
203
  initQuickSearch,
177
204
  openQuickSearch
178
- } from "./chunks/studio-kyk2v92a.js";
205
+ } from "./chunks/studio-mtfnaqs9.js";
179
206
  import {
180
207
  addRecentProject,
181
208
  clearRecentProjects,
@@ -202,19 +229,16 @@ import {
202
229
  removeRecentProject,
203
230
  renderFilesTemplate,
204
231
  renderMediaMode
205
- } from "./chunks/studio-5rywrkxz.js";
232
+ } from "./chunks/studio-5myknm0a.js";
206
233
  import {
207
234
  computeWindow
208
- } from "./chunks/studio-p8j86wag.js";
209
- import"./chunks/studio-gv8vvshc.js";
235
+ } from "./chunks/studio-4r1pv6zf.js";
236
+ import"./chunks/studio-1wagb550.js";
210
237
  import {
211
238
  autoSyncProjectOnOpen,
212
239
  cleanupGitPanel,
213
- clearGithubToken,
214
240
  cloneRepository,
215
241
  getProjectList,
216
- githubTokenLocation,
217
- githubTokenStored,
218
242
  hydrateProjectList,
219
243
  installAutomationHook,
220
244
  isUpgrade,
@@ -227,17 +251,18 @@ import {
227
251
  registerSourceControlCommands,
228
252
  renderGitPanel,
229
253
  stripRange
230
- } from "./chunks/studio-ex8zyp98.js";
254
+ } from "./chunks/studio-gfgb8pe6.js";
231
255
  import {
232
256
  createPanelScheduler
233
257
  } from "./chunks/studio-8jpzqk5s.js";
258
+ import"./chunks/studio-1ngbejft.js";
234
259
  import {
235
260
  collectionOfPath,
236
261
  entryCollections
237
- } from "./chunks/studio-sf7zjgv1.js";
262
+ } from "./chunks/studio-6yw4y3my.js";
238
263
  import {
239
264
  selectContributedEntry
240
- } from "./chunks/studio-wx5609xd.js";
265
+ } from "./chunks/studio-ew0djmhg.js";
241
266
  import {
242
267
  notifySettingsDocument,
243
268
  onSettingsDocumentChanged,
@@ -251,7 +276,7 @@ import {
251
276
  import {
252
277
  validateDoc,
253
278
  validateProjectConfig
254
- } from "./chunks/studio-68n67094.js";
279
+ } from "./chunks/studio-q9jd1a60.js";
255
280
  import {
256
281
  NULL_FORM_CONTEXT,
257
282
  REDIRECT_STATUSES,
@@ -259,7 +284,7 @@ import {
259
284
  referenceTarget,
260
285
  renderFieldRow,
261
286
  renderProvenanceChip
262
- } from "./chunks/studio-5q69gfag.js";
287
+ } from "./chunks/studio-x4qkdat5.js";
263
288
  import {
264
289
  LIBRARY_CATEGORIES,
265
290
  LIBRARY_CATEGORY_KEYS,
@@ -280,12 +305,12 @@ import {
280
305
  registerGridCommands,
281
306
  scanLibrary,
282
307
  uploadDirForCategory
283
- } from "./chunks/studio-4pqqxbrt.js";
308
+ } from "./chunks/studio-3bqpr0zh.js";
284
309
  import {
285
310
  DRAFT_FIELD,
286
311
  isDraftEntry,
287
312
  listCollectionEntryIds
288
- } from "./chunks/studio-eesa1myv.js";
313
+ } from "./chunks/studio-b55y6ewx.js";
289
314
  import {
290
315
  ROW_KEY_FIELD,
291
316
  armPreviewOverlay,
@@ -317,20 +342,20 @@ import {
317
342
  saveFile,
318
343
  serializeDocument,
319
344
  writesForTurn
320
- } from "./chunks/studio-cb12yz9w.js";
345
+ } from "./chunks/studio-cmb03bg5.js";
321
346
  import {
322
347
  resetIgnoreCache,
323
348
  startFsSync
324
349
  } from "./chunks/studio-q43a5y9h.js";
325
350
  import"./chunks/studio-qq6jym04.js";
326
- import"./chunks/studio-bw5dz6km.js";
351
+ import"./chunks/studio-qcy05dp8.js";
327
352
  import {
328
353
  isImage,
329
354
  previewFileSrc,
330
355
  setMediaChangedHandler,
331
356
  uploadAccept,
332
357
  uploadAssets
333
- } from "./chunks/studio-htsf0w6m.js";
358
+ } from "./chunks/studio-qjy2z9bv.js";
334
359
  import {
335
360
  invalidateUsages
336
361
  } from "./chunks/studio-cft9r4r7.js";
@@ -338,13 +363,13 @@ import {
338
363
  beginActivity,
339
364
  registerActivityPanel,
340
365
  showProgressModal
341
- } from "./chunks/studio-9c4k4vhv.js";
366
+ } from "./chunks/studio-4n2b5gzb.js";
342
367
  import {
343
368
  currentDeploy,
344
369
  latestDeployment,
345
370
  noteDeployment,
346
371
  platformSupportsPublish
347
- } from "./chunks/studio-ahjfdy6e.js";
372
+ } from "./chunks/studio-ef49pnzx.js";
348
373
  import {
349
374
  CATEGORIES,
350
375
  LEVELS,
@@ -460,7 +485,7 @@ import {
460
485
  timeSpan,
461
486
  timeSpanAsync,
462
487
  updateActivePanelHeaders
463
- } from "./chunks/studio-kjjsjak4.js";
488
+ } from "./chunks/studio-2b946z26.js";
464
489
  import {
465
490
  BOTTOM_TAB_IDS,
466
491
  CHROME_THEMES,
@@ -496,30 +521,7 @@ import {
496
521
  shell,
497
522
  toggleActivityTab,
498
523
  updateSiteConfig
499
- } from "./chunks/studio-hbtp0eh1.js";
500
- import {
501
- REGION_ATTR,
502
- REGION_FOR_FOCUS,
503
- activeRegistry,
504
- bottomPanelRegion,
505
- initLayers,
506
- isModalOpen,
507
- navigatorPanelRegion,
508
- openModal,
509
- overlayRegion,
510
- paneRegion,
511
- paneStripRegion,
512
- renderPopover,
513
- resolveRegion,
514
- setActiveRegistry,
515
- showConfirmDialog,
516
- showDialog,
517
- showPromptDialog,
518
- showSaveDiscardDialog
519
- } from "./chunks/studio-t7qb9db8.js";
520
- import {
521
- errorMessage
522
- } from "./chunks/studio-9n4mrmnb.js";
524
+ } from "./chunks/studio-msd847zn.js";
523
525
  import {
524
526
  EDITOR_KIND_LABELS,
525
527
  PRIMARY_PANE,
@@ -605,7 +607,7 @@ import {
605
607
  undo,
606
608
  uniquePaths,
607
609
  workspace
608
- } from "./chunks/studio-2zkz8evn.js";
610
+ } from "./chunks/studio-trxrabqf.js";
609
611
  import {
610
612
  BUFFER_COMMIT,
611
613
  STAGE_CLASS,
@@ -625,15 +627,72 @@ import {
625
627
  tabBufferUnsaved,
626
628
  view
627
629
  } from "./chunks/studio-wcy8trfx.js";
630
+ import {
631
+ classMap,
632
+ ifDefined,
633
+ styleMap
634
+ } from "./chunks/studio-m3hwn7y1.js";
635
+ import {
636
+ monitorForElements
637
+ } from "./chunks/studio-g1wdche0.js";
638
+ import"./chunks/studio-5ehhackm.js";
639
+ import {
640
+ buildComponentInstance,
641
+ componentRegistry,
642
+ loadComponentRegistry
643
+ } from "./chunks/studio-bgxt93ga.js";
644
+ import {
645
+ VOID_ELEMENTS,
646
+ activityBar,
647
+ childIndex,
648
+ childList,
649
+ flattenTree,
650
+ getNodeAtPath,
651
+ initShellRefs,
652
+ leftPanel,
653
+ nodeLabel,
654
+ parentElementPath,
655
+ projectState,
656
+ registerRenderer,
657
+ render,
658
+ renderOnly,
659
+ requireProjectState,
660
+ setProjectState,
661
+ toolbarEl,
662
+ updateCanvas,
663
+ updateSession,
664
+ updateUi
665
+ } from "./chunks/studio-p4ngc046.js";
666
+ import {
667
+ REGION_ATTR,
668
+ REGION_FOR_FOCUS,
669
+ activeRegistry,
670
+ bottomPanelRegion,
671
+ initLayers,
672
+ isModalOpen,
673
+ navigatorPanelRegion,
674
+ openModal,
675
+ overlayRegion,
676
+ paneRegion,
677
+ paneStripRegion,
678
+ renderPopover,
679
+ resolveRegion,
680
+ setActiveRegistry,
681
+ showConfirmDialog,
682
+ showDialog,
683
+ showPromptDialog,
684
+ showSaveDiscardDialog
685
+ } from "./chunks/studio-t7qb9db8.js";
686
+ import {
687
+ errorMessage
688
+ } from "./chunks/studio-9n4mrmnb.js";
628
689
  import {
629
690
  SETTINGS,
630
691
  clearSettings,
631
- hasSetting,
632
692
  hydrateSettings,
633
693
  onSettingsChanged,
634
694
  readStoredSetting,
635
695
  setSetting,
636
- setSettings,
637
696
  settingsSettled,
638
697
  watchRemoteSettings
639
698
  } from "./chunks/studio-92ab2jqe.js";
@@ -649,11 +708,6 @@ import {
649
708
  reactive,
650
709
  toRaw
651
710
  } from "./chunks/studio-xrapxwwc.js";
652
- import {
653
- classMap,
654
- ifDefined,
655
- styleMap
656
- } from "./chunks/studio-m3hwn7y1.js";
657
711
  import {
658
712
  AsyncDirective,
659
713
  Directive,
@@ -670,37 +724,6 @@ import {
670
724
  nothing,
671
725
  render as render2
672
726
  } from "./chunks/studio-kryvsw6j.js";
673
- import {
674
- monitorForElements
675
- } from "./chunks/studio-g1wdche0.js";
676
- import"./chunks/studio-5ehhackm.js";
677
- import {
678
- buildComponentInstance,
679
- componentRegistry,
680
- loadComponentRegistry
681
- } from "./chunks/studio-bgxt93ga.js";
682
- import {
683
- VOID_ELEMENTS,
684
- activityBar,
685
- childIndex,
686
- childList,
687
- flattenTree,
688
- getNodeAtPath,
689
- initShellRefs,
690
- leftPanel,
691
- nodeLabel,
692
- parentElementPath,
693
- projectState,
694
- registerRenderer,
695
- render,
696
- renderOnly,
697
- requireProjectState,
698
- setProjectState,
699
- toolbarEl,
700
- updateCanvas,
701
- updateSession,
702
- updateUi
703
- } from "./chunks/studio-p4ngc046.js";
704
727
  import {
705
728
  displayTagName
706
729
  } from "./chunks/studio-q7v10cg2.js";
@@ -715,7 +738,7 @@ import {
715
738
  mountStillWanted,
716
739
  refreshExtensionUi,
717
740
  refreshFormats
718
- } from "./chunks/studio-eenfkt4e.js";
741
+ } from "./chunks/studio-ahn3pdgx.js";
719
742
  import {
720
743
  getPlatform,
721
744
  hasPlatform,
@@ -724,7 +747,7 @@ import {
724
747
  import {
725
748
  modelUriFor
726
749
  } from "./chunks/studio-h4rxscfc.js";
727
- import"./chunks/studio-9r6j5ev1.js";
750
+ import"./chunks/studio-f3wqjtk5.js";
728
751
  import"./chunks/studio-t5wqwzdh.js";
729
752
  import {
730
753
  setBundleBase
@@ -21473,7 +21496,7 @@ function groupProblems(records = problems) {
21473
21496
  return groups;
21474
21497
  }
21475
21498
  function openProblemPath(path) {
21476
- import("./chunks/files-0cratsr0.js").then((m) => m.openFileInTab(path));
21499
+ import("./chunks/files-3kfkwhk4.js").then((m) => m.openFileInTab(path));
21477
21500
  }
21478
21501
  function actionTpl(record) {
21479
21502
  const id = record.action;
@@ -23690,7 +23713,7 @@ function createChatState(opts = {}) {
23690
23713
  store.status = "idle";
23691
23714
  store.error = null;
23692
23715
  }
23693
- function setModel(m) {
23716
+ function setModel2(m) {
23694
23717
  store.model = m;
23695
23718
  }
23696
23719
  function setTokenCount(count) {
@@ -23744,7 +23767,7 @@ function createChatState(opts = {}) {
23744
23767
  cancelStream,
23745
23768
  clearChat,
23746
23769
  retryLast,
23747
- setModel,
23770
+ setModel: setModel2,
23748
23771
  setTokenCount,
23749
23772
  setContextWarning,
23750
23773
  toMessagesArray
@@ -23790,6 +23813,7 @@ function createProxyStreamingClient({
23790
23813
  errorBody = await response.text();
23791
23814
  } catch {}
23792
23815
  let cleanMessage = errorBody || response.statusText;
23816
+ let machineCode = "";
23793
23817
  try {
23794
23818
  const parsed = JSON.parse(errorBody);
23795
23819
  if (typeof parsed.error === "string") {
@@ -23797,11 +23821,14 @@ function createProxyStreamingClient({
23797
23821
  } else if (parsed.error?.message) {
23798
23822
  cleanMessage = parsed.error.message;
23799
23823
  }
23824
+ if (typeof parsed.code === "string" && parsed.code) {
23825
+ machineCode = parsed.code;
23826
+ }
23800
23827
  } catch {}
23801
23828
  yield {
23802
23829
  type: "error",
23803
23830
  message: cleanMessage,
23804
- code: String(response.status)
23831
+ code: machineCode || String(response.status)
23805
23832
  };
23806
23833
  return;
23807
23834
  }
@@ -25168,142 +25195,6 @@ ${tokenHints}` : summary };
25168
25195
  }));
25169
25196
  }
25170
25197
 
25171
- // src/services/ai-settings.ts
25172
- function getOpenAiKey() {
25173
- return readStoredSetting(SETTINGS.aiOpenAiKey);
25174
- }
25175
- function setOpenAiKey(key) {
25176
- setSetting(SETTINGS.aiOpenAiKey, key || "");
25177
- }
25178
- function hasOpenAiKey() {
25179
- return hasSetting(SETTINGS.aiOpenAiKey);
25180
- }
25181
- function getBaseUrl() {
25182
- return readStoredSetting(SETTINGS.aiBaseUrl);
25183
- }
25184
- function storedModel() {
25185
- return readStoredSetting(SETTINGS.aiModel);
25186
- }
25187
- function setModel(modelId) {
25188
- setSetting(SETTINGS.aiModel, modelId || "");
25189
- }
25190
- function saveAiProvider(provider) {
25191
- setSettings([
25192
- [SETTINGS.aiOpenAiKey, provider.apiKey],
25193
- [SETTINGS.aiBaseUrl, provider.baseUrl],
25194
- [SETTINGS.aiModel, provider.model]
25195
- ]);
25196
- }
25197
- function clearAiProvider() {
25198
- clearSettings([SETTINGS.aiOpenAiKey, SETTINGS.aiBaseUrl, SETTINGS.aiModel]);
25199
- }
25200
-
25201
- // src/services/ai-models.ts
25202
- function aiConnection() {
25203
- return { apiKey: getOpenAiKey(), baseUrl: getBaseUrl() };
25204
- }
25205
- function fingerprint(credentials) {
25206
- return `${credentials.apiKey}\x00${credentials.baseUrl}`;
25207
- }
25208
- var cache2 = null;
25209
- var cacheKey = "";
25210
- var proxyConfigured = false;
25211
- var proxyManaged = false;
25212
- var proxyDefaultModel = "";
25213
- var proxyCode;
25214
- var proxyProbe = null;
25215
- var probeListeners = new Set;
25216
- function resetModelCache() {
25217
- cache2 = null;
25218
- cacheKey = "";
25219
- proxyConfigured = false;
25220
- proxyManaged = false;
25221
- proxyDefaultModel = "";
25222
- proxyCode = undefined;
25223
- proxyProbe = null;
25224
- }
25225
- var CONNECTION_KEYS = new Set([
25226
- SETTINGS.aiOpenAiKey.key,
25227
- SETTINGS.aiBaseUrl.key,
25228
- SETTINGS.cfToken.key,
25229
- SETTINGS.cfAccountId.key
25230
- ]);
25231
- onSettingsChanged((keys) => {
25232
- if (keys.some((key) => CONNECTION_KEYS.has(key))) {
25233
- resetModelCache();
25234
- }
25235
- });
25236
- function cachedModels(credentials) {
25237
- return cache2 && cacheKey === fingerprint(credentials) ? cache2 : null;
25238
- }
25239
- function ensureProxyProbe(onSettled) {
25240
- if (onSettled) {
25241
- probeListeners.add(onSettled);
25242
- }
25243
- proxyProbe ??= fetchAvailableModels({ force: true }).catch(() => {}).then(() => {
25244
- for (const notify2 of probeListeners) {
25245
- notify2();
25246
- }
25247
- });
25248
- }
25249
- function hasAiCredentials() {
25250
- return hasOpenAiKey() || isProxyConfigured();
25251
- }
25252
- function isProxyConfigured() {
25253
- return proxyConfigured;
25254
- }
25255
- function isManagedProxy() {
25256
- return proxyManaged;
25257
- }
25258
- function proxyStateCode() {
25259
- return proxyCode;
25260
- }
25261
- function getProxyDefaultModel() {
25262
- return proxyDefaultModel;
25263
- }
25264
- function preferredModel() {
25265
- return storedModel() || getProxyDefaultModel() || SETTINGS.aiModel.default;
25266
- }
25267
- function siblingRoute(chatUrl, segment) {
25268
- let url;
25269
- try {
25270
- url = new URL(chatUrl, "http://jx.invalid");
25271
- } catch {
25272
- return chatUrl;
25273
- }
25274
- url.pathname = url.pathname.replace(/[^/]*$/, segment);
25275
- return /^https?:/i.test(chatUrl) ? url.href : `${url.pathname}${url.search}`;
25276
- }
25277
- async function fetchAvailableModels(opts = {}) {
25278
- const credentials = opts.credentials ?? aiConnection();
25279
- const key = fingerprint(credentials);
25280
- if (cache2 && cacheKey === key && !opts.force) {
25281
- return cache2;
25282
- }
25283
- const plat = getPlatform();
25284
- const chatUrl = await Promise.resolve(plat.aiChatUrl());
25285
- const modelsUrl = siblingRoute(chatUrl, "models");
25286
- const headers = {};
25287
- if (credentials.apiKey) {
25288
- headers["X-Api-Key"] = credentials.apiKey;
25289
- }
25290
- if (credentials.baseUrl) {
25291
- headers["X-Api-Base-URL"] = credentials.baseUrl;
25292
- }
25293
- const resp = await fetch(modelsUrl, { headers });
25294
- if (!resp.ok) {
25295
- throw new Error(`HTTP ${resp.status}`);
25296
- }
25297
- const data = await resp.json();
25298
- proxyConfigured = data.configured === true;
25299
- proxyManaged = data.managed === true;
25300
- proxyDefaultModel = data.defaultModel ?? "";
25301
- proxyCode = data.code;
25302
- cache2 = (data.models || []).map((m) => ({ id: m.id, name: m.name || m.id }));
25303
- cacheKey = key;
25304
- return cache2;
25305
- }
25306
-
25307
25198
  // src/services/import-seed.ts
25308
25199
  var _brief = null;
25309
25200
  function setPendingImportBrief(brief) {
@@ -25413,6 +25304,20 @@ function breakpointPolicyFor(args, fromBrief) {
25413
25304
  function isAbsolutePath(path) {
25414
25305
  return /^(?:[a-zA-Z]:[/\\]|\/)/.test(path);
25415
25306
  }
25307
+ var REPO_DESTINATION = /^[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\/[A-Za-z0-9._-]+$/;
25308
+ function destinationProblem(destination) {
25309
+ if (getPlatform().createDestination === "repo") {
25310
+ if (!REPO_DESTINATION.test(destination)) {
25311
+ return `"directory" must name a repository as "owner/repo": ${destination}`;
25312
+ }
25313
+ } else if (!isAbsolutePath(destination)) {
25314
+ return `"directory" must be an absolute path: ${destination}`;
25315
+ }
25316
+ if (destination.split(/[/\\]/).includes("..")) {
25317
+ return `"directory" must not contain "..": ${destination}`;
25318
+ }
25319
+ return null;
25320
+ }
25416
25321
  var imported = false;
25417
25322
  function resetImportGuard() {
25418
25323
  imported = false;
@@ -25456,7 +25361,7 @@ function registerImportTools(registry, { getTab, adoptProject: adoptProject2, on
25456
25361
  url: { type: "string", description: "The site to clone. Must be http(s)." },
25457
25362
  directory: {
25458
25363
  type: "string",
25459
- description: "Absolute destination folder. Omit it when an import was started from the New " + "Project form — that destination is the one the user chose, and it wins."
25364
+ description: "Where the project goes, in whichever form this studio's backend uses: an absolute " + 'folder on a filesystem host, or "owner/repo" on a host where a project IS a ' + "repository. Omit it when an import was started from the New Project form — that " + "destination is the one the user chose, and it wins."
25460
25365
  },
25461
25366
  depth: {
25462
25367
  type: "number",
@@ -25531,13 +25436,11 @@ function registerImportTools(registry, { getTab, adoptProject: adoptProject2, on
25531
25436
  }
25532
25437
  const destination = requested || brief?.directory || "";
25533
25438
  if (!destination) {
25534
- return toolError('Pass "directory" — the absolute folder to create the project in. Ask the user where ' + "the project should live rather than guessing.");
25439
+ return toolError(platform.createDestination === "repo" ? 'Pass "directory" — the "owner/repo" to create the project as. Ask the user which ' + "account and repository name rather than guessing." : 'Pass "directory" — the absolute folder to create the project in. Ask the user ' + "where the project should live rather than guessing.");
25535
25440
  }
25536
- if (!isAbsolutePath(destination)) {
25537
- return toolError(`"directory" must be an absolute path: ${destination}`);
25538
- }
25539
- if (destination.split(/[/\\]/).includes("..")) {
25540
- return toolError(`"directory" must not contain "..": ${destination}`);
25441
+ const problem = destinationProblem(destination);
25442
+ if (problem) {
25443
+ return toolError(problem);
25541
25444
  }
25542
25445
  const id = currentToolCallId();
25543
25446
  const signal = beginImportRun(id, { directory: destination, url: target.href });
@@ -25676,6 +25579,7 @@ async function runAgentLoop({
25676
25579
  const toolCalls = new Map;
25677
25580
  let stopReason = "stop";
25678
25581
  let streamError = null;
25582
+ let streamErrorCode;
25679
25583
  for await (const event of streamingClient.streamChat(messages, tools, systemPrompt, signal)) {
25680
25584
  switch (event.type) {
25681
25585
  case "delta": {
@@ -25705,6 +25609,7 @@ async function runAgentLoop({
25705
25609
  }
25706
25610
  case "error": {
25707
25611
  streamError = event.message;
25612
+ streamErrorCode = event.code;
25708
25613
  break;
25709
25614
  }
25710
25615
  default: {
@@ -25714,6 +25619,10 @@ async function runAgentLoop({
25714
25619
  }
25715
25620
  chatState.finishStream(stopReason);
25716
25621
  if (streamError) {
25622
+ if (streamErrorCode === "cf_reconnect_required") {
25623
+ resetModelCache();
25624
+ ensureProxyProbe();
25625
+ }
25717
25626
  chatState.setError(streamError);
25718
25627
  return;
25719
25628
  }
@@ -26479,6 +26388,10 @@ function contextWindowFor(model) {
26479
26388
  if (!model) {
26480
26389
  return DEFAULT_CONTEXT_WINDOW;
26481
26390
  }
26391
+ const reported = modelContextWindow(model);
26392
+ if (reported !== undefined && reported > 0) {
26393
+ return reported;
26394
+ }
26482
26395
  const id = model.toLowerCase();
26483
26396
  let best = 0;
26484
26397
  let window2 = DEFAULT_CONTEXT_WINDOW;
@@ -27152,11 +27065,35 @@ function createManagedConnect(opts) {
27152
27065
  let busy = false;
27153
27066
  let connectError = "";
27154
27067
  function canOffer() {
27155
- return isManagedProxy() && !isProxyConfigured() && hasPlatform() && Boolean(getPlatform().cfConnect);
27068
+ if (!isManagedProxy() || !hasPlatform() || !getPlatform().cfConnect) {
27069
+ return false;
27070
+ }
27071
+ return !isProxyConfigured() || proxyStateCode() === "cf_reconnect_required";
27156
27072
  }
27157
27073
  function ensureProbe() {
27158
27074
  ensureProxyProbe(opts.requestRender);
27159
27075
  }
27076
+ async function settle2(outcome) {
27077
+ if (!outcome || outcome.status === "redirect" || outcome.status === "canceled") {
27078
+ return;
27079
+ }
27080
+ if (outcome.status === "timeout") {
27081
+ connectError = "The Cloudflare window didn't finish. Sign in there, then reconnect — nothing was changed.";
27082
+ return;
27083
+ }
27084
+ if (!outcome.connection.accountId) {
27085
+ const { openCfAccountPicker } = await import("./chunks/cf-account-picker-en86v7x7.js");
27086
+ if (!await openCfAccountPicker()) {
27087
+ connectError = "Cloudflare is connected, but no account is chosen yet — pick one to finish setting up the assistant.";
27088
+ return;
27089
+ }
27090
+ }
27091
+ resetModelCache();
27092
+ await fetchAvailableModels({ force: true });
27093
+ if (!isProxyConfigured() || proxyStateCode() === "cf_reconnect_required") {
27094
+ connectError = "Cloudflare connected, but the assistant backend still reports the connection as unusable. Try reconnecting, or use your own API key below.";
27095
+ }
27096
+ }
27160
27097
  async function connect() {
27161
27098
  if (busy) {
27162
27099
  return;
@@ -27165,12 +27102,7 @@ function createManagedConnect(opts) {
27165
27102
  connectError = "";
27166
27103
  opts.requestRender();
27167
27104
  try {
27168
- const connection = await getPlatform().cfConnect?.();
27169
- if (connection) {
27170
- await fetchAvailableModels({ force: true });
27171
- } else {
27172
- connectError = "Cloudflare connection was not completed.";
27173
- }
27105
+ await settle2(await getPlatform().cfConnect?.() ?? null);
27174
27106
  } catch (error) {
27175
27107
  connectError = error instanceof Error ? error.message : String(error);
27176
27108
  }
@@ -27246,59 +27178,6 @@ function shortcutReference(commands, overrides) {
27246
27178
  return rows.toSorted((a, b) => a.scope.localeCompare(b.scope) || a.chord.localeCompare(b.chord));
27247
27179
  }
27248
27180
 
27249
- // src/settings/preferences-accounts.ts
27250
- function listAccounts() {
27251
- const githubToken = githubTokenStored();
27252
- const cfToken = getCfToken();
27253
- const cfAccount = getCfAccountId();
27254
- const model = preferredModel();
27255
- const endpoint = getBaseUrl();
27256
- return [
27257
- {
27258
- id: "github",
27259
- label: "GitHub",
27260
- detail: githubToken ? githubTokenLocation() === "desktop" ? "Signed in — the token is in this app's config folder, readable only by you." : "Signed in — a device-flow token is stored in this browser." : "Not signed in. Cloning and pushing will ask when they need it.",
27261
- connected: Boolean(githubToken),
27262
- revoke: clearGithubToken
27263
- },
27264
- {
27265
- id: "ai",
27266
- label: "AI provider",
27267
- detail: hasOpenAiKey() ? `Key stored. Model ${model}${endpoint ? ` via ${endpoint}` : ""}.` : "No key stored. The Assistant section is where one is entered.",
27268
- connected: hasOpenAiKey(),
27269
- revoke: clearAiProvider
27270
- },
27271
- {
27272
- id: "cloudflare",
27273
- label: "Cloudflare",
27274
- detail: cfToken ? `Connected${cfAccount ? ` — account ${cfAccount}` : ""}.` : "Not connected. Publishing will ask when it needs it.",
27275
- connected: Boolean(cfToken),
27276
- revoke: clearCfConnection
27277
- }
27278
- ];
27279
- }
27280
- function revokeAccount(id) {
27281
- const account = listAccounts().find((candidate) => candidate.id === id);
27282
- if (!account) {
27283
- return false;
27284
- }
27285
- account.revoke();
27286
- notifyCredentialsChanged();
27287
- return true;
27288
- }
27289
- var _listeners = new Set;
27290
- function onCredentialsChanged(listener) {
27291
- _listeners.add(listener);
27292
- return () => {
27293
- _listeners.delete(listener);
27294
- };
27295
- }
27296
- function notifyCredentialsChanged() {
27297
- for (const listener of _listeners) {
27298
- listener();
27299
- }
27300
- }
27301
-
27302
27181
  // src/settings/preferences-keymap.ts
27303
27182
  var KEYBINDINGS_STORAGE_KEY = SETTINGS.keybindings.key;
27304
27183
  var UNMODIFIED_KEYS = new Set([
@@ -27473,6 +27352,11 @@ function credentialsChanged() {
27473
27352
  notifyCredentialsChanged();
27474
27353
  repaint();
27475
27354
  }
27355
+ function sectionShown() {
27356
+ if (_section === "accounts" && platformBrokersCf()) {
27357
+ refreshCfConnection().then(repaint);
27358
+ }
27359
+ }
27476
27360
  var credsForm = createAiCredentialsForm({
27477
27361
  intro: html`
27478
27362
  Any OpenAI-compatible key works. Stored locally on this machine; sent only to the Studio proxy
@@ -27508,7 +27392,38 @@ function assistantTpl() {
27508
27392
  managedConnect.ensureProbe();
27509
27393
  return html`<div class="prefs-assistant">${managedConnect.render()} ${credsForm.render()}</div>`;
27510
27394
  }
27395
+ function accountActionsTpl(account) {
27396
+ if (account.actions) {
27397
+ return account.actions.map((action) => html`
27398
+ <sp-button
27399
+ size="s"
27400
+ data-action=${action.id}
27401
+ variant=${action.variant ?? nothing}
27402
+ treatment=${action.variant === "negative" ? "outline" : nothing}
27403
+ @click=${() => {
27404
+ Promise.resolve(action.run()).finally(repaint);
27405
+ }}
27406
+ >
27407
+ ${action.label}
27408
+ </sp-button>
27409
+ `);
27410
+ }
27411
+ return account.connected ? html`
27412
+ <sp-button
27413
+ size="s"
27414
+ variant="negative"
27415
+ treatment="outline"
27416
+ @click=${() => {
27417
+ revokeAccount(account.id);
27418
+ repaint();
27419
+ }}
27420
+ >
27421
+ Disconnect
27422
+ </sp-button>
27423
+ ` : nothing;
27424
+ }
27511
27425
  function accountsTpl() {
27426
+ ensureCfConnection();
27512
27427
  return html`
27513
27428
  <div class="prefs-accounts">
27514
27429
  ${listAccounts().map((account) => html`
@@ -27517,19 +27432,7 @@ function accountsTpl() {
27517
27432
  <span class="prefs-account-label">${account.label}</span>
27518
27433
  <span class="prefs-account-detail">${account.detail}</span>
27519
27434
  </div>
27520
- ${account.connected ? html`
27521
- <sp-button
27522
- size="s"
27523
- variant="negative"
27524
- treatment="outline"
27525
- @click=${() => {
27526
- revokeAccount(account.id);
27527
- repaint();
27528
- }}
27529
- >
27530
- Disconnect
27531
- </sp-button>
27532
- ` : nothing}
27435
+ <div class="prefs-account-actions">${accountActionsTpl(account)}</div>
27533
27436
  </div>
27534
27437
  `)}
27535
27438
  </div>
@@ -27709,14 +27612,17 @@ function sectionBodyTpl() {
27709
27612
  return appearanceTpl();
27710
27613
  }
27711
27614
  function openPreferences(section) {
27615
+ resetCfConnectionCache();
27712
27616
  _section = section !== undefined && isPreferencesSection(section) ? section : _section;
27713
27617
  if (_close) {
27714
27618
  repaint();
27619
+ sectionShown();
27715
27620
  return Promise.resolve(null);
27716
27621
  }
27717
27622
  _section = section !== undefined && isPreferencesSection(section) ? section : DEFAULT_PREFERENCES_SECTION;
27718
27623
  credsForm.startEdit();
27719
27624
  resetKeyboardState();
27625
+ sectionShown();
27720
27626
  return showDialog((done) => {
27721
27627
  let wrapperEl = null;
27722
27628
  function finish2() {
@@ -27752,6 +27658,7 @@ function openPreferences(section) {
27752
27658
  _section = candidate.id;
27753
27659
  resetKeyboardState();
27754
27660
  repaint();
27661
+ sectionShown();
27755
27662
  }}
27756
27663
  >
27757
27664
  ${candidate.title}
@@ -27817,6 +27724,10 @@ function registerPreferencesCommands(registry) {
27817
27724
  // src/ui/ai-model-picker.ts
27818
27725
  var RETRY_MODELS = "__retry_models__";
27819
27726
  var LOADING_MODELS = "__loading__";
27727
+ var NO_TOOLS_SUFFIX = " — no tools";
27728
+ function itemLabel(model) {
27729
+ return modelToolSupport(model.id) === false ? `${model.name}${NO_TOOLS_SUFFIX}` : model.name;
27730
+ }
27820
27731
  function createModelPicker(opts) {
27821
27732
  const getModel = opts.getModel ?? preferredModel;
27822
27733
  const onChange = opts.onChange ?? setModel;
@@ -27868,13 +27779,18 @@ function createModelPicker(opts) {
27868
27779
  .value=${live(current)}
27869
27780
  @change=${onPickerChange}
27870
27781
  >
27871
- ${items.map((m) => html`<sp-menu-item value=${m.id}>${m.name}</sp-menu-item>`)}
27782
+ ${items.map((m) => html`<sp-menu-item value=${m.id}>${itemLabel(m)}</sp-menu-item>`)}
27872
27783
  ${loading ? html`<sp-menu-item disabled value=${LOADING_MODELS}>Loading models…</sp-menu-item>` : nothing}
27873
27784
  ${failure ? html`<sp-menu-item value=${RETRY_MODELS}>Retry loading models</sp-menu-item>` : nothing}
27874
27785
  </sp-picker>
27875
27786
  `;
27876
27787
  }
27877
- return { error: () => failure, isLoading: () => loading, render: render8 };
27788
+ return {
27789
+ error: () => failure,
27790
+ isLoading: () => loading,
27791
+ render: render8,
27792
+ selectedLacksTools: () => modelToolSupport(getModel()) === false
27793
+ };
27878
27794
  }
27879
27795
 
27880
27796
  // src/panels/ai-chat/composer.ts
@@ -28045,6 +27961,9 @@ function createComposer(opts) {
28045
27961
  </sp-action-button>
28046
27962
  `}
28047
27963
  </div>
27964
+ ${modelPicker.selectedLacksTools() ? html`<div class="ai-composer-note">
27965
+ This model can't use editing tools — the assistant will answer but not edit.
27966
+ </div>` : nothing}
28048
27967
  </div>
28049
27968
  `;
28050
27969
  }
@@ -28488,6 +28407,114 @@ function componentMetaFrom(doc, path) {
28488
28407
  };
28489
28408
  }
28490
28409
 
28410
+ // src/services/import-client.ts
28411
+ var IMPORT_WARNING_PHASE = "warning";
28412
+ async function streamImport(endpoint, opts, onProgress, signal, onReady) {
28413
+ const headers = { "Content-Type": "application/json" };
28414
+ if (opts.apiKey) {
28415
+ headers["X-Api-Key"] = opts.apiKey;
28416
+ }
28417
+ if (opts.baseUrl) {
28418
+ headers["X-Api-Base-URL"] = opts.baseUrl;
28419
+ }
28420
+ const res = await fetch(endpoint, {
28421
+ body: JSON.stringify({
28422
+ url: opts.url,
28423
+ directory: opts.directory,
28424
+ depth: opts.depth,
28425
+ maxPages: opts.maxPages,
28426
+ aiComponents: opts.aiComponents,
28427
+ ...opts.breakpoints === undefined ? {} : { breakpoints: opts.breakpoints },
28428
+ ...opts.model === undefined ? {} : { aiModel: opts.model },
28429
+ ...opts.verify === undefined ? {} : { verify: opts.verify },
28430
+ ...opts.verifyThreshold === undefined ? {} : { verifyThreshold: opts.verifyThreshold },
28431
+ ...opts.verifyMinFidelity === undefined ? {} : { verifyMinFidelity: opts.verifyMinFidelity }
28432
+ }),
28433
+ headers,
28434
+ method: "POST",
28435
+ ...signal === undefined ? {} : { signal }
28436
+ });
28437
+ if (!res.ok) {
28438
+ let message = `Import failed (${res.status})`;
28439
+ try {
28440
+ const body = await res.json();
28441
+ if (body.error) {
28442
+ message = body.error;
28443
+ }
28444
+ } catch {}
28445
+ throw new Error(message);
28446
+ }
28447
+ if (!res.body) {
28448
+ throw new Error("Import stream had no response body");
28449
+ }
28450
+ const reader = res.body.getReader();
28451
+ const decoder = new TextDecoder;
28452
+ let buffer = "";
28453
+ let result = null;
28454
+ let unreadable = 0;
28455
+ const handleLine = (line) => {
28456
+ const trimmed = line.trim();
28457
+ if (!trimmed) {
28458
+ return;
28459
+ }
28460
+ let parsed;
28461
+ try {
28462
+ parsed = JSON.parse(trimmed);
28463
+ } catch {
28464
+ unreadable += 1;
28465
+ return;
28466
+ }
28467
+ if (parsed.type === "progress") {
28468
+ onProgress({
28469
+ phase: parsed.phase ?? "",
28470
+ message: parsed.message ?? "",
28471
+ ...parsed.current === undefined ? {} : { current: parsed.current },
28472
+ ...parsed.total === undefined ? {} : { total: parsed.total }
28473
+ });
28474
+ } else if (parsed.type === "ready" && parsed.root !== undefined) {
28475
+ onReady?.({ root: parsed.root });
28476
+ } else if (parsed.type === "done" && parsed.root !== undefined && parsed.config) {
28477
+ result = {
28478
+ root: parsed.root,
28479
+ config: parsed.config,
28480
+ ...parsed.result === undefined ? {} : { result: parsed.result }
28481
+ };
28482
+ } else if (parsed.type === "error") {
28483
+ throw new Error(parsed.error || "Import failed");
28484
+ }
28485
+ };
28486
+ try {
28487
+ for (;; ) {
28488
+ const { done, value } = await reader.read();
28489
+ if (done) {
28490
+ break;
28491
+ }
28492
+ buffer += decoder.decode(value, { stream: true });
28493
+ const lines = buffer.split(`
28494
+ `);
28495
+ buffer = lines.pop() ?? "";
28496
+ for (const line of lines) {
28497
+ handleLine(line);
28498
+ }
28499
+ }
28500
+ handleLine(buffer);
28501
+ } finally {
28502
+ try {
28503
+ await reader.cancel();
28504
+ } catch {}
28505
+ }
28506
+ if (unreadable > 0) {
28507
+ onProgress({
28508
+ message: `${unreadable} progress line${unreadable === 1 ? "" : "s"} could not be read and ` + `${unreadable === 1 ? "was" : "were"} skipped — the import may be missing steps.`,
28509
+ phase: IMPORT_WARNING_PHASE
28510
+ });
28511
+ }
28512
+ if (!result) {
28513
+ throw new Error("Import stream ended without a result");
28514
+ }
28515
+ return result;
28516
+ }
28517
+
28491
28518
  // ../protocol/src/problem.ts
28492
28519
  var PROBLEM_TYPE_BASE = "https://jxsuite.com/problems/";
28493
28520
  function problemSlug(type) {
@@ -28653,9 +28680,93 @@ async function fetchCfConnection() {
28653
28680
  return {
28654
28681
  connected: true,
28655
28682
  ...body.accountId ? { accountId: body.accountId } : {},
28656
- ...body.accountName ? { accountName: body.accountName } : {}
28683
+ ...body.accountName ? { accountName: body.accountName } : {},
28684
+ ...body.needsReconnect ? { needsReconnect: true } : {},
28685
+ ...body.needsAccount ? { needsAccount: true } : {},
28686
+ ...body.code ? { code: body.code } : {},
28687
+ ...body.reason ? { reason: body.reason } : {},
28688
+ ...body.hasRefreshToken === undefined ? {} : { hasRefreshToken: body.hasRefreshToken },
28689
+ ...body.expiresAt === undefined ? {} : { expiresAt: body.expiresAt }
28657
28690
  };
28658
28691
  }
28692
+ var cfConnectFlow = null;
28693
+ async function runCfConnect(handle2) {
28694
+ const baseline = await fetchCfConnection().catch(() => null);
28695
+ const healthyBaseline = Boolean(baseline?.connected && !baseline.needsReconnect);
28696
+ const popup = window.open("/api/v1/cf/connect", "cf-connect", "width=980,height=780");
28697
+ if (!popup) {
28698
+ location.assign("/api/v1/cf/connect");
28699
+ return { status: "redirect" };
28700
+ }
28701
+ handle2.popup = popup;
28702
+ const deadline = Date.now() + 180000;
28703
+ return new Promise((resolve, reject) => {
28704
+ let timer = 0;
28705
+ const cleanup = () => {
28706
+ window.removeEventListener("message", onMessage);
28707
+ window.clearTimeout(timer);
28708
+ if (!popup.closed) {
28709
+ popup.close();
28710
+ }
28711
+ };
28712
+ const settle2 = (outcome) => {
28713
+ cleanup();
28714
+ resolve(outcome);
28715
+ };
28716
+ const fail = (reason) => {
28717
+ cleanup();
28718
+ reject(new Error(reason));
28719
+ };
28720
+ const usable = (connection) => Boolean(connection?.connected && !connection.needsReconnect);
28721
+ const onMessage = (event) => {
28722
+ if (event.origin !== location.origin) {
28723
+ return;
28724
+ }
28725
+ const data = event.data;
28726
+ if (!data || data.source !== "jx-cf") {
28727
+ return;
28728
+ }
28729
+ if (data.status === "error") {
28730
+ fail(data.reason ?? "Cloudflare authorization failed");
28731
+ return;
28732
+ }
28733
+ fetchCfConnection().then((connection) => {
28734
+ settle2(usable(connection) ? { connection, status: "connected" } : { status: "timeout" });
28735
+ }, () => {
28736
+ fail("Cloudflare connected, but the connection could not be confirmed");
28737
+ });
28738
+ };
28739
+ window.addEventListener("message", onMessage);
28740
+ const poll = async () => {
28741
+ if (Date.now() > deadline) {
28742
+ settle2({ status: "timeout" });
28743
+ return;
28744
+ }
28745
+ let connection = null;
28746
+ let answered = true;
28747
+ try {
28748
+ connection = await fetchCfConnection();
28749
+ } catch {
28750
+ answered = false;
28751
+ }
28752
+ if (answered && usable(connection) && !healthyBaseline) {
28753
+ settle2({ connection, status: "connected" });
28754
+ return;
28755
+ }
28756
+ if (popup.closed) {
28757
+ const final = await fetchCfConnection().catch(() => null);
28758
+ settle2(usable(final) ? { connection: final, status: "connected" } : { status: "canceled" });
28759
+ return;
28760
+ }
28761
+ timer = window.setTimeout(() => {
28762
+ poll();
28763
+ }, 1500);
28764
+ };
28765
+ timer = window.setTimeout(() => {
28766
+ poll();
28767
+ }, 1500);
28768
+ });
28769
+ }
28659
28770
  function parseRootKey(root) {
28660
28771
  const match = /^([^/@]+)\/([^/@]+)@(.+)$/.exec(root);
28661
28772
  if (!match) {
@@ -29134,6 +29245,9 @@ function createCloudPlatform(project) {
29134
29245
  config: { name: opts.name }
29135
29246
  };
29136
29247
  },
29248
+ async importSite(opts, onProgress, signal, onReady) {
29249
+ return await streamImport("/api/v1/import/site", opts, onProgress, signal, onReady);
29250
+ },
29137
29251
  async getUser() {
29138
29252
  const res = await fetch("/api/v1/me", { credentials: "include" });
29139
29253
  if (!res.ok) {
@@ -29207,70 +29321,49 @@ function createCloudPlatform(project) {
29207
29321
  async cfConnection() {
29208
29322
  return fetchCfConnection();
29209
29323
  },
29210
- async cfConnect() {
29324
+ cfConnect() {
29211
29325
  if (typeof window === "undefined" || typeof location === "undefined") {
29212
- return null;
29326
+ return Promise.resolve(null);
29213
29327
  }
29214
- const popup = window.open("/api/v1/cf/connect", "cf-connect", "width=980,height=780");
29215
- if (!popup) {
29216
- location.assign("/api/v1/cf/connect");
29217
- return null;
29328
+ const running = cfConnectFlow;
29329
+ if (running) {
29330
+ try {
29331
+ running.popup?.focus();
29332
+ } catch {}
29333
+ return running.promise;
29218
29334
  }
29219
- const deadline = Date.now() + 180000;
29220
- return new Promise((resolve, reject) => {
29221
- let timer = 0;
29222
- const cleanup = () => {
29223
- window.removeEventListener("message", onMessage);
29224
- window.clearTimeout(timer);
29225
- if (!popup.closed) {
29226
- popup.close();
29227
- }
29228
- };
29229
- const settle2 = (connection) => {
29230
- cleanup();
29231
- resolve(connection);
29232
- };
29233
- const fail = (reason) => {
29234
- cleanup();
29235
- reject(new Error(reason));
29236
- };
29237
- const onMessage = (event) => {
29238
- if (event.origin !== location.origin) {
29239
- return;
29240
- }
29241
- const data = event.data;
29242
- if (!data || data.source !== "jx-cf") {
29243
- return;
29244
- }
29245
- if (data.status === "error") {
29246
- fail(data.reason ?? "Cloudflare authorization failed");
29247
- return;
29248
- }
29249
- fetchCfConnection().then(settle2);
29250
- };
29251
- window.addEventListener("message", onMessage);
29252
- const poll = async () => {
29253
- if (Date.now() > deadline) {
29254
- settle2(null);
29255
- return;
29256
- }
29257
- const connection = await fetchCfConnection();
29258
- if (connection) {
29259
- settle2(connection);
29260
- return;
29261
- }
29262
- if (popup.closed) {
29263
- settle2(await fetchCfConnection());
29264
- return;
29265
- }
29266
- timer = window.setTimeout(() => {
29267
- poll();
29268
- }, 1500);
29269
- };
29270
- timer = window.setTimeout(() => {
29271
- poll();
29272
- }, 1500);
29335
+ const handle2 = { popup: null, promise: Promise.resolve(null) };
29336
+ cfConnectFlow = handle2;
29337
+ handle2.promise = runCfConnect(handle2).finally(() => {
29338
+ if (cfConnectFlow === handle2) {
29339
+ cfConnectFlow = null;
29340
+ }
29273
29341
  });
29342
+ return handle2.promise;
29343
+ },
29344
+ async cfAccounts() {
29345
+ const res = await fetch("/api/v1/cf/accounts", { credentials: "include" });
29346
+ return okJson(res, "Failed to list Cloudflare accounts");
29347
+ },
29348
+ async cfSelectAccount(account) {
29349
+ const res = await fetch("/api/v1/cf/select-account", {
29350
+ body: JSON.stringify({ accountId: account.id, accountName: account.name }),
29351
+ credentials: "include",
29352
+ headers: { "Content-Type": "application/json" },
29353
+ method: "POST"
29354
+ });
29355
+ if (!res.ok) {
29356
+ throw new Error(await errorMessage2(res, "Failed to select a Cloudflare account"));
29357
+ }
29358
+ },
29359
+ async cfDisconnect() {
29360
+ const res = await fetch("/api/v1/cf/connection", {
29361
+ credentials: "include",
29362
+ method: "DELETE"
29363
+ });
29364
+ if (!res.ok) {
29365
+ throw new Error(await errorMessage2(res, "Failed to disconnect Cloudflare"));
29366
+ }
29274
29367
  },
29275
29368
  async cfApi(apiPath, init) {
29276
29369
  const res = await fetch(`/api/v1/cf/proxy${apiPath}`, {
@@ -29295,114 +29388,6 @@ function createCloudPlatform(project) {
29295
29388
  return platform;
29296
29389
  }
29297
29390
 
29298
- // src/services/import-client.ts
29299
- var IMPORT_WARNING_PHASE = "warning";
29300
- async function streamImport(endpoint, opts, onProgress, signal, onReady) {
29301
- const headers = { "Content-Type": "application/json" };
29302
- if (opts.apiKey) {
29303
- headers["X-Api-Key"] = opts.apiKey;
29304
- }
29305
- if (opts.baseUrl) {
29306
- headers["X-Api-Base-URL"] = opts.baseUrl;
29307
- }
29308
- const res = await fetch(endpoint, {
29309
- body: JSON.stringify({
29310
- url: opts.url,
29311
- directory: opts.directory,
29312
- depth: opts.depth,
29313
- maxPages: opts.maxPages,
29314
- aiComponents: opts.aiComponents,
29315
- ...opts.breakpoints === undefined ? {} : { breakpoints: opts.breakpoints },
29316
- ...opts.model === undefined ? {} : { aiModel: opts.model },
29317
- ...opts.verify === undefined ? {} : { verify: opts.verify },
29318
- ...opts.verifyThreshold === undefined ? {} : { verifyThreshold: opts.verifyThreshold },
29319
- ...opts.verifyMinFidelity === undefined ? {} : { verifyMinFidelity: opts.verifyMinFidelity }
29320
- }),
29321
- headers,
29322
- method: "POST",
29323
- ...signal === undefined ? {} : { signal }
29324
- });
29325
- if (!res.ok) {
29326
- let message = `Import failed (${res.status})`;
29327
- try {
29328
- const body = await res.json();
29329
- if (body.error) {
29330
- message = body.error;
29331
- }
29332
- } catch {}
29333
- throw new Error(message);
29334
- }
29335
- if (!res.body) {
29336
- throw new Error("Import stream had no response body");
29337
- }
29338
- const reader = res.body.getReader();
29339
- const decoder = new TextDecoder;
29340
- let buffer = "";
29341
- let result = null;
29342
- let unreadable = 0;
29343
- const handleLine = (line) => {
29344
- const trimmed = line.trim();
29345
- if (!trimmed) {
29346
- return;
29347
- }
29348
- let parsed;
29349
- try {
29350
- parsed = JSON.parse(trimmed);
29351
- } catch {
29352
- unreadable += 1;
29353
- return;
29354
- }
29355
- if (parsed.type === "progress") {
29356
- onProgress({
29357
- phase: parsed.phase ?? "",
29358
- message: parsed.message ?? "",
29359
- ...parsed.current === undefined ? {} : { current: parsed.current },
29360
- ...parsed.total === undefined ? {} : { total: parsed.total }
29361
- });
29362
- } else if (parsed.type === "ready" && parsed.root !== undefined) {
29363
- onReady?.({ root: parsed.root });
29364
- } else if (parsed.type === "done" && parsed.root !== undefined && parsed.config) {
29365
- result = {
29366
- root: parsed.root,
29367
- config: parsed.config,
29368
- ...parsed.result === undefined ? {} : { result: parsed.result }
29369
- };
29370
- } else if (parsed.type === "error") {
29371
- throw new Error(parsed.error || "Import failed");
29372
- }
29373
- };
29374
- try {
29375
- for (;; ) {
29376
- const { done, value } = await reader.read();
29377
- if (done) {
29378
- break;
29379
- }
29380
- buffer += decoder.decode(value, { stream: true });
29381
- const lines = buffer.split(`
29382
- `);
29383
- buffer = lines.pop() ?? "";
29384
- for (const line of lines) {
29385
- handleLine(line);
29386
- }
29387
- }
29388
- handleLine(buffer);
29389
- } finally {
29390
- try {
29391
- await reader.cancel();
29392
- } catch {}
29393
- }
29394
- if (unreadable > 0) {
29395
- onProgress({
29396
- message: `${unreadable} progress line${unreadable === 1 ? "" : "s"} could not be read and ` + `${unreadable === 1 ? "was" : "were"} skipped — the import may be missing steps.`,
29397
- phase: IMPORT_WARNING_PHASE
29398
- });
29399
- }
29400
- if (!result) {
29401
- throw new Error("Import stream ended without a result");
29402
- }
29403
- return result;
29404
- }
29405
-
29406
29391
  // src/services/directory-picker.ts
29407
29392
  function canPickDirectory() {
29408
29393
  return typeof globalThis.showDirectoryPicker === "function";
@@ -30226,8 +30211,8 @@ function createDevServerPlatform() {
30226
30211
  }
30227
30212
  },
30228
30213
  async cfApi(apiPath, init) {
30229
- const { getCfToken: getCfToken2 } = await import("./chunks/cf-settings-45fgyx8y.js");
30230
- const token = getCfToken2();
30214
+ const { getCfToken } = await import("./chunks/cf-settings-45fgyx8y.js");
30215
+ const token = getCfToken();
30231
30216
  if (!token) {
30232
30217
  throw new Error("No Cloudflare API token configured");
30233
30218
  }
@@ -30244,8 +30229,8 @@ function createDevServerPlatform() {
30244
30229
  return envelope.result ?? envelope;
30245
30230
  },
30246
30231
  async cfConnection() {
30247
- const { getCfAccountId: getCfAccountId2, getCfToken: getCfToken2, setCfAccountId } = await import("./chunks/cf-settings-45fgyx8y.js");
30248
- if (!getCfToken2()) {
30232
+ const { getCfAccountId, getCfToken, setCfAccountId } = await import("./chunks/cf-settings-45fgyx8y.js");
30233
+ if (!getCfToken()) {
30249
30234
  return null;
30250
30235
  }
30251
30236
  try {
@@ -30253,7 +30238,7 @@ function createDevServerPlatform() {
30253
30238
  if (!accounts?.length) {
30254
30239
  return { connected: false };
30255
30240
  }
30256
- const chosen = accounts.find((a) => a.id === getCfAccountId2()) ?? accounts[0];
30241
+ const chosen = accounts.find((a) => a.id === getCfAccountId()) ?? accounts[0];
30257
30242
  setCfAccountId(chosen.id);
30258
30243
  return { connected: true, accountId: chosen.id, accountName: chosen.name };
30259
30244
  } catch {
@@ -35470,8 +35455,8 @@ class TruncatedValueTooltipController {
35470
35455
  return;
35471
35456
  }
35472
35457
  await Promise.all([
35473
- import("./chunks/sp-overlay.dev-yztmtrs1.js"),
35474
- import("./chunks/sp-tooltip.dev-xcvpnqr0.js")
35458
+ import("./chunks/sp-overlay.dev-qgvhnxf4.js"),
35459
+ import("./chunks/sp-tooltip.dev-4sastdnw.js")
35475
35460
  ]);
35476
35461
  this._tooltipDepsLoaded = true;
35477
35462
  Promise.resolve().then(() => {
@@ -36444,7 +36429,7 @@ class MenuItem extends LikeAnchor(ObserveSlotText(ObserveSlotPresence(Focusable,
36444
36429
  }
36445
36430
  this.dependencyManager.add("sp-overlay");
36446
36431
  this.dependencyManager.add("sp-popover");
36447
- import("./chunks/sp-overlay.dev-yztmtrs1.js");
36432
+ import("./chunks/sp-overlay.dev-qgvhnxf4.js");
36448
36433
  import("./chunks/sp-popover.dev-n2etmqdp.js");
36449
36434
  return html`
36450
36435
  <sp-overlay
@@ -43829,11 +43814,11 @@ function $488c6ddbf4ef74c2$var$getCachedNumberFormatter(locale, options = {}) {
43829
43814
  style: "decimal"
43830
43815
  };
43831
43816
  }
43832
- let cacheKey2 = locale + (options ? Object.entries(options).sort((a4, b2) => a4[0] < b2[0] ? -1 : 1).join() : "");
43833
- if ($488c6ddbf4ef74c2$var$formatterCache.has(cacheKey2))
43834
- return $488c6ddbf4ef74c2$var$formatterCache.get(cacheKey2);
43817
+ let cacheKey = locale + (options ? Object.entries(options).sort((a4, b2) => a4[0] < b2[0] ? -1 : 1).join() : "");
43818
+ if ($488c6ddbf4ef74c2$var$formatterCache.has(cacheKey))
43819
+ return $488c6ddbf4ef74c2$var$formatterCache.get(cacheKey);
43835
43820
  let numberFormatter = new Intl.NumberFormat(locale, options);
43836
- $488c6ddbf4ef74c2$var$formatterCache.set(cacheKey2, numberFormatter);
43821
+ $488c6ddbf4ef74c2$var$formatterCache.set(cacheKey, numberFormatter);
43837
43822
  return numberFormatter;
43838
43823
  }
43839
43824
  function $488c6ddbf4ef74c2$export$711b50b3c525e0f2(numberFormat, signDisplay, num) {
@@ -43906,11 +43891,11 @@ function $6c7bd7858deea686$var$getNumberParserImpl(locale, options, value) {
43906
43891
  return defaultParser;
43907
43892
  }
43908
43893
  function $6c7bd7858deea686$var$getCachedNumberParser(locale, options) {
43909
- let cacheKey2 = locale + (options ? Object.entries(options).sort((a4, b2) => a4[0] < b2[0] ? -1 : 1).join() : "");
43910
- let parser = $6c7bd7858deea686$var$numberParserCache.get(cacheKey2);
43894
+ let cacheKey = locale + (options ? Object.entries(options).sort((a4, b2) => a4[0] < b2[0] ? -1 : 1).join() : "");
43895
+ let parser = $6c7bd7858deea686$var$numberParserCache.get(cacheKey);
43911
43896
  if (!parser) {
43912
43897
  parser = new $6c7bd7858deea686$var$NumberParserImpl(locale, options);
43913
- $6c7bd7858deea686$var$numberParserCache.set(cacheKey2, parser);
43898
+ $6c7bd7858deea686$var$numberParserCache.set(cacheKey, parser);
43914
43899
  }
43915
43900
  return parser;
43916
43901
  }
@@ -45590,7 +45575,7 @@ class PickerBase extends SizedMixin(ExpandableElement, {
45590
45575
  var _a;
45591
45576
  const container = this.renderContainer(menu);
45592
45577
  this.dependencyManager.add("sp-overlay");
45593
- import("./chunks/sp-overlay.dev-yztmtrs1.js");
45578
+ import("./chunks/sp-overlay.dev-qgvhnxf4.js");
45594
45579
  return html`
45595
45580
  <sp-overlay
45596
45581
  @slottable-request=${this.handleSlottableRequest}
@@ -46241,7 +46226,7 @@ class Picker extends SizedMixin(ExpandableElement, {
46241
46226
  var _a;
46242
46227
  const container = this.renderContainer(menu);
46243
46228
  this.dependencyManager.add("sp-overlay");
46244
- import("./chunks/sp-overlay.dev-yztmtrs1.js");
46229
+ import("./chunks/sp-overlay.dev-qgvhnxf4.js");
46245
46230
  return html`
46246
46231
  <sp-overlay
46247
46232
  @slottable-request=${this.handleSlottableRequest}
@@ -56778,8 +56763,8 @@ function joinPath(parent, name) {
56778
56763
  return parent.endsWith("/") || parent.endsWith("\\") ? `${parent}${name}` : `${parent}${sep}${name}`;
56779
56764
  }
56780
56765
  function destinationPath(destination, slug) {
56781
- if (destination.kind !== "path") {
56782
- throw new Error("Only filesystem destinations have a path");
56766
+ if (destination.kind === "repo") {
56767
+ return `${destination.owner}/${destination.repo || slug.trim()}`;
56783
56768
  }
56784
56769
  return joinPath(destination.parent, slug.trim());
56785
56770
  }
@@ -56981,6 +56966,9 @@ function breakpointPolicyFromForm() {
56981
56966
  }
56982
56967
  return { count: _breakpointCount, mode: "limit", rounding: _breakpointRounding };
56983
56968
  }
56969
+ function canVerify() {
56970
+ return getPlatform().createDestination !== "repo";
56971
+ }
56984
56972
  function slugOf(name) {
56985
56973
  return name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/^-|-$/g, "");
56986
56974
  }
@@ -57014,7 +57002,7 @@ function importBriefFor(ctx) {
57014
57002
  return null;
57015
57003
  }
57016
57004
  const destination = ctx.resolveDestination();
57017
- if (!destination || destination.kind !== "path") {
57005
+ if (!destination) {
57018
57006
  return null;
57019
57007
  }
57020
57008
  return {
@@ -57028,7 +57016,7 @@ function importBriefFor(ctx) {
57028
57016
  prompt: _prompt.trim(),
57029
57017
  minFidelity: _minFidelity,
57030
57018
  url: parsed.href,
57031
- verify: _verify
57019
+ verify: canVerify() && _verify
57032
57020
  };
57033
57021
  }
57034
57022
  function handoffImport(ctx) {
@@ -57176,16 +57164,16 @@ function renderImportSource(ctx) {
57176
57164
  >
57177
57165
  AI component naming
57178
57166
  </sp-switch>
57179
- <sp-switch
57180
- .checked=${live(_verify)}
57181
- @change=${(e20) => {
57167
+ ${canVerify() ? html`<sp-switch
57168
+ .checked=${live(_verify)}
57169
+ @change=${(e20) => {
57182
57170
  _verify = e20.target.checked;
57183
57171
  ctx.rerender();
57184
57172
  }}
57185
- >
57186
- Check fidelity against the original (slower)
57187
- </sp-switch>
57188
- ${_verify ? html`
57173
+ >
57174
+ Check fidelity against the original (slower)
57175
+ </sp-switch>` : nothing}
57176
+ ${canVerify() && _verify ? html`
57189
57177
  <label class="new-project-field">
57190
57178
  <span class="new-project-label">Minimum fidelity</span>
57191
57179
  <sp-number-field
@@ -60159,7 +60147,7 @@ async function openProjectSettings(section) {
60159
60147
  showSettingsDocument();
60160
60148
  notifySettingsDocument();
60161
60149
  try {
60162
- const { syncExtensionSettingsSections } = await import("./chunks/extension-sections-3ydgjbdy.js");
60150
+ const { syncExtensionSettingsSections } = await import("./chunks/extension-sections-txv08xxg.js");
60163
60151
  await syncExtensionSettingsSections();
60164
60152
  } catch (error) {
60165
60153
  notify.warn(`Could not load extension settings sections — ${errorMessage(error)}`, {
@@ -60245,9 +60233,9 @@ function registerSettingsCommands(registry) {
60245
60233
 
60246
60234
  // src/version.ts
60247
60235
  var APP_NAME = "Jx Studio";
60248
- var VERSION = "4.0.0";
60249
- var BUILD_DATE = "2026-08-28T00:08:28.374Z";
60250
- var GIT_COMMIT = "f069523";
60236
+ var VERSION = "4.1.0";
60237
+ var BUILD_DATE = "2026-08-30T10:30:46.138Z";
60238
+ var GIT_COMMIT = "0a53920";
60251
60239
  var LINKS = {
60252
60240
  github: "https://github.com/jxsuite/jx",
60253
60241
  docs: "https://github.com/jxsuite/jx#readme",
@@ -60379,7 +60367,7 @@ function aboutCommands() {
60379
60367
  title: `About ${APP_NAME}`,
60380
60368
  category: "Help",
60381
60369
  level: "application",
60382
- menus: ["palette"],
60370
+ menus: ["commandbar/overflow", "palette"],
60383
60371
  group: "9_help",
60384
60372
  run: () => {
60385
60373
  openAboutModal();
@@ -60742,9 +60730,9 @@ function withExtension(path, ext) {
60742
60730
  return current === "" ? `${path}${ext}` : `${path.slice(0, path.length - current.length)}${ext}`;
60743
60731
  }
60744
60732
  async function readDocument(path, source2) {
60745
- const { formatForPath: formatForPath2 } = await import("./chunks/format-host-tgcmfs4p.js");
60733
+ const { formatForPath: formatForPath2 } = await import("./chunks/format-host-w16q81tf.js");
60746
60734
  if (formatForPath2(path)) {
60747
- const { parseSourceForPath: parseSourceForPath2 } = await import("./chunks/file-ops-rskmhxyq.js");
60735
+ const { parseSourceForPath: parseSourceForPath2 } = await import("./chunks/file-ops-wbh4hhsx.js");
60748
60736
  const parsed = await parseSourceForPath2(path, source2);
60749
60737
  return { document: parsed.document, frontmatter: parsed.frontmatter };
60750
60738
  }
@@ -60756,7 +60744,7 @@ async function writeDocument(targetExt, document2, frontmatter) {
60756
60744
  return `${JSON.stringify(merged, null, 2)}
60757
60745
  `;
60758
60746
  }
60759
- const { formatByExtension: formatByExtension2, formatSerialize: formatSerialize2 } = await import("./chunks/format-host-tgcmfs4p.js");
60747
+ const { formatByExtension: formatByExtension2, formatSerialize: formatSerialize2 } = await import("./chunks/format-host-w16q81tf.js");
60760
60748
  const format = formatByExtension2(targetExt, "serialize");
60761
60749
  if (!format) {
60762
60750
  throw new Error(`No installed format writes ${targetExt} files.`);
@@ -60793,7 +60781,7 @@ async function buildPlan(path, source2, targetExt) {
60793
60781
  };
60794
60782
  }
60795
60783
  if (targetExt === ".json") {
60796
- const { validateDocOrNull } = await import("./chunks/jx-validate-8q2g05x1.js");
60784
+ const { validateDocOrNull } = await import("./chunks/jx-validate-8er6gbxy.js");
60797
60785
  const errors5 = await validateDocOrNull(JSON.parse(text));
60798
60786
  if (errors5 === null) {
60799
60787
  lines.push("The result could not be checked against the document schema — that is not the same as " + "it being valid.");
@@ -60826,13 +60814,13 @@ async function convertFile(path, targetExt) {
60826
60814
  notify2.error(message, { detail, path, source: "Convert" });
60827
60815
  return null;
60828
60816
  };
60829
- const { loadFormats: loadFormats2 } = await import("./chunks/format-host-tgcmfs4p.js");
60817
+ const { loadFormats: loadFormats2 } = await import("./chunks/format-host-w16q81tf.js");
60830
60818
  await loadFormats2();
60831
60819
  const targets = convertTargets(path);
60832
60820
  if (targets.length === 0) {
60833
60821
  return fail(`${path} cannot be converted to another format.`, CANNOT_CONVERT);
60834
60822
  }
60835
- const { workspace: workspace2 } = await import("./chunks/workspace-xpres40v.js");
60823
+ const { workspace: workspace2 } = await import("./chunks/workspace-fjx52ryv.js");
60836
60824
  const { commitTabBuffers: commitTabBuffers2 } = await import("./chunks/monaco-buffer-dqw0xxpx.js");
60837
60825
  const openTabEntry = [...workspace2.tabs.values()].find((tab2) => tab2.documentPath === path);
60838
60826
  if (openTabEntry) {
@@ -60880,7 +60868,7 @@ async function convertFile(path, targetExt) {
60880
60868
  return null;
60881
60869
  }
60882
60870
  const { markLocalMutation } = await import("./chunks/fs-events-hrrg328g.js");
60883
- const { notifyMoveOutcome, settleRename } = await import("./chunks/files-0cratsr0.js");
60871
+ const { notifyMoveOutcome, settleRename } = await import("./chunks/files-3kfkwhk4.js");
60884
60872
  markLocalMutation(path, plan.targetPath);
60885
60873
  try {
60886
60874
  await platform.writeFile(path, plan.text);
@@ -60905,15 +60893,15 @@ async function convertFile(path, targetExt) {
60905
60893
  return plan.targetPath;
60906
60894
  }
60907
60895
  async function rebuildTab(from, to2, text) {
60908
- const { openTab: openTab2, renameTab } = await import("./chunks/workspace-xpres40v.js");
60909
- const { formatForPath: formatForPath2 } = await import("./chunks/format-host-tgcmfs4p.js");
60896
+ const { openTab: openTab2, renameTab } = await import("./chunks/workspace-fjx52ryv.js");
60897
+ const { formatForPath: formatForPath2 } = await import("./chunks/format-host-w16q81tf.js");
60910
60898
  renameTab(from, to2, to2);
60911
60899
  const format = formatForPath2(to2);
60912
60900
  let document2;
60913
60901
  let frontmatter;
60914
60902
  try {
60915
60903
  if (format) {
60916
- const { parseSourceForPath: parseSourceForPath2 } = await import("./chunks/file-ops-rskmhxyq.js");
60904
+ const { parseSourceForPath: parseSourceForPath2 } = await import("./chunks/file-ops-wbh4hhsx.js");
60917
60905
  ({ document: document2, frontmatter } = await parseSourceForPath2(to2, text));
60918
60906
  } else {
60919
60907
  document2 = JSON.parse(text);
@@ -61074,7 +61062,7 @@ function publishCommands() {
61074
61062
  name: "set_up_publishing"
61075
61063
  },
61076
61064
  run: async () => {
61077
- const { openPublishPanel } = await import("./chunks/publish-panel-54jvhskq.js");
61065
+ const { openPublishPanel } = await import("./chunks/publish-panel-v9st96ja.js");
61078
61066
  openPublishPanel();
61079
61067
  },
61080
61068
  title: "Set Up Publishing"
@@ -61796,7 +61784,7 @@ function i18nCommands() {
61796
61784
  });
61797
61785
  return;
61798
61786
  }
61799
- const { openFileInTab: openFileInTab2 } = await import("./chunks/files-0cratsr0.js");
61787
+ const { openFileInTab: openFileInTab2 } = await import("./chunks/files-3kfkwhk4.js");
61800
61788
  await openFileInTab2(path);
61801
61789
  },
61802
61790
  title: "Open Translation"
@@ -61843,7 +61831,7 @@ function i18nCommands() {
61843
61831
  return;
61844
61832
  }
61845
61833
  const cut = path.lastIndexOf("/");
61846
- const { createFileIn: createFileIn2, openFileInTab: openFileInTab2 } = await import("./chunks/files-0cratsr0.js");
61834
+ const { createFileIn: createFileIn2, openFileInTab: openFileInTab2 } = await import("./chunks/files-3kfkwhk4.js");
61847
61835
  const created = await createFileIn2({
61848
61836
  content,
61849
61837
  dir: cut === -1 ? "." : path.slice(0, cut),
@@ -62669,5 +62657,5 @@ export {
62669
62657
  hasUnsavedTabs
62670
62658
  };
62671
62659
 
62672
- //# debugId=5B98A201D907B4F264756E2164756E21
62660
+ //# debugId=59ED4F8CE251D97C64756E2164756E21
62673
62661
  //# sourceMappingURL=studio.js.map