@jxsuite/studio 0.35.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/studio.js CHANGED
@@ -199522,10 +199522,10 @@ function loadFromLocalStorage() {
199522
199522
  }
199523
199523
  }
199524
199524
  function currentList() {
199525
- return backend() ? cache : loadFromLocalStorage();
199525
+ return backend() ? cache2 : loadFromLocalStorage();
199526
199526
  }
199527
199527
  function commit(list2) {
199528
- cache = list2;
199528
+ cache2 = list2;
199529
199529
  const store = backend();
199530
199530
  if (store) {
199531
199531
  store.saveRecentProjects(list2);
@@ -199541,9 +199541,9 @@ async function hydrateRecentProjects() {
199541
199541
  return;
199542
199542
  }
199543
199543
  try {
199544
- cache = await store.getRecentProjects();
199544
+ cache2 = await store.getRecentProjects();
199545
199545
  } catch {
199546
- cache = [];
199546
+ cache2 = [];
199547
199547
  }
199548
199548
  }
199549
199549
  function getRecentProjects() {
@@ -199561,7 +199561,7 @@ function removeRecentProject(root) {
199561
199561
  commit(currentList().filter((p) => p.root !== root));
199562
199562
  }
199563
199563
  function clearRecentProjects() {
199564
- cache = [];
199564
+ cache2 = [];
199565
199565
  const store = backend();
199566
199566
  if (store) {
199567
199567
  store.saveRecentProjects([]);
@@ -199599,10 +199599,10 @@ function trackRecentFile(file) {
199599
199599
  }
199600
199600
  localStorage.setItem(FILES_STORAGE_KEY, JSON.stringify(kept));
199601
199601
  }
199602
- var STORAGE_KEY = "jx-studio-recent-projects", FILES_STORAGE_KEY = "jx-studio-recent-files", MAX_RECENT = 8, MAX_RECENT_FILES = 10, cache;
199602
+ var STORAGE_KEY = "jx-studio-recent-projects", FILES_STORAGE_KEY = "jx-studio-recent-files", MAX_RECENT = 8, MAX_RECENT_FILES = 10, cache2;
199603
199603
  var init_recent_projects = __esm(() => {
199604
199604
  init_platform3();
199605
- cache = [];
199605
+ cache2 = [];
199606
199606
  });
199607
199607
 
199608
199608
  // ../../node_modules/lit-html/development/directives/live.js
@@ -200063,7 +200063,7 @@ var init_progress_modal = __esm(() => {
200063
200063
  });
200064
200064
 
200065
200065
  // src/version.ts
200066
- var APP_NAME = "Jx Studio", VERSION = "0.35.0", BUILD_DATE = "2026-07-06T17:20:36.204Z", GIT_COMMIT = "01619b7", LINKS;
200066
+ var APP_NAME = "Jx Studio", VERSION = "0.36.0", BUILD_DATE = "2026-07-07T23:14:50.526Z", GIT_COMMIT = "482a801", LINKS;
200067
200067
  var init_version = __esm(() => {
200068
200068
  LINKS = {
200069
200069
  github: "https://github.com/jxsuite/jx",
@@ -201794,18 +201794,18 @@ var init_popover_reset_styles = __esm(() => {
201794
201794
 
201795
201795
  // ../../node_modules/@atlaskit/pragmatic-drag-and-drop/dist/esm/public-utils/once.js
201796
201796
  function once(fn) {
201797
- var cache2 = null;
201797
+ var cache3 = null;
201798
201798
  return function wrapped() {
201799
- if (!cache2) {
201799
+ if (!cache3) {
201800
201800
  for (var _len = arguments.length, args = new Array(_len), _key = 0;_key < _len; _key++) {
201801
201801
  args[_key] = arguments[_key];
201802
201802
  }
201803
201803
  var result = fn.apply(this, args);
201804
- cache2 = {
201804
+ cache3 = {
201805
201805
  result
201806
201806
  };
201807
201807
  }
201808
- return cache2.result;
201808
+ return cache3.result;
201809
201809
  };
201810
201810
  }
201811
201811
 
@@ -220498,6 +220498,120 @@ var init_schema_field_ui = __esm(() => {
220498
220498
  FORMAT_OPTIONS = ["", "image", "date", "color"];
220499
220499
  });
220500
220500
 
220501
+ // src/services/settings-store.ts
220502
+ function readLocal(key) {
220503
+ try {
220504
+ return globalThis.localStorage?.getItem(key) ?? "";
220505
+ } catch {
220506
+ return "";
220507
+ }
220508
+ }
220509
+ async function hydrateSettings() {
220510
+ if (!hasPlatform()) {
220511
+ return;
220512
+ }
220513
+ const platform3 = getPlatform();
220514
+ if (!platform3.getSettings) {
220515
+ return;
220516
+ }
220517
+ let stored;
220518
+ try {
220519
+ stored = await platform3.getSettings();
220520
+ } catch {
220521
+ return;
220522
+ }
220523
+ const merged = { ...stored };
220524
+ let needsMigration = false;
220525
+ for (const key of PERSISTED_SETTINGS_KEYS) {
220526
+ const backendValue = stored[key];
220527
+ if (backendValue) {
220528
+ try {
220529
+ globalThis.localStorage?.setItem(key, backendValue);
220530
+ } catch {}
220531
+ } else {
220532
+ const localValue = readLocal(key);
220533
+ if (localValue) {
220534
+ merged[key] = localValue;
220535
+ needsMigration = true;
220536
+ }
220537
+ }
220538
+ }
220539
+ if (needsMigration && platform3.saveSettings) {
220540
+ platform3.saveSettings(merged).catch(() => {});
220541
+ }
220542
+ }
220543
+ function persistSettings() {
220544
+ if (!hasPlatform()) {
220545
+ return;
220546
+ }
220547
+ const platform3 = getPlatform();
220548
+ if (!platform3.saveSettings) {
220549
+ return;
220550
+ }
220551
+ const settings = {};
220552
+ for (const key of PERSISTED_SETTINGS_KEYS) {
220553
+ const value = readLocal(key);
220554
+ if (value) {
220555
+ settings[key] = value;
220556
+ }
220557
+ }
220558
+ platform3.saveSettings(settings).catch(() => {});
220559
+ }
220560
+ var PERSISTED_SETTINGS_KEYS;
220561
+ var init_settings_store = __esm(() => {
220562
+ init_platform3();
220563
+ PERSISTED_SETTINGS_KEYS = [
220564
+ "jx.ai.openaiKey",
220565
+ "jx.ai.baseUrl",
220566
+ "jx.ai.model",
220567
+ "jx.cf.token",
220568
+ "jx.cf.accountId"
220569
+ ];
220570
+ });
220571
+
220572
+ // src/services/cf-settings.ts
220573
+ var exports_cf_settings = {};
220574
+ __export(exports_cf_settings, {
220575
+ setCfToken: () => setCfToken,
220576
+ setCfAccountId: () => setCfAccountId,
220577
+ getCfToken: () => getCfToken,
220578
+ getCfAccountId: () => getCfAccountId
220579
+ });
220580
+ function read(key) {
220581
+ try {
220582
+ return globalThis.localStorage?.getItem(key) ?? "";
220583
+ } catch {
220584
+ return "";
220585
+ }
220586
+ }
220587
+ function write(key, value) {
220588
+ try {
220589
+ const trimmed = (value || "").trim();
220590
+ if (trimmed) {
220591
+ globalThis.localStorage?.setItem(key, trimmed);
220592
+ } else {
220593
+ globalThis.localStorage?.removeItem(key);
220594
+ }
220595
+ } catch {}
220596
+ persistSettings();
220597
+ }
220598
+ function getCfToken() {
220599
+ return read(TOKEN_STORAGE);
220600
+ }
220601
+ function setCfToken(token) {
220602
+ write(TOKEN_STORAGE, token);
220603
+ }
220604
+ function getCfAccountId() {
220605
+ return read(ACCOUNT_STORAGE);
220606
+ }
220607
+ function setCfAccountId(accountId) {
220608
+ write(ACCOUNT_STORAGE, accountId);
220609
+ }
220610
+ var TOKEN_STORAGE = "jx.cf.token", ACCOUNT_STORAGE = "jx.cf.accountId";
220611
+ var init_cf_settings = __esm(() => {
220612
+ init_settings_store();
220613
+ });
220614
+
220501
220615
  // ../../node_modules/@lit/reactive-element/development/css-tag.js
220502
220616
  class CSSResult {
220503
220617
  constructor(cssText, strings, safeToken) {
@@ -221328,17 +221442,17 @@ var desc = (obj, name, descriptor) => {
221328
221442
  };
221329
221443
 
221330
221444
  // ../../node_modules/@lit/reactive-element/development/decorators/query.js
221331
- function query(selector, cache2) {
221445
+ function query(selector, cache3) {
221332
221446
  return (protoOrTarget, nameOrContext, descriptor) => {
221333
221447
  const doQuery = (el) => {
221334
221448
  const result = el.renderRoot?.querySelector(selector) ?? null;
221335
- if (DEV_MODE6 && result === null && cache2 && !el.hasUpdated) {
221449
+ if (DEV_MODE6 && result === null && cache3 && !el.hasUpdated) {
221336
221450
  const name = typeof nameOrContext === "object" ? nameOrContext.name : nameOrContext;
221337
221451
  issueWarning5("", `@query'd field ${JSON.stringify(String(name))} with the 'cache' ` + `flag set for selector '${selector}' has been accessed before ` + `the first update and returned null. This is expected if the ` + `renderRoot tree has not been provided beforehand (e.g. via ` + `Declarative Shadow DOM). Therefore the value hasn't been cached.`);
221338
221452
  }
221339
221453
  return result;
221340
221454
  };
221341
- if (cache2) {
221455
+ if (cache3) {
221342
221456
  const { get, set } = typeof nameOrContext === "object" ? protoOrTarget : descriptor ?? (() => {
221343
221457
  const key = DEV_MODE6 ? Symbol(`${String(nameOrContext)} (@query() cache)`) : Symbol();
221344
221458
  return {
@@ -225036,8 +225150,8 @@ function hasFixedPositionAncestor(element2, stopNode) {
225036
225150
  }
225037
225151
  return getComputedStyle3(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode);
225038
225152
  }
225039
- function getClippingElementAncestors(element2, cache2) {
225040
- const cachedResult = cache2.get(element2);
225153
+ function getClippingElementAncestors(element2, cache3) {
225154
+ const cachedResult = cache3.get(element2);
225041
225155
  if (cachedResult) {
225042
225156
  return cachedResult;
225043
225157
  }
@@ -225059,7 +225173,7 @@ function getClippingElementAncestors(element2, cache2) {
225059
225173
  }
225060
225174
  currentNode = getParentNode(currentNode);
225061
225175
  }
225062
- cache2.set(element2, result);
225176
+ cache3.set(element2, result);
225063
225177
  return result;
225064
225178
  }
225065
225179
  function getClippingRect(_ref) {
@@ -225336,14 +225450,14 @@ var noOffsets, SCROLLBAR_MAX = 25, absoluteOrFixed, getElementRects = async func
225336
225450
  }
225337
225451
  };
225338
225452
  }, platform3, offset2, shift3, flip2, size3, arrow2, computePosition2 = (reference, floating, options) => {
225339
- const cache2 = new Map;
225453
+ const cache3 = new Map;
225340
225454
  const mergedOptions = {
225341
225455
  platform: platform3,
225342
225456
  ...options
225343
225457
  };
225344
225458
  const platformWithCache = {
225345
225459
  ...mergedOptions.platform,
225346
- _c: cache2
225460
+ _c: cache3
225347
225461
  };
225348
225462
  return computePosition(reference, floating, {
225349
225463
  ...mergedOptions,
@@ -260877,12 +260991,46 @@ var project_schema_default = {
260877
260991
  adapter: {
260878
260992
  description: "Platform adapter for deployment-specific output.",
260879
260993
  enum: [
260880
- "netlify",
260881
- "vercel",
260882
- "cloudflare"
260994
+ "static",
260995
+ "cloudflare-pages",
260996
+ "cloudflare-workers",
260997
+ "node",
260998
+ "bun"
260883
260999
  ],
260884
261000
  type: "string"
260885
261001
  },
261002
+ deploy: {
261003
+ additionalProperties: false,
261004
+ description: "Deployment tracking: the hosting project this repo publishes to. Identifiers only (no secrets) — safe to commit; Studio uses it to tell whether the publish workflow already exists. `adapter` says how the build is packaged; `deploy` says where it ships.",
261005
+ properties: {
261006
+ accountId: {
261007
+ description: "Hosting account id (e.g. the Cloudflare account id).",
261008
+ type: "string"
261009
+ },
261010
+ productionUrl: {
261011
+ description: "Production URL of the connected hosting project.",
261012
+ type: "string"
261013
+ },
261014
+ projectName: {
261015
+ description: "Hosting project name (e.g. the Cloudflare Pages project).",
261016
+ pattern: "^[a-z0-9][a-z0-9-]*$",
261017
+ type: "string"
261018
+ },
261019
+ provider: {
261020
+ description: "Hosting provider the project is connected to.",
261021
+ enum: [
261022
+ "cloudflare-pages"
261023
+ ],
261024
+ type: "string"
261025
+ }
261026
+ },
261027
+ required: [
261028
+ "provider",
261029
+ "accountId",
261030
+ "projectName"
261031
+ ],
261032
+ type: "object"
261033
+ },
260886
261034
  format: {
260887
261035
  default: "directory",
260888
261036
  description: "Output format.",
@@ -261133,6 +261281,29 @@ init_format_host();
261133
261281
 
261134
261282
  // src/panels/welcome-screen.ts
261135
261283
  init_lit_html();
261284
+
261285
+ // src/project-list.ts
261286
+ init_platform3();
261287
+ var cache = [];
261288
+ function platformListsProjects() {
261289
+ return hasPlatform() && typeof getPlatform().listProjects === "function";
261290
+ }
261291
+ async function hydrateProjectList() {
261292
+ if (!platformListsProjects()) {
261293
+ cache = [];
261294
+ return;
261295
+ }
261296
+ try {
261297
+ cache = await getPlatform().listProjects?.() ?? [];
261298
+ } catch {
261299
+ cache = [];
261300
+ }
261301
+ }
261302
+ function getProjectList() {
261303
+ return cache;
261304
+ }
261305
+
261306
+ // src/panels/welcome-screen.ts
261136
261307
  init_recent_projects();
261137
261308
  init_store();
261138
261309
  init_git_panel();
@@ -261143,6 +261314,7 @@ function initWelcome(ctx) {
261143
261314
  function renderWelcome(host) {
261144
261315
  const ctx = _ctx2;
261145
261316
  const recent = getRecentProjects();
261317
+ const catalogue = getProjectList().filter((p) => !recent.some((r) => r.root === p.root));
261146
261318
  const showClone = platformSupportsClone();
261147
261319
  render2(html3`
261148
261320
  <div class="welcome-screen">
@@ -261196,6 +261368,25 @@ function renderWelcome(host) {
261196
261368
  </button>` : nothing}
261197
261369
  </div>
261198
261370
 
261371
+ ${catalogue.length > 0 ? html3`
261372
+ <div class="welcome-section">
261373
+ <h2 class="welcome-section-title">Projects</h2>
261374
+ ${catalogue.map((p) => html3`
261375
+ <div class="welcome-recent-row">
261376
+ <button
261377
+ class="welcome-recent welcome-catalogue"
261378
+ @click=${() => ctx.openRecentProject(p.root)}
261379
+ title=${p.root}
261380
+ >
261381
+ <span class="welcome-recent-name">${p.name}</span>
261382
+ <span class="welcome-recent-path">
261383
+ ${p.description ?? shortenPath(p.root)}
261384
+ </span>
261385
+ </button>
261386
+ </div>
261387
+ `)}
261388
+ </div>
261389
+ ` : nothing}
261199
261390
  ${recent.length > 0 ? html3`
261200
261391
  <div class="welcome-section">
261201
261392
  <div class="welcome-section-header">
@@ -262151,15 +262342,15 @@ function isShallowEqual(a, b) {
262151
262342
  }
262152
262343
  function stable() {
262153
262344
  var isEqual2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : isShallowEqual;
262154
- var cache2 = null;
262345
+ var cache3 = null;
262155
262346
  return function(value) {
262156
- if (cache2 && isEqual2(cache2.value, value)) {
262157
- return cache2.value;
262347
+ if (cache3 && isEqual2(cache3.value, value)) {
262348
+ return cache3.value;
262158
262349
  }
262159
- cache2 = {
262350
+ cache3 = {
262160
262351
  value
262161
262352
  };
262162
- return cache2.value;
262353
+ return cache3.value;
262163
262354
  };
262164
262355
  }
262165
262356
 
@@ -269936,6 +270127,56 @@ function createDevServerPlatform() {
269936
270127
  throw new Error(body.error);
269937
270128
  }
269938
270129
  },
270130
+ async cfApi(apiPath, init) {
270131
+ const { getCfToken: getCfToken2 } = await Promise.resolve().then(() => (init_cf_settings(), exports_cf_settings));
270132
+ const token = getCfToken2();
270133
+ if (!token) {
270134
+ throw new Error("No Cloudflare API token configured");
270135
+ }
270136
+ const res = await fetch("/__studio/cf/proxy", {
270137
+ method: "POST",
270138
+ headers: { "Content-Type": "application/json", "X-CF-Token": token },
270139
+ body: JSON.stringify({ path: apiPath, method: init?.method ?? "GET", body: init?.body })
270140
+ });
270141
+ const envelope = await res.json();
270142
+ if (!res.ok || envelope.success === false) {
270143
+ const message = envelope.errors?.map((e) => e.message).join("; ") ?? envelope.error ?? res.statusText;
270144
+ throw new Error(`Cloudflare API: ${message}`);
270145
+ }
270146
+ return envelope.result ?? envelope;
270147
+ },
270148
+ async cfConnection() {
270149
+ const { getCfAccountId: getCfAccountId2, getCfToken: getCfToken2, setCfAccountId: setCfAccountId2 } = await Promise.resolve().then(() => (init_cf_settings(), exports_cf_settings));
270150
+ if (!getCfToken2()) {
270151
+ return null;
270152
+ }
270153
+ try {
270154
+ const accounts = await this.cfApi?.("/accounts");
270155
+ if (!accounts?.length) {
270156
+ return { connected: false };
270157
+ }
270158
+ const chosen = accounts.find((a) => a.id === getCfAccountId2()) ?? accounts[0];
270159
+ setCfAccountId2(chosen.id);
270160
+ return { connected: true, accountId: chosen.id, accountName: chosen.name };
270161
+ } catch {
270162
+ return { connected: false };
270163
+ }
270164
+ },
270165
+ async listProjects() {
270166
+ const res = await fetch("/__studio/sites");
270167
+ if (!res.ok) {
270168
+ return [];
270169
+ }
270170
+ const sites = await readJson(res);
270171
+ return sites.map((site) => {
270172
+ const config = site.config;
270173
+ return {
270174
+ name: config?.name || site.path.split("/").at(-1) || site.path,
270175
+ root: site.path,
270176
+ description: site.path
270177
+ };
270178
+ });
270179
+ },
269939
270180
  aiChatUrl() {
269940
270181
  return "/__studio/ai/chat";
269941
270182
  }
@@ -296319,84 +296560,457 @@ function renderActivityBar() {
296319
296560
 
296320
296561
  // src/panels/toolbar.ts
296321
296562
  init_lit_html();
296322
- init_store();
296323
- init_transact();
296324
- init_reactivity();
296325
- init_workspace2();
296326
- init_view3();
296327
- init_recent_projects();
296328
- init_platform3();
296329
- init_git_panel();
296330
296563
 
296331
- // src/new-project/new-project-modal.ts
296564
+ // src/publish/publish-panel.ts
296332
296565
  init_lit_html();
296333
- init_parse();
296334
- init_layers();
296335
296566
  init_platform3();
296567
+ init_cf_settings();
296568
+ init_store();
296569
+ init_layers();
296336
296570
 
296337
- // src/services/settings-store.ts
296338
- init_platform3();
296339
- var PERSISTED_SETTINGS_KEYS = ["jx.ai.openaiKey", "jx.ai.baseUrl", "jx.ai.model"];
296340
- function readLocal(key) {
296571
+ // ../create/scaffold.ts
296572
+ var CF_ADAPTERS = new Set(["cloudflare-pages", "cloudflare-workers"]);
296573
+ function buildWranglerJsonc({ slug, adapter: adapter2 }) {
296574
+ const compatibilityDate = new Date().toISOString().slice(0, 10);
296575
+ const config = adapter2 === "cloudflare-workers" ? {
296576
+ assets: { binding: "ASSETS", directory: "./dist" },
296577
+ compatibility_date: compatibilityDate,
296578
+ compatibility_flags: ["nodejs_compat"],
296579
+ main: "./dist/worker.js",
296580
+ name: slug
296581
+ } : {
296582
+ compatibility_date: compatibilityDate,
296583
+ compatibility_flags: ["nodejs_compat"],
296584
+ name: slug,
296585
+ pages_build_output_dir: "./dist"
296586
+ };
296587
+ return `${JSON.stringify(config, null, "\t")}
296588
+ `;
296589
+ }
296590
+ function updateWranglerConfig(existing, { slug, adapter: adapter2 }) {
296591
+ if (!existing) {
296592
+ return { content: buildWranglerJsonc({ adapter: adapter2, slug }), patched: true };
296593
+ }
296594
+ let config;
296341
296595
  try {
296342
- return globalThis.localStorage?.getItem(key) ?? "";
296596
+ config = JSON.parse(existing);
296343
296597
  } catch {
296344
- return "";
296598
+ return { content: existing, patched: false };
296345
296599
  }
296346
- }
296347
- async function hydrateSettings() {
296348
- if (!hasPlatform()) {
296349
- return;
296600
+ config["name"] = slug;
296601
+ if (adapter2 === "cloudflare-workers") {
296602
+ delete config["pages_build_output_dir"];
296603
+ config["main"] = "./dist/worker.js";
296604
+ config["assets"] = { binding: "ASSETS", directory: "./dist" };
296605
+ } else {
296606
+ delete config["main"];
296607
+ delete config["assets"];
296608
+ config["pages_build_output_dir"] = "./dist";
296350
296609
  }
296351
- const platform4 = getPlatform();
296352
- if (!platform4.getSettings) {
296353
- return;
296610
+ return { content: `${JSON.stringify(config, null, "\t")}
296611
+ `, patched: true };
296612
+ }
296613
+
296614
+ // src/publish/pages-service.ts
296615
+ init_platform3();
296616
+ init_site_context();
296617
+ function platformSupportsPublish() {
296618
+ return typeof getPlatform().cfApi === "function";
296619
+ }
296620
+ async function cfApi(path, init) {
296621
+ const api2 = getPlatform().cfApi;
296622
+ if (!api2) {
296623
+ throw new Error("This platform cannot reach the Cloudflare API");
296354
296624
  }
296355
- let stored;
296625
+ return await api2(path, init);
296626
+ }
296627
+ async function listAccounts() {
296628
+ return cfApi("/accounts");
296629
+ }
296630
+ async function getPagesProject(accountId, projectName) {
296356
296631
  try {
296357
- stored = await platform4.getSettings();
296632
+ return await cfApi(`/accounts/${accountId}/pages/projects/${projectName}`);
296358
296633
  } catch {
296359
- return;
296634
+ return null;
296360
296635
  }
296361
- const merged = { ...stored };
296362
- let needsMigration = false;
296363
- for (const key of PERSISTED_SETTINGS_KEYS) {
296364
- const backendValue = stored[key];
296365
- if (backendValue) {
296366
- try {
296367
- globalThis.localStorage?.setItem(key, backendValue);
296368
- } catch {}
296369
- } else {
296370
- const localValue = readLocal(key);
296371
- if (localValue) {
296372
- merged[key] = localValue;
296373
- needsMigration = true;
296636
+ }
296637
+ async function createPagesProject(opts) {
296638
+ return cfApi(`/accounts/${opts.accountId}/pages/projects`, {
296639
+ method: "POST",
296640
+ body: {
296641
+ name: opts.projectName,
296642
+ production_branch: opts.productionBranch,
296643
+ build_config: {
296644
+ build_command: "bunx jx build",
296645
+ destination_dir: "dist"
296646
+ },
296647
+ source: {
296648
+ type: "github",
296649
+ config: {
296650
+ owner: opts.owner,
296651
+ repo_name: opts.repo,
296652
+ production_branch: opts.productionBranch,
296653
+ deployments_enabled: true
296654
+ }
296655
+ }
296656
+ }
296657
+ });
296658
+ }
296659
+ async function latestDeployment(deploy) {
296660
+ const deployments = await cfApi(`/accounts/${deploy.accountId}/pages/projects/${deploy.projectName}/deployments`);
296661
+ const [latest] = deployments;
296662
+ if (!latest) {
296663
+ return null;
296664
+ }
296665
+ return {
296666
+ id: latest.id,
296667
+ url: latest.url,
296668
+ environment: latest.environment,
296669
+ stage: latest.latest_stage?.name ?? "unknown",
296670
+ status: latest.latest_stage?.status ?? "unknown",
296671
+ createdOn: latest.created_on
296672
+ };
296673
+ }
296674
+ async function writeDeployConfig(config, deploy) {
296675
+ const build = { ...config.build };
296676
+ if (deploy === null) {
296677
+ delete build.deploy;
296678
+ } else {
296679
+ build.deploy = deploy;
296680
+ }
296681
+ await updateSiteConfig({ build });
296682
+ if (deploy !== null) {
296683
+ const platform4 = getPlatform();
296684
+ let existing = null;
296685
+ try {
296686
+ existing = await platform4.readFile("wrangler.jsonc");
296687
+ } catch {
296688
+ existing = null;
296689
+ }
296690
+ const adapter2 = build.adapter === "cloudflare-workers" ? "cloudflare-workers" : "cloudflare-pages";
296691
+ const { content, patched } = updateWranglerConfig(existing, {
296692
+ adapter: adapter2,
296693
+ slug: deploy.projectName
296694
+ });
296695
+ if (patched) {
296696
+ await platform4.writeFile("wrangler.jsonc", content);
296697
+ }
296698
+ }
296699
+ }
296700
+ async function connectDeploy(config, opts) {
296701
+ const existing = await getPagesProject(opts.accountId, opts.projectName);
296702
+ const project = existing ?? await createPagesProject(opts);
296703
+ const deploy = {
296704
+ provider: "cloudflare-pages",
296705
+ accountId: opts.accountId,
296706
+ projectName: opts.projectName,
296707
+ ...project.subdomain ? { productionUrl: `https://${project.subdomain}` } : {}
296708
+ };
296709
+ await writeDeployConfig(config, deploy);
296710
+ return deploy;
296711
+ }
296712
+
296713
+ // src/publish/publish-panel.ts
296714
+ var PAGES_APP_INSTALL_URL = "https://github.com/apps/cloudflare-pages/installations/new";
296715
+ var _handle4 = null;
296716
+ var _connection = "loading";
296717
+ var _accounts = [];
296718
+ var _deployment = null;
296719
+ var _error = "";
296720
+ var _busy2 = false;
296721
+ var _form = { accountId: "", branch: "main", owner: "", projectName: "", repo: "" };
296722
+ function currentConfig() {
296723
+ return projectState?.projectConfig ?? null;
296724
+ }
296725
+ function currentDeploy() {
296726
+ return currentConfig()?.build?.deploy;
296727
+ }
296728
+ function deriveSlug(name) {
296729
+ return name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/^-+|-+$/g, "").slice(0, 58) || "site";
296730
+ }
296731
+ function prefillRepo() {
296732
+ const root2 = getPlatform().projectRoot;
296733
+ const match2 = /^([\w.-]+)\/([\w.-]+)$/.exec(root2);
296734
+ return match2 ? { owner: match2[1], repo: match2[2] } : { owner: "", repo: "" };
296735
+ }
296736
+ async function loadConnection() {
296737
+ _connection = "loading";
296738
+ render6();
296739
+ try {
296740
+ _connection = await getPlatform().cfConnection?.() ?? null;
296741
+ if (_connection?.connected) {
296742
+ _accounts = await listAccounts();
296743
+ _form.accountId = _connection.accountId ?? _accounts[0]?.id ?? "";
296744
+ const deploy = currentDeploy();
296745
+ if (deploy) {
296746
+ _deployment = await latestDeployment(deploy);
296374
296747
  }
296375
296748
  }
296749
+ } catch (error) {
296750
+ _connection = null;
296751
+ _error = error instanceof Error ? error.message : String(error);
296376
296752
  }
296377
- if (needsMigration && platform4.saveSettings) {
296378
- platform4.saveSettings(merged).catch(() => {});
296753
+ render6();
296754
+ }
296755
+ async function saveToken(host) {
296756
+ const input = host.querySelector("#cf-token-input");
296757
+ setCfToken(input?.value ?? "");
296758
+ _error = "";
296759
+ await loadConnection();
296760
+ }
296761
+ async function hostedConnect() {
296762
+ _busy2 = true;
296763
+ render6();
296764
+ try {
296765
+ await getPlatform().cfConnect?.();
296766
+ } catch (error) {
296767
+ _error = error instanceof Error ? error.message : String(error);
296379
296768
  }
296769
+ _busy2 = false;
296770
+ await loadConnection();
296380
296771
  }
296381
- function persistSettings() {
296382
- if (!hasPlatform()) {
296772
+ async function submitConnect() {
296773
+ const config = currentConfig();
296774
+ if (!config) {
296383
296775
  return;
296384
296776
  }
296385
- const platform4 = getPlatform();
296386
- if (!platform4.saveSettings) {
296777
+ if (!_form.projectName || !_form.owner || !_form.repo || !_form.accountId) {
296778
+ _error = "Account, project name, and the GitHub owner/repo are all required.";
296779
+ render6();
296387
296780
  return;
296388
296781
  }
296389
- const settings = {};
296390
- for (const key of PERSISTED_SETTINGS_KEYS) {
296391
- const value = readLocal(key);
296392
- if (value) {
296393
- settings[key] = value;
296394
- }
296782
+ _busy2 = true;
296783
+ _error = "";
296784
+ render6();
296785
+ try {
296786
+ const deploy = await connectDeploy(config, {
296787
+ accountId: _form.accountId,
296788
+ owner: _form.owner,
296789
+ productionBranch: _form.branch || "main",
296790
+ projectName: _form.projectName,
296791
+ repo: _form.repo
296792
+ });
296793
+ _deployment = await latestDeployment(deploy).catch(() => null);
296794
+ } catch (error) {
296795
+ _error = error instanceof Error ? error.message : String(error);
296796
+ }
296797
+ _busy2 = false;
296798
+ render6();
296799
+ }
296800
+ async function disconnect() {
296801
+ const config = currentConfig();
296802
+ if (!config) {
296803
+ return;
296804
+ }
296805
+ _busy2 = true;
296806
+ render6();
296807
+ try {
296808
+ await writeDeployConfig(config, null);
296809
+ _deployment = null;
296810
+ } catch (error) {
296811
+ _error = error instanceof Error ? error.message : String(error);
296812
+ }
296813
+ _busy2 = false;
296814
+ render6();
296815
+ }
296816
+ function close() {
296817
+ _handle4?.close();
296818
+ _handle4 = null;
296819
+ }
296820
+ function fieldRow(label, input) {
296821
+ return html3`
296822
+ <label class="publish-field">
296823
+ <span>${label}</span>
296824
+ ${input}
296825
+ </label>
296826
+ `;
296827
+ }
296828
+ function credentialTpl() {
296829
+ const platform4 = getPlatform();
296830
+ if (platform4.cfConnect) {
296831
+ return html3`
296832
+ <p>Connect your Cloudflare account to publish this site.</p>
296833
+ <sp-button ?disabled=${_busy2} @click=${() => void hostedConnect()}>
296834
+ Connect Cloudflare
296835
+ </sp-button>
296836
+ `;
296837
+ }
296838
+ return html3`
296839
+ <p>
296840
+ Paste a Cloudflare API token (permissions: Account Settings Read, Pages Read/Write). It is
296841
+ stored locally and only sent to the same-origin proxy.
296842
+ </p>
296843
+ ${fieldRow("API token", html3`<sp-textfield
296844
+ id="cf-token-input"
296845
+ type="password"
296846
+ value=${getCfToken()}
296847
+ placeholder="cf_..."
296848
+ ></sp-textfield>`)}
296849
+ <sp-button ?disabled=${_busy2} @click=${(e20) => void saveToken(hostOf(e20))}>
296850
+ Verify & Connect
296851
+ </sp-button>
296852
+ `;
296853
+ }
296854
+ function hostOf(e20) {
296855
+ return e20.target.closest(".publish-modal") ?? document.body;
296856
+ }
296857
+ function connectFormTpl() {
296858
+ return html3`
296859
+ <p>
296860
+ Create a Cloudflare Pages project connected to this repository. Every commit then builds and
296861
+ publishes automatically (<code>bunx jx build</code>).
296862
+ </p>
296863
+ ${fieldRow("Account", html3`
296864
+ <sp-picker
296865
+ value=${_form.accountId}
296866
+ @change=${(e20) => {
296867
+ _form.accountId = e20.target.value;
296868
+ }}
296869
+ >
296870
+ ${_accounts.map((a5) => html3`<sp-menu-item value=${a5.id}>${a5.name}</sp-menu-item>`)}
296871
+ </sp-picker>
296872
+ `)}
296873
+ ${fieldRow("Pages project name", html3`<sp-textfield
296874
+ value=${_form.projectName}
296875
+ @input=${(e20) => {
296876
+ _form.projectName = e20.target.value;
296877
+ }}
296878
+ ></sp-textfield>`)}
296879
+ ${fieldRow("GitHub owner", html3`<sp-textfield
296880
+ value=${_form.owner}
296881
+ @input=${(e20) => {
296882
+ _form.owner = e20.target.value;
296883
+ }}
296884
+ ></sp-textfield>`)}
296885
+ ${fieldRow("GitHub repository", html3`<sp-textfield
296886
+ value=${_form.repo}
296887
+ @input=${(e20) => {
296888
+ _form.repo = e20.target.value;
296889
+ }}
296890
+ ></sp-textfield>`)}
296891
+ ${fieldRow("Production branch", html3`<sp-textfield
296892
+ value=${_form.branch}
296893
+ @input=${(e20) => {
296894
+ _form.branch = e20.target.value;
296895
+ }}
296896
+ ></sp-textfield>`)}
296897
+ <sp-button ?disabled=${_busy2} @click=${() => void submitConnect()}>
296898
+ ${_busy2 ? "Connecting…" : "Create & Connect"}
296899
+ </sp-button>
296900
+ `;
296901
+ }
296902
+ function statusTpl(deploy) {
296903
+ return html3`
296904
+ <p>
296905
+ Connected to Pages project <strong>${deploy.projectName}</strong>
296906
+ ${deploy.productionUrl ? html3` —
296907
+ <a href=${deploy.productionUrl} target="_blank" rel="noreferrer">
296908
+ ${deploy.productionUrl}
296909
+ </a>` : ""}
296910
+ </p>
296911
+ ${_deployment ? html3`
296912
+ <p>
296913
+ Latest deployment: <strong>${_deployment.stage}: ${_deployment.status}</strong>
296914
+ (${_deployment.environment}) —
296915
+ <a href=${_deployment.url} target="_blank" rel="noreferrer">preview</a>
296916
+ </p>
296917
+ ` : html3`<p>No deployments yet — the first commit after connecting triggers one.</p>`}
296918
+ <p class="publish-hint">Publishing happens automatically on every commit.</p>
296919
+ <div class="publish-actions">
296920
+ <sp-button variant="secondary" ?disabled=${_busy2} @click=${() => void loadConnection()}>
296921
+ Refresh
296922
+ </sp-button>
296923
+ <sp-button variant="negative" ?disabled=${_busy2} @click=${() => void disconnect()}>
296924
+ Disconnect
296925
+ </sp-button>
296926
+ </div>
296927
+ `;
296928
+ }
296929
+ function bodyTpl() {
296930
+ if (!platformSupportsPublish()) {
296931
+ return html3`
296932
+ <p>
296933
+ This platform cannot reach the Cloudflare API. Publish by committing and pushing — your host
296934
+ builds <code>bunx jx build</code> and serves <code>dist/</code>.
296935
+ </p>
296936
+ `;
296937
+ }
296938
+ if (_connection === "loading") {
296939
+ return html3`<p>Checking Cloudflare connection…</p>`;
296940
+ }
296941
+ if (!_connection?.connected) {
296942
+ return credentialTpl();
296943
+ }
296944
+ const deploy = currentDeploy();
296945
+ return deploy ? statusTpl(deploy) : connectFormTpl();
296946
+ }
296947
+ function errorTpl() {
296948
+ if (!_error) {
296949
+ return "";
296950
+ }
296951
+ const needsPagesApp = /github/i.test(_error) && /app|install|source|repo/i.test(_error);
296952
+ return html3`
296953
+ <p class="publish-error">
296954
+ ${_error}
296955
+ ${needsPagesApp ? html3` — if the Cloudflare Pages GitHub App is not installed on the repository,
296956
+ <a href=${PAGES_APP_INSTALL_URL} target="_blank" rel="noreferrer">install it</a> and
296957
+ retry.` : ""}
296958
+ </p>
296959
+ `;
296960
+ }
296961
+ function render6() {
296962
+ const tpl = html3`
296963
+ <div class="new-project-modal publish-modal">
296964
+ <div class="new-project-modal-header">
296965
+ <h2 class="new-project-modal-title">Publish</h2>
296966
+ <sp-action-button size="s" quiet @click=${close}>✕</sp-action-button>
296967
+ </div>
296968
+ <div class="new-project-modal-body">${bodyTpl()} ${errorTpl()}</div>
296969
+ </div>
296970
+ `;
296971
+ if (_handle4) {
296972
+ _handle4.update(tpl);
296973
+ } else {
296974
+ _handle4 = openModal(tpl);
296395
296975
  }
296396
- platform4.saveSettings(settings).catch(() => {});
296397
296976
  }
296977
+ function openPublishPanel() {
296978
+ const config = currentConfig();
296979
+ const { owner, repo } = prefillRepo();
296980
+ _connection = "loading";
296981
+ _accounts = [];
296982
+ _deployment = null;
296983
+ _error = "";
296984
+ _busy2 = false;
296985
+ _form = {
296986
+ accountId: "",
296987
+ branch: "main",
296988
+ owner,
296989
+ projectName: currentDeploy()?.projectName ?? deriveSlug(config?.name ?? ""),
296990
+ repo
296991
+ };
296992
+ render6();
296993
+ loadConnection();
296994
+ }
296995
+
296996
+ // src/panels/toolbar.ts
296997
+ init_store();
296998
+ init_transact();
296999
+ init_reactivity();
297000
+ init_workspace2();
297001
+ init_view3();
297002
+ init_recent_projects();
297003
+ init_platform3();
297004
+ init_git_panel();
297005
+
297006
+ // src/new-project/new-project-modal.ts
297007
+ init_lit_html();
297008
+ init_parse();
297009
+ init_layers();
297010
+ init_platform3();
296398
297011
 
296399
297012
  // src/services/ai-settings.ts
297013
+ init_settings_store();
296400
297014
  var KEY_STORAGE = "jx.ai.openaiKey";
296401
297015
  var BASE_URL_STORAGE = "jx.ai.baseUrl";
296402
297016
  var MODEL_STORAGE = "jx.ai.model";
@@ -296506,13 +297120,22 @@ init_lit_html();
296506
297120
 
296507
297121
  // src/services/ai-models.ts
296508
297122
  init_platform3();
296509
- var cache2 = null;
297123
+ var cache3 = null;
297124
+ var proxyConfigured = false;
297125
+ var proxyManaged = false;
297126
+ var proxyDefaultModel = "";
296510
297127
  function invalidateModelCache() {
296511
- cache2 = null;
297128
+ cache3 = null;
297129
+ proxyConfigured = false;
297130
+ proxyManaged = false;
297131
+ proxyDefaultModel = "";
297132
+ }
297133
+ function isProxyConfigured() {
297134
+ return proxyConfigured;
296512
297135
  }
296513
297136
  async function fetchAvailableModels(opts = {}) {
296514
- if (cache2 && !opts.force) {
296515
- return cache2;
297137
+ if (cache3 && !opts.force) {
297138
+ return cache3;
296516
297139
  }
296517
297140
  const plat = getPlatform();
296518
297141
  const chatUrl = await Promise.resolve(plat.aiChatUrl());
@@ -296531,8 +297154,11 @@ async function fetchAvailableModels(opts = {}) {
296531
297154
  throw new Error(`HTTP ${resp.status}`);
296532
297155
  }
296533
297156
  const data = await resp.json();
296534
- cache2 = (data.models || []).map((m3) => ({ id: m3.id, name: m3.name || m3.id }));
296535
- return cache2;
297157
+ proxyConfigured = data.configured === true;
297158
+ proxyManaged = data.managed === true;
297159
+ proxyDefaultModel = data.defaultModel ?? "";
297160
+ cache3 = (data.models || []).map((m3) => ({ id: m3.id, name: m3.name || m3.id }));
297161
+ return cache3;
296536
297162
  }
296537
297163
 
296538
297164
  // src/ui/ai-credentials-form.ts
@@ -296588,7 +297214,7 @@ function createAiCredentialsForm(opts) {
296588
297214
  opts.requestRender();
296589
297215
  }
296590
297216
  }
296591
- function render6() {
297217
+ function render7() {
296592
297218
  const haveKey = hasOpenAiKey();
296593
297219
  return html3`
296594
297220
  <div
@@ -296659,7 +297285,7 @@ function createAiCredentialsForm(opts) {
296659
297285
  </div>
296660
297286
  `;
296661
297287
  }
296662
- return { render: render6, startEdit };
297288
+ return { render: render7, startEdit };
296663
297289
  }
296664
297290
 
296665
297291
  // src/new-project/templates.ts
@@ -297154,8 +297780,8 @@ function renderImportSource(ctx) {
297154
297780
  }
297155
297781
 
297156
297782
  // src/new-project/new-project-modal.ts
297157
- var _handle4 = null;
297158
- var _form = {
297783
+ var _handle5 = null;
297784
+ var _form2 = {
297159
297785
  adapter: "static",
297160
297786
  description: "",
297161
297787
  directory: "",
@@ -297168,7 +297794,7 @@ var _template = "blank";
297168
297794
  var _starter = "";
297169
297795
  var _agentPrompt = "";
297170
297796
  var _paramsSeededFor = "";
297171
- var _error = "";
297797
+ var _error2 = "";
297172
297798
  var _creating = false;
297173
297799
  var _starters = [];
297174
297800
  var _resolve = null;
@@ -297176,12 +297802,12 @@ var _credsForm = null;
297176
297802
  function credsForm() {
297177
297803
  _credsForm ??= createAiCredentialsForm({
297178
297804
  onSaved: () => {
297179
- if (_handle4) {
297805
+ if (_handle5) {
297180
297806
  renderModal3();
297181
297807
  }
297182
297808
  },
297183
297809
  requestRender: () => {
297184
- if (_handle4) {
297810
+ if (_handle5) {
297185
297811
  renderModal3();
297186
297812
  }
297187
297813
  }
@@ -297189,10 +297815,10 @@ function credsForm() {
297189
297815
  return _credsForm;
297190
297816
  }
297191
297817
  function openNewProjectModal() {
297192
- if (_handle4) {
297818
+ if (_handle5) {
297193
297819
  return Promise.resolve(null);
297194
297820
  }
297195
- _form = {
297821
+ _form2 = {
297196
297822
  adapter: "static",
297197
297823
  description: "",
297198
297824
  directory: "",
@@ -297205,7 +297831,7 @@ function openNewProjectModal() {
297205
297831
  _starter = "";
297206
297832
  _agentPrompt = "";
297207
297833
  _paramsSeededFor = "";
297208
- _error = "";
297834
+ _error2 = "";
297209
297835
  _creating = false;
297210
297836
  _starters = [];
297211
297837
  _dirDerived = true;
@@ -297218,7 +297844,7 @@ function openNewProjectModal() {
297218
297844
  if (!_starter) {
297219
297845
  _starter = starters[0]?.id ?? "";
297220
297846
  }
297221
- if (_handle4) {
297847
+ if (_handle5) {
297222
297848
  renderModal3();
297223
297849
  }
297224
297850
  }).catch(() => {});
@@ -297229,11 +297855,11 @@ function openNewProjectModal() {
297229
297855
  });
297230
297856
  }
297231
297857
  function closeNewProjectModal() {
297232
- if (!_handle4 || _creating || isImportRunning()) {
297858
+ if (!_handle5 || _creating || isImportRunning()) {
297233
297859
  return;
297234
297860
  }
297235
- _handle4.close();
297236
- _handle4 = null;
297861
+ _handle5.close();
297862
+ _handle5 = null;
297237
297863
  if (_resolve) {
297238
297864
  _resolve(null);
297239
297865
  _resolve = null;
@@ -297241,16 +297867,16 @@ function closeNewProjectModal() {
297241
297867
  }
297242
297868
  function finish(result) {
297243
297869
  _creating = false;
297244
- if (_handle4) {
297245
- _handle4.close();
297246
- _handle4 = null;
297870
+ if (_handle5) {
297871
+ _handle5.close();
297872
+ _handle5 = null;
297247
297873
  }
297248
297874
  if (_resolve) {
297249
297875
  _resolve(result);
297250
297876
  _resolve = null;
297251
297877
  }
297252
297878
  }
297253
- function deriveSlug(name) {
297879
+ function deriveSlug2(name) {
297254
297880
  return name.toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/^-|-$/g, "");
297255
297881
  }
297256
297882
  function sourceLabel() {
@@ -297273,17 +297899,17 @@ function renderModal3() {
297273
297899
  const platform4 = getPlatform();
297274
297900
  const importCtx = {
297275
297901
  credsForm: credsForm(),
297276
- form: _form,
297902
+ form: _form2,
297277
297903
  onDone: finish,
297278
297904
  rerender: renderModal3
297279
297905
  };
297280
297906
  const onInput2 = (field) => (e20) => {
297281
- _form[field] = e20.target.value;
297282
- if (field === "name" && !_form.directory) {
297907
+ _form2[field] = e20.target.value;
297908
+ if (field === "name" && !_form2.directory) {
297283
297909
  _dirDerived = true;
297284
297910
  }
297285
297911
  if (_dirDerived && field === "name") {
297286
- _form.directory = deriveSlug(_form.name);
297912
+ _form2.directory = deriveSlug2(_form2.name);
297287
297913
  }
297288
297914
  if (field === "directory") {
297289
297915
  _dirDerived = false;
@@ -297291,7 +297917,7 @@ function renderModal3() {
297291
297917
  renderModal3();
297292
297918
  };
297293
297919
  const onAdapterChange = (e20) => {
297294
- _form.adapter = e20.target.value;
297920
+ _form2.adapter = e20.target.value;
297295
297921
  renderModal3();
297296
297922
  };
297297
297923
  const selectTemplate = (id) => {
@@ -297307,12 +297933,12 @@ function renderModal3() {
297307
297933
  return;
297308
297934
  }
297309
297935
  _tab = e20.target.selected;
297310
- _error = "";
297936
+ _error2 = "";
297311
297937
  renderModal3();
297312
297938
  };
297313
297939
  const goNext = () => {
297314
297940
  if (_tab === "starter" && !_starter) {
297315
- _error = "Choose a starter site";
297941
+ _error2 = "Choose a starter site";
297316
297942
  renderModal3();
297317
297943
  return;
297318
297944
  }
@@ -297320,7 +297946,7 @@ function renderModal3() {
297320
297946
  return;
297321
297947
  }
297322
297948
  if (_tab === "agent" && !_agentPrompt.trim()) {
297323
- _error = "Describe the site you want the agent to build";
297949
+ _error2 = "Describe the site you want the agent to build";
297324
297950
  renderModal3();
297325
297951
  return;
297326
297952
  }
@@ -297329,8 +297955,8 @@ function renderModal3() {
297329
297955
  _paramsSeededFor = seedKey;
297330
297956
  if (_tab === "starter") {
297331
297957
  const meta = _starters.find((s2) => s2.id === _starter);
297332
- if (meta && !_form.description.trim()) {
297333
- _form.description = meta.tagline;
297958
+ if (meta && !_form2.description.trim()) {
297959
+ _form2.description = meta.tagline;
297334
297960
  }
297335
297961
  resetDesignFields({
297336
297962
  ...meta?.accent ? { accent: meta.accent } : {},
@@ -297343,7 +297969,7 @@ function renderModal3() {
297343
297969
  }
297344
297970
  }
297345
297971
  _step = "params";
297346
- _error = "";
297972
+ _error2 = "";
297347
297973
  renderModal3();
297348
297974
  };
297349
297975
  const goBack = () => {
@@ -297351,51 +297977,51 @@ function renderModal3() {
297351
297977
  return;
297352
297978
  }
297353
297979
  _step = "source";
297354
- _error = "";
297980
+ _error2 = "";
297355
297981
  renderModal3();
297356
297982
  };
297357
297983
  const onSubmit = async () => {
297358
- if (!_form.name.trim()) {
297359
- _error = "Project name is required";
297984
+ if (!_form2.name.trim()) {
297985
+ _error2 = "Project name is required";
297360
297986
  renderModal3();
297361
297987
  return;
297362
297988
  }
297363
- if (!_form.directory.trim()) {
297364
- _form.directory = deriveSlug(_form.name);
297989
+ if (!_form2.directory.trim()) {
297990
+ _form2.directory = deriveSlug2(_form2.name);
297365
297991
  }
297366
297992
  _creating = true;
297367
- _error = "";
297993
+ _error2 = "";
297368
297994
  renderModal3();
297369
297995
  try {
297370
297996
  const design = collectDesign();
297371
297997
  const result = await getPlatform().createProject({
297372
- ..._form,
297998
+ ..._form2,
297373
297999
  ..._tab === "starter" && _starter ? { starter: _starter } : { template: _template },
297374
298000
  ...design ? { design } : {}
297375
298001
  });
297376
298002
  finish(result);
297377
298003
  } catch (error) {
297378
298004
  _creating = false;
297379
- _error = errorMessage(error);
298005
+ _error2 = errorMessage(error);
297380
298006
  renderModal3();
297381
298007
  }
297382
298008
  };
297383
298009
  const onAgentSubmit = async () => {
297384
- if (!_form.name.trim()) {
297385
- _error = "Project name is required";
298010
+ if (!_form2.name.trim()) {
298011
+ _error2 = "Project name is required";
297386
298012
  renderModal3();
297387
298013
  return;
297388
298014
  }
297389
- if (!_form.directory.trim()) {
297390
- _form.directory = deriveSlug(_form.name);
298015
+ if (!_form2.directory.trim()) {
298016
+ _form2.directory = deriveSlug2(_form2.name);
297391
298017
  }
297392
298018
  _creating = true;
297393
- _error = "";
298019
+ _error2 = "";
297394
298020
  renderModal3();
297395
298021
  try {
297396
298022
  const design = collectDesign();
297397
298023
  const result = await getPlatform().createProject({
297398
- ..._form,
298024
+ ..._form2,
297399
298025
  template: "blank",
297400
298026
  ...design ? { design } : {}
297401
298027
  });
@@ -297403,7 +298029,7 @@ function renderModal3() {
297403
298029
  finish(result);
297404
298030
  } catch (error) {
297405
298031
  _creating = false;
297406
- _error = errorMessage(error);
298032
+ _error2 = errorMessage(error);
297407
298033
  renderModal3();
297408
298034
  }
297409
298035
  };
@@ -297493,7 +298119,7 @@ function renderModal3() {
297493
298119
  <span class="new-project-label">Project Name *</span>
297494
298120
  <sp-textfield
297495
298121
  placeholder="My Site"
297496
- .value=${_form.name}
298122
+ .value=${_form2.name}
297497
298123
  @input=${onInput2("name")}
297498
298124
  style="width: 100%"
297499
298125
  ></sp-textfield>
@@ -297503,7 +298129,7 @@ function renderModal3() {
297503
298129
  <span class="new-project-label">Directory</span>
297504
298130
  <sp-textfield
297505
298131
  placeholder="my-site"
297506
- .value=${_form.directory}
298132
+ .value=${_form2.directory}
297507
298133
  @input=${onInput2("directory")}
297508
298134
  style="width: 100%"
297509
298135
  ></sp-textfield>
@@ -297518,7 +298144,7 @@ function renderModal3() {
297518
298144
  <span class="new-project-label">Description</span>
297519
298145
  <sp-textfield
297520
298146
  placeholder="A short description of the site"
297521
- .value=${_form.description}
298147
+ .value=${_form2.description}
297522
298148
  @input=${onInput2("description")}
297523
298149
  style="width: 100%"
297524
298150
  ></sp-textfield>
@@ -297528,7 +298154,7 @@ function renderModal3() {
297528
298154
  <span class="new-project-label">Production URL</span>
297529
298155
  <sp-textfield
297530
298156
  placeholder="https://example.com"
297531
- .value=${_form.url}
298157
+ .value=${_form2.url}
297532
298158
  @input=${onInput2("url")}
297533
298159
  style="width: 100%"
297534
298160
  ></sp-textfield>
@@ -297536,7 +298162,7 @@ function renderModal3() {
297536
298162
 
297537
298163
  <label class="new-project-field">
297538
298164
  <span class="new-project-label">Deployment Adapter</span>
297539
- <sp-picker label="Adapter" .value=${_form.adapter} @change=${onAdapterChange}>
298165
+ <sp-picker label="Adapter" .value=${_form2.adapter} @change=${onAdapterChange}>
297540
298166
  <sp-menu-item value="static">Static</sp-menu-item>
297541
298167
  <sp-menu-item value="cloudflare-pages">Cloudflare Pages</sp-menu-item>
297542
298168
  <sp-menu-item value="node">Node</sp-menu-item>
@@ -297580,7 +298206,7 @@ function renderModal3() {
297580
298206
  ${primary}
297581
298207
  `;
297582
298208
  };
297583
- const bodyTpl = () => {
298209
+ const bodyTpl2 = () => {
297584
298210
  if (isImportRunning()) {
297585
298211
  return renderImportProgress();
297586
298212
  }
@@ -297613,16 +298239,16 @@ function renderModal3() {
297613
298239
  </div>
297614
298240
  ` : ""}
297615
298241
  <div class="new-project-modal-body">
297616
- ${bodyTpl()}
297617
- ${_tab !== "import" && _error ? html3`<div class="new-project-error">${_error}</div>` : ""}
298242
+ ${bodyTpl2()}
298243
+ ${_tab !== "import" && _error2 ? html3`<div class="new-project-error">${_error2}</div>` : ""}
297618
298244
  </div>
297619
298245
  <div class="new-project-modal-footer">${footerTpl()}</div>
297620
298246
  </div>
297621
298247
  `;
297622
- if (!_handle4) {
297623
- _handle4 = openModal(tpl);
298248
+ if (!_handle5) {
298249
+ _handle5 = openModal(tpl);
297624
298250
  } else {
297625
- _handle4.update(tpl);
298251
+ _handle5.update(tpl);
297626
298252
  }
297627
298253
  }
297628
298254
  var _dirDerived = true;
@@ -297677,11 +298303,11 @@ function mount4(rootEl, ctx) {
297677
298303
  tab.history.index;
297678
298304
  tab.history.snapshots.length;
297679
298305
  }
297680
- render6();
298306
+ render7();
297681
298307
  });
297682
298308
  });
297683
298309
  }
297684
- function render6() {
298310
+ function render7() {
297685
298311
  if (!_rootEl || !_ctx9) {
297686
298312
  return;
297687
298313
  }
@@ -297712,7 +298338,7 @@ function recentMenuTpl(ctx) {
297712
298338
  handleNewProject();
297713
298339
  } else if (val === "__clear__") {
297714
298340
  clearRecentProjects();
297715
- render6();
298341
+ render7();
297716
298342
  } else {
297717
298343
  ctx.openRecentProject(val);
297718
298344
  }
@@ -297732,7 +298358,7 @@ function recentMenuTpl(ctx) {
297732
298358
  @click=${(e20) => {
297733
298359
  e20.stopPropagation();
297734
298360
  removeRecentProject(p2.root);
297735
- render6();
298361
+ render7();
297736
298362
  }}
297737
298363
  >
297738
298364
  <sp-icon-close slot="icon"></sp-icon-close>
@@ -297829,7 +298455,7 @@ function minimalToolbarTemplate(ctx) {
297829
298455
  @click=${() => {
297830
298456
  view.rightPanelCollapsed = !view.rightPanelCollapsed;
297831
298457
  applyPanelCollapse();
297832
- render6();
298458
+ render7();
297833
298459
  }}
297834
298460
  >
297835
298461
  ${view.rightPanelCollapsed ? html3`<sp-icon-rail-right-open slot="icon"></sp-icon-rail-right-open>` : html3`<sp-icon-rail-right-close slot="icon"></sp-icon-rail-right-close>`}
@@ -297980,6 +298606,7 @@ function toolbarTemplate() {
297980
298606
  ${recentProjectsTpl}
297981
298607
  </div>
297982
298608
  ${tbBtnTpl("Manage", openBrowseModal, "sp-icon-view-list")}
298609
+ ${tbBtnTpl("Publish", openPublishPanel)}
297983
298610
  <sp-action-button size="s" title="Save" ?disabled=${!canSave} @click=${ctx.saveFile}>
297984
298611
  ${toolbarIconMap["sp-icon-save-floppy"]}<span class="tb-label">Save</span>
297985
298612
  </sp-action-button>
@@ -298032,7 +298659,7 @@ function toolbarTemplate() {
298032
298659
  @click=${() => {
298033
298660
  view.rightPanelCollapsed = !view.rightPanelCollapsed;
298034
298661
  applyPanelCollapse();
298035
- render6();
298662
+ render7();
298036
298663
  }}
298037
298664
  >
298038
298665
  ${view.rightPanelCollapsed ? html3`<sp-icon-rail-right-open slot="icon"></sp-icon-rail-right-open>` : html3`<sp-icon-rail-right-close slot="icon"></sp-icon-rail-right-close>`}
@@ -298064,7 +298691,7 @@ function isTextInput(el) {
298064
298691
  return false;
298065
298692
  }
298066
298693
  function createPanelScheduler(opts) {
298067
- const { root: root2, render: render7, blockWhile } = opts;
298694
+ const { root: root2, render: render8, blockWhile } = opts;
298068
298695
  let editing = false;
298069
298696
  let scheduled = false;
298070
298697
  let pending = false;
@@ -298084,7 +298711,7 @@ function createPanelScheduler(opts) {
298084
298711
  pending = false;
298085
298712
  rendering = true;
298086
298713
  try {
298087
- render7();
298714
+ render8();
298088
298715
  } finally {
298089
298716
  rendering = false;
298090
298717
  }
@@ -308851,14 +309478,14 @@ function emphasis(node, _, state3, info) {
308851
309478
  between = encodeCharacterReference(betweenHead) + between.slice(1);
308852
309479
  }
308853
309480
  const betweenTail = between.charCodeAt(between.length - 1);
308854
- const close = encodeInfo(info.after.charCodeAt(0), betweenTail, marker2);
308855
- if (close.inside) {
309481
+ const close2 = encodeInfo(info.after.charCodeAt(0), betweenTail, marker2);
309482
+ if (close2.inside) {
308856
309483
  between = between.slice(0, -1) + encodeCharacterReference(betweenTail);
308857
309484
  }
308858
309485
  const after2 = tracker.move(marker2);
308859
309486
  exit();
308860
309487
  state3.attentionEncodeSurroundingInfo = {
308861
- after: close.outside,
309488
+ after: close2.outside,
308862
309489
  before: open2.outside
308863
309490
  };
308864
309491
  return before + between + after2;
@@ -309460,14 +310087,14 @@ function strong(node2, _, state3, info) {
309460
310087
  between = encodeCharacterReference(betweenHead) + between.slice(1);
309461
310088
  }
309462
310089
  const betweenTail = between.charCodeAt(between.length - 1);
309463
- const close = encodeInfo(info.after.charCodeAt(0), betweenTail, marker2);
309464
- if (close.inside) {
310090
+ const close2 = encodeInfo(info.after.charCodeAt(0), betweenTail, marker2);
310091
+ if (close2.inside) {
309465
310092
  between = between.slice(0, -1) + encodeCharacterReference(betweenTail);
309466
310093
  }
309467
310094
  const after2 = tracker.move(marker2 + marker2);
309468
310095
  exit();
309469
310096
  state3.attentionEncodeSurroundingInfo = {
309470
- after: close.outside,
310097
+ after: close2.outside,
309471
310098
  before: open2.outside
309472
310099
  };
309473
310100
  return before + between + after2;
@@ -310323,9 +310950,9 @@ function tokenizeAttention(effects, ok4) {
310323
310950
  const after2 = classifyCharacter(code3);
310324
310951
  ok2(attentionMarkers, "expected `attentionMarkers` to be populated");
310325
310952
  const open2 = !after2 || after2 === constants2.characterGroupPunctuation && before || attentionMarkers.includes(code3);
310326
- const close = !before || before === constants2.characterGroupPunctuation && after2 || attentionMarkers.includes(previous2);
310327
- token._open = Boolean(marker2 === codes.asterisk ? open2 : open2 && (before || !close));
310328
- token._close = Boolean(marker2 === codes.asterisk ? close : close && (after2 || !open2));
310953
+ const close2 = !before || before === constants2.characterGroupPunctuation && after2 || attentionMarkers.includes(previous2);
310954
+ token._open = Boolean(marker2 === codes.asterisk ? open2 : open2 && (before || !close2));
310955
+ token._close = Boolean(marker2 === codes.asterisk ? close2 : close2 && (after2 || !open2));
310329
310956
  return ok4(code3);
310330
310957
  }
310331
310958
  }
@@ -312499,7 +313126,7 @@ function resolveToLabelEnd(events, context) {
312499
313126
  let offset4 = 0;
312500
313127
  let token;
312501
313128
  let open2;
312502
- let close;
313129
+ let close2;
312503
313130
  let media;
312504
313131
  while (index2--) {
312505
313132
  token = events[index2][1];
@@ -312510,7 +313137,7 @@ function resolveToLabelEnd(events, context) {
312510
313137
  if (events[index2][0] === "enter" && token.type === types.labelLink) {
312511
313138
  token._inactive = true;
312512
313139
  }
312513
- } else if (close) {
313140
+ } else if (close2) {
312514
313141
  if (events[index2][0] === "enter" && (token.type === types.labelImage || token.type === types.labelLink) && !token._balanced) {
312515
313142
  open2 = index2;
312516
313143
  if (token.type !== types.labelLink) {
@@ -312519,11 +313146,11 @@ function resolveToLabelEnd(events, context) {
312519
313146
  }
312520
313147
  }
312521
313148
  } else if (token.type === types.labelEnd) {
312522
- close = index2;
313149
+ close2 = index2;
312523
313150
  }
312524
313151
  }
312525
313152
  ok2(open2 !== undefined, "`open` is supposed to be found");
312526
- ok2(close !== undefined, "`close` is supposed to be found");
313153
+ ok2(close2 !== undefined, "`close` is supposed to be found");
312527
313154
  const group = {
312528
313155
  type: events[open2][1].type === types.labelLink ? types.link : types.image,
312529
313156
  start: { ...events[open2][1].start },
@@ -312532,12 +313159,12 @@ function resolveToLabelEnd(events, context) {
312532
313159
  const label = {
312533
313160
  type: types.label,
312534
313161
  start: { ...events[open2][1].start },
312535
- end: { ...events[close][1].end }
313162
+ end: { ...events[close2][1].end }
312536
313163
  };
312537
313164
  const text6 = {
312538
313165
  type: types.labelText,
312539
313166
  start: { ...events[open2 + offset4 + 2][1].end },
312540
- end: { ...events[close - 2][1].start }
313167
+ end: { ...events[close2 - 2][1].start }
312541
313168
  };
312542
313169
  media = [
312543
313170
  ["enter", group, context],
@@ -312546,14 +313173,14 @@ function resolveToLabelEnd(events, context) {
312546
313173
  media = push(media, events.slice(open2 + 1, open2 + offset4 + 3));
312547
313174
  media = push(media, [["enter", text6, context]]);
312548
313175
  ok2(context.parser.constructs.insideSpan.null, "expected `insideSpan.null` to be populated");
312549
- media = push(media, resolveAll(context.parser.constructs.insideSpan.null, events.slice(open2 + offset4 + 4, close - 3), context));
313176
+ media = push(media, resolveAll(context.parser.constructs.insideSpan.null, events.slice(open2 + offset4 + 4, close2 - 3), context));
312550
313177
  media = push(media, [
312551
313178
  ["exit", text6, context],
312552
- events[close - 2],
312553
- events[close - 1],
313179
+ events[close2 - 2],
313180
+ events[close2 - 1],
312554
313181
  ["exit", label, context]
312555
313182
  ]);
312556
- media = push(media, events.slice(close + 1));
313183
+ media = push(media, events.slice(close2 + 1));
312557
313184
  media = push(media, [["exit", group, context]]);
312558
313185
  splice3(events, open2, events.length, media);
312559
313186
  return events;
@@ -313871,17 +314498,17 @@ function tokenizeTasklistCheck(effects, ok4, nok) {
313871
314498
  effects.enter("taskListCheckValueUnchecked");
313872
314499
  effects.consume(code3);
313873
314500
  effects.exit("taskListCheckValueUnchecked");
313874
- return close;
314501
+ return close2;
313875
314502
  }
313876
314503
  if (code3 === codes.uppercaseX || code3 === codes.lowercaseX) {
313877
314504
  effects.enter("taskListCheckValueChecked");
313878
314505
  effects.consume(code3);
313879
314506
  effects.exit("taskListCheckValueChecked");
313880
- return close;
314507
+ return close2;
313881
314508
  }
313882
314509
  return nok(code3);
313883
314510
  }
313884
- function close(code3) {
314511
+ function close2(code3) {
313885
314512
  if (code3 === codes.rightSquareBracket) {
313886
314513
  effects.enter("taskListCheckMarker");
313887
314514
  effects.consume(code3);
@@ -314451,7 +315078,7 @@ function createTokenizer(parser, initialize2, from) {
314451
315078
  previous: codes.eof,
314452
315079
  sliceSerialize,
314453
315080
  sliceStream,
314454
- write
315081
+ write: write2
314455
315082
  };
314456
315083
  let state3 = initialize2.tokenize.call(context, effects);
314457
315084
  let expectedCode;
@@ -314459,7 +315086,7 @@ function createTokenizer(parser, initialize2, from) {
314459
315086
  resolveAllConstructs.push(initialize2);
314460
315087
  }
314461
315088
  return context;
314462
- function write(slice) {
315089
+ function write2(slice) {
314463
315090
  chunks = push(chunks, slice);
314464
315091
  main();
314465
315092
  if (chunks[chunks.length - 1] !== codes.eof) {
@@ -315133,8 +315760,8 @@ function compiler(options) {
315133
315760
  };
315134
315761
  }
315135
315762
  function closer(and) {
315136
- return close;
315137
- function close(token) {
315763
+ return close2;
315764
+ function close2(token) {
315138
315765
  if (and)
315139
315766
  and.call(this, token);
315140
315767
  exit3.call(this, token);
@@ -316795,17 +317422,17 @@ function markdownToHtml(markdown) {
316795
317422
  }
316796
317423
 
316797
317424
  // src/panels/ai-chat/chat-markdown.ts
316798
- var cache3 = new Map;
317425
+ var cache4 = new Map;
316799
317426
  function renderMarkdown3(id, content3) {
316800
- let entry = cache3.get(id);
317427
+ let entry = cache4.get(id);
316801
317428
  if (!entry || entry.len !== content3.length) {
316802
317429
  entry = { len: content3.length, html: markdownToHtml(content3) };
316803
- cache3.set(id, entry);
317430
+ cache4.set(id, entry);
316804
317431
  }
316805
317432
  return html3`<div class="ai-msg-md">${unsafeHTML(entry.html)}</div>`;
316806
317433
  }
316807
317434
  function clearMarkdownCache() {
316808
- cache3.clear();
317435
+ cache4.clear();
316809
317436
  }
316810
317437
 
316811
317438
  // src/panels/ai-chat/chat-view.ts
@@ -317172,7 +317799,7 @@ function createComposer(opts) {
317172
317799
  function focus() {
317173
317800
  textareaEl?.focus();
317174
317801
  }
317175
- function render7() {
317802
+ function render8() {
317176
317803
  const streaming = opts.isStreaming();
317177
317804
  return html3`
317178
317805
  <div class="ai-composer">
@@ -317212,7 +317839,7 @@ function createComposer(opts) {
317212
317839
  </div>
317213
317840
  `;
317214
317841
  }
317215
- return { clear, focus, render: render7 };
317842
+ return { clear, focus, render: render8 };
317216
317843
  }
317217
317844
 
317218
317845
  // src/panels/ai-chat/sessions-view.ts
@@ -317283,6 +317910,12 @@ function renderSessionsList(opts) {
317283
317910
  // src/panels/ai-panel.ts
317284
317911
  var mounted2 = false;
317285
317912
  var keyEditing = false;
317913
+ var proxyProbe = null;
317914
+ function ensureProxyProbe() {
317915
+ proxyProbe ??= fetchAvailableModels({ force: true }).catch(() => {}).then(() => {
317916
+ scheduleAiRender();
317917
+ });
317918
+ }
317286
317919
  var view2 = "chat";
317287
317920
  var assistant = createDocumentAssistant();
317288
317921
  globalThis.assistant = assistant;
@@ -317420,7 +318053,10 @@ var composer = createComposer({
317420
318053
  requestRender: scheduleAiRender
317421
318054
  });
317422
318055
  function renderAiPanelTemplate() {
317423
- if (!hasOpenAiKey() || keyEditing) {
318056
+ if (!hasOpenAiKey() && !isProxyConfigured() || keyEditing) {
318057
+ if (!keyEditing) {
318058
+ ensureProxyProbe();
318059
+ }
317424
318060
  return renderKeyGate();
317425
318061
  }
317426
318062
  if (view2 === "sessions") {
@@ -317486,11 +318122,11 @@ function mount5(ctx) {
317486
318122
  tab2.session.ui.styleFilter;
317487
318123
  tab2.session.ui.styleFilterActive;
317488
318124
  tab2.session.ui.inspectorSections;
317489
- render7();
318125
+ render8();
317490
318126
  });
317491
318127
  });
317492
318128
  }
317493
- function render7() {
318129
+ function render8() {
317494
318130
  _scheduler?.schedule();
317495
318131
  }
317496
318132
  var _propsContainer = null;
@@ -317549,7 +318185,7 @@ function _doRender() {
317549
318185
  const sel = e20.target.selected;
317550
318186
  if (sel && sel !== tab2) {
317551
318187
  updateUi("rightTab", sel);
317552
- render7();
318188
+ render8();
317553
318189
  }
317554
318190
  }}
317555
318191
  >
@@ -317849,11 +318485,11 @@ function mount6(ctx) {
317849
318485
  tab2.session.ui.gitLoading;
317850
318486
  tab2.session.ui.gitError;
317851
318487
  }
317852
- render8();
318488
+ render9();
317853
318489
  });
317854
318490
  });
317855
318491
  }
317856
- function render8() {
318492
+ function render9() {
317857
318493
  _scheduler2?.schedule();
317858
318494
  }
317859
318495
  function _doRender2() {
@@ -317897,7 +318533,7 @@ function _render() {
317897
318533
  if (tree) {
317898
318534
  ctx.setupTreeKeyboard(tree);
317899
318535
  }
317900
- ctx.registerFileTreeDnD({ renderLeftPanel: render8 });
318536
+ ctx.registerFileTreeDnD({ renderLeftPanel: render9 });
317901
318537
  return;
317902
318538
  }
317903
318539
  if (tab2 === "git") {
@@ -317909,7 +318545,7 @@ function _render() {
317909
318545
  if (tab2 === "blocks") {
317910
318546
  const content4 = renderElementsTemplate({
317911
318547
  defaultDef: ctx.defaultDef,
317912
- rerender: render8,
318548
+ rerender: render9,
317913
318549
  webdata: ctx.webdata
317914
318550
  });
317915
318551
  render2(html3`<div class="panel-body">${content4}</div>`, leftPanel);
@@ -317938,7 +318574,7 @@ function _render() {
317938
318574
  stylebookMeta: stylebook_meta_default
317939
318575
  }) : renderLayersTemplate({
317940
318576
  navigateToComponent: ctx.navigateToComponent,
317941
- rerender: render8
318577
+ rerender: render9
317942
318578
  });
317943
318579
  } else if (tab2 === "imports") {
317944
318580
  content3 = ctx.renderImportsTemplate({
@@ -317947,12 +318583,12 @@ function _render() {
317947
318583
  },
317948
318584
  documentElements: S.document.$elements || [],
317949
318585
  documentPath: S.documentPath,
317950
- renderLeftPanel: render8
318586
+ renderLeftPanel: render9
317951
318587
  });
317952
318588
  } else if (tab2 === "state") {
317953
318589
  content3 = ctx.renderSignalsTemplate(S, {
317954
318590
  renderCanvas: ctx.renderCanvas,
317955
- renderLeftPanel: render8,
318591
+ renderLeftPanel: render9,
317956
318592
  updateSession
317957
318593
  });
317958
318594
  } else if (tab2 === "data") {
@@ -317960,7 +318596,7 @@ function _render() {
317960
318596
  defBadgeLabel: ctx.defBadgeLabel,
317961
318597
  defCategory: ctx.defCategory,
317962
318598
  renderCanvas: ctx.renderCanvas,
317963
- renderLeftPanel: render8
318599
+ renderLeftPanel: render9
317964
318600
  });
317965
318601
  } else if (tab2 === "head") {
317966
318602
  const isContent = S.mode === "content";
@@ -317981,12 +318617,12 @@ function _render() {
317981
318617
  }
317982
318618
  const newHead = tmp.$head && tmp.$head.length > 0 ? tmp.$head : undefined;
317983
318619
  mutateUpdateFrontmatter(tabNow, "$head", newHead);
317984
- render8();
318620
+ render9();
317985
318621
  } : (fn) => {
317986
318622
  transact(activeTab.value, fn);
317987
318623
  },
317988
318624
  document: headDoc,
317989
- renderLeftPanel: render8
318625
+ renderLeftPanel: render9
317990
318626
  });
317991
318627
  } else {
317992
318628
  content3 = nothing;
@@ -318017,11 +318653,11 @@ function mount7(host) {
318017
318653
  tab2.doc.dirty;
318018
318654
  tab2.documentPath;
318019
318655
  }
318020
- render9();
318656
+ render10();
318021
318657
  });
318022
318658
  });
318023
318659
  }
318024
- function render9() {
318660
+ function render10() {
318025
318661
  if (!_host) {
318026
318662
  return;
318027
318663
  }
@@ -318120,11 +318756,11 @@ function mount8(host, ctx) {
318120
318756
  tab2.session.ui.previewParams;
318121
318757
  tab2.session.ui.showLayout;
318122
318758
  }
318123
- render10();
318759
+ render11();
318124
318760
  });
318125
318761
  });
318126
318762
  }
318127
- function render10() {
318763
+ function render11() {
318128
318764
  if (!_host2 || !_ctx12) {
318129
318765
  return;
318130
318766
  }
@@ -318277,7 +318913,7 @@ function paramValuesFor(tab2) {
318277
318913
  }
318278
318914
  _paramValues = values2;
318279
318915
  autoSelectParams(tab2, values2);
318280
- render10();
318916
+ render11();
318281
318917
  });
318282
318918
  return _paramValues;
318283
318919
  }
@@ -318516,6 +319152,7 @@ function registerCanvasDndBridge() {
318516
319152
 
318517
319153
  // src/studio.ts
318518
319154
  init_recent_projects();
319155
+ init_settings_store();
318519
319156
  function getCanvasMode() {
318520
319157
  const ui = activeTab.value?.session.ui;
318521
319158
  const base2 = ui?.canvasMode ?? "design";
@@ -318833,9 +319470,9 @@ mount6({
318833
319470
  setupTreeKeyboard,
318834
319471
  webdata: webdata_default
318835
319472
  });
318836
- registerRenderer("leftPanel", () => render8());
319473
+ registerRenderer("leftPanel", () => render9());
318837
319474
  registerRenderer("canvas", () => renderCanvas());
318838
- registerRenderer("rightPanel", () => render7());
319475
+ registerRenderer("rightPanel", () => render8());
318839
319476
  registerRenderer("overlays", () => render4());
318840
319477
  setStatusbarRenderer(() => renderStatusbar());
318841
319478
  mountStatusbar();
@@ -318850,7 +319487,7 @@ canvasWrap.addEventListener("click", (e20) => {
318850
319487
  activeTab.value.session.selection = null;
318851
319488
  });
318852
319489
  function safeRenderRightPanel() {
318853
- render7();
319490
+ render8();
318854
319491
  }
318855
319492
  registerFunctionCompletions();
318856
319493
  var fsUnsub = null;
@@ -318983,14 +319620,17 @@ if (_projectParam) {
318983
319620
  ensureFsSync();
318984
319621
  }
318985
319622
  hydrateRecentProjects().then(() => {
318986
- render6();
319623
+ render7();
319624
+ render();
319625
+ });
319626
+ hydrateProjectList().then(() => {
318987
319627
  render();
318988
319628
  });
318989
319629
  hydrateSettings().then(() => {
318990
319630
  render();
318991
319631
  });
318992
319632
  function renderLeftPanel() {
318993
- render8();
319633
+ render9();
318994
319634
  }
318995
319635
  function loadProject2() {
318996
319636
  return loadProject();
@@ -319063,7 +319703,7 @@ async function openRecentProject(root6) {
319063
319703
  maybePromptJxsuiteUpdate(root6);
319064
319704
  } catch (error) {
319065
319705
  removeRecentProject(root6);
319066
- render6();
319706
+ render7();
319067
319707
  render();
319068
319708
  statusMessage(`Error: ${errorMessage(error)}`);
319069
319709
  }
@@ -319120,5 +319760,5 @@ effect(() => {
319120
319760
  }
319121
319761
  });
319122
319762
 
319123
- //# debugId=C561D7C6126277AA64756E2164756E21
319763
+ //# debugId=DD8AF3657118F85C64756E2164756E21
319124
319764
  //# sourceMappingURL=studio.js.map